changeset 14091:d9da93cfe39c

3856 want FW config version number for igb and ixgbe Reviewed by: Dan McDonald <danmcd@nexenta.com> Reviewed by: Carlos Cardenas <carlos.cardenas@joyent.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Keith M Wesolowski <wesolows@foobazco.org>
date Sun, 30 Jun 2013 18:37:54 +0000
parents 613489527e1f
children d5286cdcaa9a
files exception_lists/cstyle usr/src/uts/common/io/igb/igb_api.c usr/src/uts/common/io/igb/igb_api.h usr/src/uts/common/io/igb/igb_defines.h usr/src/uts/common/io/igb/igb_main.c usr/src/uts/common/io/igb/igb_nvm.c usr/src/uts/common/io/igb/igb_nvm.h usr/src/uts/common/io/ixgbe/ixgbe_main.c
diffstat 8 files changed, 224 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/exception_lists/cstyle	Fri Jul 26 18:53:37 2013 -0700
+++ b/exception_lists/cstyle	Sun Jun 30 18:37:54 2013 +0000
@@ -655,6 +655,9 @@
 usr/src/uts/common/gssapi/mechs/krb5/mech/val_cred.c
 usr/src/uts/common/gssapi/mechs/krb5/mech/verify.c
 usr/src/uts/common/gssapi/mechs/krb5/mech/wrap_size_limit.c
+usr/src/uts/common/io/igb/igb_api.c
+usr/src/uts/common/io/igb/igb_nvm.c
+usr/src/uts/common/io/igb/igb_defines.h
 usr/src/uts/common/io/ixgbe/ixgbe_82598.c
 usr/src/uts/common/io/ixgbe/ixgbe_82598.h
 usr/src/uts/common/io/ixgbe/ixgbe_82599.c
--- a/usr/src/uts/common/io/igb/igb_api.c	Fri Jul 26 18:53:37 2013 -0700
+++ b/usr/src/uts/common/io/igb/igb_api.c	Sun Jun 30 18:37:54 2013 +0000
@@ -984,9 +984,10 @@
 }
 
 /*
- * e1000_read_pba_num - Read device part number
+ * e1000_read_pba_string - Read device part number string
  * @hw: pointer to the HW structure
  * @pba_num: pointer to device part number
+ * @pba_num_size: size of part number buffer
  *
  * Reads the product board assembly (PBA) number from the EEPROM and stores
  * the value in pba_num.
@@ -994,9 +995,24 @@
  * generic version of this function.
  */
 s32
-e1000_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
+e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size)
 {
-	return (e1000_read_pba_num_generic(hw, pba_num));
+	return (e1000_read_pba_string_generic(hw, pba_num, pba_num_size));
+}
+
+/*
+ * e1000_read_pba_length - Read device part number string length
+ * @hw: pointer to the HW structure
+ * @pba_num_size: size of part number buffer
+ *
+ * Reads the product board assembly (PBA) number length from the EEPROM and
+ * stores the value in pba_num.
+ * Currently no func pointer exists and all implementations are handled in the
+ * generic version of this function.
+ */
+s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size)
+{
+	return e1000_read_pba_length_generic(hw, pba_num_size);
 }
 
 /*
--- a/usr/src/uts/common/io/igb/igb_api.h	Fri Jul 26 18:53:37 2013 -0700
+++ b/usr/src/uts/common/io/igb/igb_api.h	Sun Jun 30 18:37:54 2013 +0000
@@ -87,7 +87,8 @@
 void e1000_power_up_phy(struct e1000_hw *hw);
 void e1000_power_down_phy(struct e1000_hw *hw);
 s32 e1000_read_mac_addr(struct e1000_hw *hw);
-s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *part_num);
+s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size);
+s32 e1000_read_pbe_length(struct e1000_hw *hw, u32 *pba_num_size);
 void e1000_reload_nvm(struct e1000_hw *hw);
 s32 e1000_update_nvm_checksum(struct e1000_hw *hw);
 s32 e1000_validate_nvm_checksum(struct e1000_hw *hw);
--- a/usr/src/uts/common/io/igb/igb_defines.h	Fri Jul 26 18:53:37 2013 -0700
+++ b/usr/src/uts/common/io/igb/igb_defines.h	Sun Jun 30 18:37:54 2013 +0000
@@ -946,6 +946,9 @@
 #define	E1000_ERR_SWFW_SYNC	13
 #define	E1000_NOT_IMPLEMENTED	14
 #define	E1000_ERR_MBX		15
+#define	E1000_ERR_INVALID_ARGUMENT	16
+#define	E1000_ERR_NO_SPACE		17
+#define	E1000_ERR_NVM_PBA_SECTION	18
 
 /* Loop limit on how long we wait for auto-negotiation to complete */
 #define	FIBER_LINK_UP_LIMIT	50
