aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAndrew Rybchenko <arybchik@FreeBSD.org>2016-01-14 09:11:20 +0000
committerAndrew Rybchenko <arybchik@FreeBSD.org>2016-01-14 09:11:20 +0000
commit72cda83214f188a51643837d589ee8249329f586 (patch)
tree9b2187ce77d642f6b55b052a505c41872f1eb4f7 /sys
parentac23c34a9f2e82a2857dda1a61f646727d1c494d (diff)
downloadsrc-72cda83214f188a51643837d589ee8249329f586.tar.gz
src-72cda83214f188a51643837d589ee8249329f586.zip
sfxge: fix common code VPD iterator and duplicate tag verification
Fix efx_vpd_hunk_next() which has -- since its inception -- failed to correctly iterate over the tags and keywords contained in the VPD data. Only the first tag or keyword would be returned and the next call with *contp == 1 would walk to the end of the data and finish. This was spotted when fixing up errors spotted by Prefast code analysis (which neglected to set all of the out parameters in all successful cases) Also fix efx_vpd_verify() on Siena and EF10 which (as a side effect of correctly iterating over all the tags and keywords) was failing as it detected that both the static VPD and dynamic VPD storage contained an RV keyword in the VPD-R tag. This is intentional as the static VPD and dynamic VPD are stored separately (firmware merges their contents and computes a new RV keyword checksum for the data readable from the VPD capability in PCIe configuration space). Submitted by: Andrew Lee <alee at solarflare.com> Reviewed by: gnn Sponsored by: Solarflare Communications, Inc. MFC after: 2 days Differential Revision: https://reviews.freebsd.org/D4915
Notes
Notes: svn path=/head/; revision=293895
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/sfxge/common/efx_vpd.c19
-rw-r--r--sys/dev/sfxge/common/hunt_vpd.c7
-rw-r--r--sys/dev/sfxge/common/siena_vpd.c7
3 files changed, 25 insertions, 8 deletions
diff --git a/sys/dev/sfxge/common/efx_vpd.c b/sys/dev/sfxge/common/efx_vpd.c
index c1762e62193f..ebeddfea90f5 100644
--- a/sys/dev/sfxge/common/efx_vpd.c
+++ b/sys/dev/sfxge/common/efx_vpd.c
@@ -669,7 +669,7 @@ efx_vpd_hunk_next(
__in size_t size,
__out efx_vpd_tag_t *tagp,
__out efx_vpd_keyword_t *keywordp,
- __out_bcount_opt(*paylenp) unsigned int *payloadp,
+ __out_opt unsigned int *payloadp,
__out_opt uint8_t *paylenp,
__inout unsigned int *contp)
{
@@ -689,12 +689,18 @@ efx_vpd_hunk_next(
if ((rc = efx_vpd_next_tag(data, size, &offset,
&tag, &taglen)) != 0)
goto fail1;
- if (tag == EFX_VPD_END)
+
+ if (tag == EFX_VPD_END) {
+ keyword = 0;
+ paylen = 0;
+ index = 0;
break;
+ }
if (tag == EFX_VPD_ID) {
- if (index == *contp) {
+ if (index++ == *contp) {
EFSYS_ASSERT3U(taglen, <, 0x100);
+ keyword = 0;
paylen = (uint8_t)MIN(taglen, 0xff);
goto done;
@@ -705,7 +711,7 @@ efx_vpd_hunk_next(
taglen, pos, &keyword, &keylen)) != 0)
goto fail2;
- if (index == *contp) {
+ if (index++ == *contp) {
offset += pos + 3;
paylen = keylen;
@@ -717,9 +723,6 @@ efx_vpd_hunk_next(
offset += taglen;
}
- *contp = 0;
- return (0);
-
done:
*tagp = tag;
*keywordp = keyword;
@@ -728,7 +731,7 @@ done:
if (paylenp != NULL)
*paylenp = paylen;
- ++(*contp);
+ *contp = index;
return (0);
fail2:
diff --git a/sys/dev/sfxge/common/hunt_vpd.c b/sys/dev/sfxge/common/hunt_vpd.c
index 58e9a66ac712..6ada785e456d 100644
--- a/sys/dev/sfxge/common/hunt_vpd.c
+++ b/sys/dev/sfxge/common/hunt_vpd.c
@@ -210,6 +210,13 @@ ef10_vpd_verify(
if (dcont == 0)
break;
+ /*
+ * Skip the RV keyword. It should be present in both the static
+ * and dynamic cfg sectors.
+ */
+ if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))
+ continue;
+
scont = 0;
_NOTE(CONSTANTCONDITION)
while (1) {
diff --git a/sys/dev/sfxge/common/siena_vpd.c b/sys/dev/sfxge/common/siena_vpd.c
index 9a07f9130e00..7a7ce675ef56 100644
--- a/sys/dev/sfxge/common/siena_vpd.c
+++ b/sys/dev/sfxge/common/siena_vpd.c
@@ -326,6 +326,13 @@ siena_vpd_verify(
if (dcont == 0)
break;
+ /*
+ * Skip the RV keyword. It should be present in both the static
+ * and dynamic cfg sectors.
+ */
+ if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))
+ continue;
+
scont = 0;
_NOTE(CONSTANTCONDITION)
while (1) {