@@ -1230,8 +1233,11 @@
 #define	NVM_SUM				0xBABA
 
 #define	NVM_MAC_ADDR_OFFSET		0
+#define	NVM_OEM_OFFSET_0		6
+#define	NVM_OEM_OFFSET_1		7
 #define	NVM_PBA_OFFSET_0		8
 #define	NVM_PBA_OFFSET_1		9
+#define NVM_PBA_PTR_GUARD		0xFAFA
 #define	NVM_RESERVED_WORD		0xFFFF
 #define	NVM_PHY_CLASS_A			0x8000
 #define	NVM_SERDES_AMPLITUDE_MASK	0x000F
@@ -1240,6 +1246,8 @@
 #define	NVM_WORD_SIZE_BASE_SHIFT	6
 #define	NVM_SWDPIO_EXT_SHIFT		4
 
+#define	E1000_PBANUM_LENGTH		11
+
 /* NVM Commands - Microwire */
 #define	NVM_READ_OPCODE_MICROWIRE	0x6  /* NVM read opcode */
 #define	NVM_WRITE_OPCODE_MICROWIRE	0x5  /* NVM write opcode */
--- a/usr/src/uts/common/io/igb/igb_main.c	Fri Jul 26 18:53:37 2013 -0700
+++ b/usr/src/uts/common/io/igb/igb_main.c	Sun Jun 30 18:37:54 2013 +0000
@@ -1254,6 +1254,10 @@
 	struct e1000_hw *hw = &igb->hw;
 	uint32_t pba;
 	uint32_t high_water;
+	int oemid[2];
+	uint16_t nvmword;
+	u8 pbanum[E1000_PBANUM_LENGTH];
+	char eepromver[5];	/* f.ff */
 	int i;
 
 	ASSERT(mutex_owned(&igb->gen_lock));
@@ -1397,6 +1401,33 @@
 		E1000_WRITE_REG(hw, E1000_EITR(i), igb->intr_throttling[i]);
 
 	/*
+	 * Read identifying information and place in devinfo.
+	 */
+	nvmword = 0xffff;
+	(void) e1000_read_nvm(&igb->hw, NVM_OEM_OFFSET_0, 1, &nvmword);
+	oemid[0] = (int)nvmword;
+	(void) e1000_read_nvm(&igb->hw, NVM_OEM_OFFSET_1, 1, &nvmword);
+	oemid[1] = (int)nvmword;
+	(void) ddi_prop_update_int_array(DDI_DEV_T_NONE, igb->dip,
+	    "oem-identifier", oemid, 2);
+
+	pbanum[0] = '\0';
+	(void) e1000_read_pba_string(&igb->hw, pbanum, sizeof (pbanum));
+	if (*pbanum != '\0') {
+		(void) ddi_prop_update_string(DDI_DEV_T_NONE, igb->dip,
+		    "printed-board-assembly", (char *)pbanum);
+	}
+
+	nvmword = 0xffff;
+	(void) e1000_read_nvm(&igb->hw, NVM_VERSION, 1, &nvmword);
+	if ((nvmword & 0xf00) == 0) {
+		(void) snprintf(eepromver, sizeof (eepromver), "%x.%x",
+		    (nvmword & 0xf000) >> 12, (nvmword & 0xff));
+		(void) ddi_prop_update_string(DDI_DEV_T_NONE, igb->dip,
+		    "nvm-version", eepromver);
+	}
+
+	/*
 	 * Save the state of the phy
 	 */
 	igb_get_phy_state(igb);
--- a/usr/src/uts/common/io/igb/igb_nvm.c	Fri Jul 26 18:53:37 2013 -0700
+++ b/usr/src/uts/common/io/igb/igb_nvm.c	Sun Jun 30 18:37:54 2013 +0000
@@ -728,37 +728,172 @@
 }
 
 /*
- * e1000_read_pba_num_generic - Read device part number
+ * e1000_read_pba_string_generic - Read device part number
  * @hw: pointer to the HW structure
  * @pba_num: pointer to device part number
+ * @pba_num_size: size of part number buffer
  *
  * Reads the product board assembly (PBA) number from the EEPROM and stores
  * the value in pba_num.
  */
-s32
-e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num)
+s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+    u32 pba_num_size)
 {
-	s32  ret_val;
+	s32 ret_val;
 	u16 nvm_data;
+	u16 pba_ptr;
+	u16 offset;
+	u16 length;
 
-	DEBUGFUNC("e1000_read_pba_num_generic");
+	DEBUGFUNC("e1000_read_pba_string_generic");
+
+	if (pba_num == NULL) {
+		DEBUGOUT("PBA string buffer was null\n");
+		return (-E1000_ERR_INVALID_ARGUMENT);
+	}
 
 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
 	if (ret_val) {
 		DEBUGOUT("NVM Read Error\n");
-		goto out;
+		return (ret_val);
+	}
+
+	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error\n");
+		return (ret_val);
 	}
-	*pba_num = (u32)(nvm_data << 16);
+
+	/* if nvm_data is not ptr guard the PBA must be in legacy format which
+	 * means pba_ptr is actually our second data word for the PBA number
+	 * and we can decode it into an ascii string
+	 */
+	if (nvm_data != NVM_PBA_PTR_GUARD) {
+		DEBUGOUT("NVM PBA number is not stored as string\n");
+
+		/* make sure callers buffer is big enough to store the PBA */
+		if (pba_num_size < E1000_PBANUM_LENGTH) {
+			DEBUGOUT("PBA string buffer too small\n");
+			return (-E1000_ERR_NO_SPACE);
+		}
 
-	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
+		/* extract hex string from data and pba_ptr */
+		pba_num[0] = (nvm_data >> 12) & 0xF;
+		pba_num[1] = (nvm_data >> 8) & 0xF;
+		pba_num[2] = (nvm_data >> 4) & 0xF;
+		pba_num[3] = nvm_data & 0xF;
+		pba_num[4] = (pba_ptr >> 12) & 0xF;
+		pba_num[5] = (pba_ptr >> 8) & 0xF;
+		pba_num[6] = '-';
+		pba_num[7] = 0;
+		pba_num[8] = (pba_ptr >> 4) & 0xF;
+		pba_num[9] = pba_ptr & 0xF;
+
+		/* put a null character on the end of our string */
+		pba_num[10] = '\0';
+
+		/* switch all the data but the '-' to hex char */
+		for (offset = 0; offset < 10; offset++) {
+			if (pba_num[offset] < 0xA)
+				pba_num[offset] += '0';
+			else if (pba_num[offset] < 0x10)
+				pba_num[offset] += 'A' - 0xA;
+		}
+
+		return (E1000_SUCCESS);
+	}
+
+	ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
 	if (ret_val) {
 		DEBUGOUT("NVM Read Error\n");
-		goto out;
+		return (ret_val);
+	}
+
+	if (length == 0xFFFF || length == 0) {
+		DEBUGOUT("NVM PBA number section invalid length\n");
+		return (-E1000_ERR_NVM_PBA_SECTION);
+	}
+	/* check if pba_num buffer is big enough */
+	if (pba_num_size < (((u32)length * 2) - 1)) {
+		DEBUGOUT("PBA string buffer too small\n");
+		return (-E1000_ERR_NO_SPACE);
+	}
+
+	/* trim pba length from start of string */
+	pba_ptr++;
+	length--;
+
+	for (offset = 0; offset < length; offset++) {
+		ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
+		if (ret_val) {
+			DEBUGOUT("NVM Read Error\n");
+			return (ret_val);
+		}
+		pba_num[offset * 2] = (u8)(nvm_data >> 8);
+		pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
 	}
-	*pba_num |= nvm_data;
+	pba_num[offset * 2] = '\0';
+
+	return (E1000_SUCCESS);
+}
+
+/*
+ *  e1000_read_pba_length_generic - Read device part number length
+ *  @hw: pointer to the HW structure
+ *  @pba_num_size: size of part number buffer
+ *
+ *  Reads the product board assembly (PBA) number length from the EEPROM and
+ *  stores the value in pba_num_size.
+ */
+s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size)
+{
+	s32 ret_val;
+	u16 nvm_data;
+	u16 pba_ptr;
+	u16 length;
+
+	DEBUGFUNC("e1000_read_pba_length_generic");
+
+	if (pba_num_size == NULL) {
+		DEBUGOUT("PBA buffer size was null\n");
+		return (-E1000_ERR_INVALID_ARGUMENT);
+	}
 
-out:
-	return (ret_val);
+	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error\n");
+		return (ret_val);
+	}
+
+	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error\n");
+		return (ret_val);
+	}
+
+	 /* if data is not ptr guard the PBA must be in legacy format */
+	if (nvm_data != NVM_PBA_PTR_GUARD) {
+		*pba_num_size = E1000_PBANUM_LENGTH;
+		return (E1000_SUCCESS);
+	}
+
+	ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error\n");
+		return (ret_val);
+	}
+
+	if (length == 0xFFFF || length == 0) {
+		DEBUGOUT("NVM PBA number section invalid length\n");
+		return (-E1000_ERR_NVM_PBA_SECTION);
+	}
+
+	/* Convert from length in u16 values to u8 chars, add 1 for NULL,
+	 * and subtract 2 because length field is included in length.
+	 */
+	*pba_num_size = ((u32)length * 2) - 1;
+
+	return (E1000_SUCCESS);
 }
 
 /*
--- a/usr/src/uts/common/io/igb/igb_nvm.h	Fri Jul 26 18:53:37 2013 -0700
+++ b/usr/src/uts/common/io/igb/igb_nvm.h	Sun Jun 30 18:37:54 2013 +0000
@@ -45,7 +45,9 @@
 
 s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
 s32 e1000_read_mac_addr_generic(struct e1000_hw *hw);
-s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num);
+s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+    u32 pba_num_size);
+s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size);
 s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset,
     u16 words, u16 *data);
 s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words,
--- a/usr/src/uts/common/io/ixgbe/ixgbe_main.c	Fri Jul 26 18:53:37 2013 -0700
+++ b/usr/src/uts/common/io/ixgbe/ixgbe_main.c	Sun Jun 30 18:37:54 2013 +0000
@@ -1246,6 +1246,7 @@
 ixgbe_init(ixgbe_t *ixgbe)
 {
 	struct ixgbe_hw *hw = &ixgbe->hw;
+	u8 pbanum[IXGBE_PBANUM_LENGTH];
 
 	mutex_enter(&ixgbe->gen_lock);
 
@@ -1308,6 +1309,16 @@
 		goto init_fail;
 	}
 
+	/*
+	 * Read identifying information and place in devinfo.
+	 */
+	pbanum[0] = '\0';
+	(void) ixgbe_read_pba_string(hw, pbanum, sizeof (pbanum));
+	if (*pbanum != '\0') {
+		(void) ddi_prop_update_string(DDI_DEV_T_NONE, ixgbe->dip,
+		    "printed-board-assembly", (char *)pbanum);
+	}
+
 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
 		goto init_fail;
 	}