Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Mar 2016 07:48:56 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r296489 - in head/sys/dev/cxgbe: . common
Message-ID:  <201603080748.u287muuq070817@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Tue Mar  8 07:48:55 2016
New Revision: 296489
URL: https://svnweb.freebsd.org/changeset/base/296489

Log:
  cxgbe(4): Updates to the shared routines that deal with the serial EEPROM,
  flash, and VPD.
  
  Obtained from:	Chelsio Communications

Modified:
  head/sys/dev/cxgbe/adapter.h
  head/sys/dev/cxgbe/common/common.h
  head/sys/dev/cxgbe/common/t4_hw.c
  head/sys/dev/cxgbe/osdep.h
  head/sys/dev/cxgbe/t4_main.c

Modified: head/sys/dev/cxgbe/adapter.h
==============================================================================
--- head/sys/dev/cxgbe/adapter.h	Tue Mar  8 06:27:47 2016	(r296488)
+++ head/sys/dev/cxgbe/adapter.h	Tue Mar  8 07:48:55 2016	(r296489)
@@ -734,6 +734,8 @@ struct adapter {
 
 	unsigned int pf;
 	unsigned int mbox;
+	unsigned int vpd_busy;
+	unsigned int vpd_flag;
 
 	/* Interrupt information */
 	int intr_type;

Modified: head/sys/dev/cxgbe/common/common.h
==============================================================================
--- head/sys/dev/cxgbe/common/common.h	Tue Mar  8 06:27:47 2016	(r296488)
+++ head/sys/dev/cxgbe/common/common.h	Tue Mar  8 07:48:55 2016	(r296489)
@@ -499,20 +499,24 @@ int t4_eeprom_ptov(unsigned int phys_add
 int t4_seeprom_wp(struct adapter *adapter, int enable);
 int t4_read_flash(struct adapter *adapter, unsigned int addr, unsigned int nwords,
 		  u32 *data, int byte_oriented);
+int t4_write_flash(struct adapter *adapter, unsigned int addr,
+		   unsigned int n, const u8 *data, int byte_oriented);
 int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
+int t4_load_bootcfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
 int t4_load_boot(struct adapter *adap, u8 *boot_data,
                  unsigned int boot_addr, unsigned int size);
+int t4_flash_erase_sectors(struct adapter *adapter, int start, int end);
 int t4_flash_cfg_addr(struct adapter *adapter);
 int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
 int t4_get_fw_version(struct adapter *adapter, u32 *vers);
 int t4_get_tp_version(struct adapter *adapter, u32 *vers);
 int t4_check_fw_version(struct adapter *adapter);
 int t4_init_hw(struct adapter *adapter, u32 fw_params);
-int t4_prep_adapter(struct adapter *adapter);
+int t4_prep_adapter(struct adapter *adapter, u8 *buf);
 int t4_init_sge_params(struct adapter *adapter);
 int t4_init_tp_params(struct adapter *adap);
 int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
-int t4_port_init(struct port_info *p, int mbox, int pf, int vf);
+int t4_port_init(struct adapter *adap, int mbox, int pf, int vf, int port_id);
 void t4_fatal_err(struct adapter *adapter);
 void t4_db_full(struct adapter *adapter);
 void t4_db_dropped(struct adapter *adapter);
@@ -557,6 +561,7 @@ int t4_cim_read_la(struct adapter *adap,
 void t4_cim_read_pif_la(struct adapter *adap, u32 *pif_req, u32 *pif_rsp,
 		unsigned int *pif_req_wrptr, unsigned int *pif_rsp_wrptr);
 void t4_cim_read_ma_la(struct adapter *adap, u32 *ma_req, u32 *ma_rsp);
+int t4_get_flash_params(struct adapter *adapter);
 int t4_mc_read(struct adapter *adap, int idx, u32 addr,
 	       __be32 *data, u64 *parity);
 int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *parity);

Modified: head/sys/dev/cxgbe/common/t4_hw.c
==============================================================================
--- head/sys/dev/cxgbe/common/t4_hw.c	Tue Mar  8 06:27:47 2016	(r296488)
+++ head/sys/dev/cxgbe/common/t4_hw.c	Tue Mar  8 07:48:55 2016	(r296489)
@@ -2536,7 +2536,7 @@ void t4_get_regs(struct adapter *adap, u
 
 /*
  * Partial EEPROM Vital Product Data structure.  Includes only the ID and
- * VPD-R header.
+ * VPD-R sections.
  */
 struct t4_vpd_hdr {
 	u8  id_tag;
@@ -2549,14 +2549,65 @@ struct t4_vpd_hdr {
 /*
  * EEPROM reads take a few tens of us while writes can take a bit over 5 ms.
  */
-#define EEPROM_MAX_RD_POLL 40
-#define EEPROM_MAX_WR_POLL 6
-#define EEPROM_STAT_ADDR   0x7bfc
-#define VPD_BASE           0x400
-#define VPD_BASE_OLD       0
-#define VPD_LEN            1024
+#define EEPROM_DELAY		10		/* 10us per poll spin */
+#define EEPROM_MAX_POLL		5000		/* x 5000 == 50ms */
+
+#define EEPROM_STAT_ADDR	0x7bfc
+#define VPD_BASE		0x400
+#define VPD_BASE_OLD		0
+#define VPD_LEN			1024
 #define VPD_INFO_FLD_HDR_SIZE	3
-#define CHELSIO_VPD_UNIQUE_ID 0x82
+#define CHELSIO_VPD_UNIQUE_ID	0x82
+
+/*
+ * Small utility function to wait till any outstanding VPD Access is complete.
+ * We have a per-adapter state variable "VPD Busy" to indicate when we have a
+ * VPD Access in flight.  This allows us to handle the problem of having a
+ * previous VPD Access time out and prevent an attempt to inject a new VPD
+ * Request before any in-flight VPD reguest has completed.
+ */
+static int t4_seeprom_wait(struct adapter *adapter)
+{
+	unsigned int base = adapter->params.pci.vpd_cap_addr;
+	int max_poll;
+
+	/*
+	 * If no VPD Access is in flight, we can just return success right
+	 * away.
+	 */
+	if (!adapter->vpd_busy)
+		return 0;
+
+	/*
+	 * Poll the VPD Capability Address/Flag register waiting for it
+	 * to indicate that the operation is complete.
+	 */
+	max_poll = EEPROM_MAX_POLL;
+	do {
+		u16 val;
+
+		udelay(EEPROM_DELAY);
+		t4_os_pci_read_cfg2(adapter, base + PCI_VPD_ADDR, &val);
+
+		/*
+		 * If the operation is complete, mark the VPD as no longer
+		 * busy and return success.
+		 */
+		if ((val & PCI_VPD_ADDR_F) == adapter->vpd_flag) {
+			adapter->vpd_busy = 0;
+			return 0;
+		}
+	} while (--max_poll);
+
+	/*
+	 * Failure!  Note that we leave the VPD Busy status set in order to
+	 * avoid pushing a new VPD Access request into the VPD Capability till
+	 * the current operation eventually succeeds.  It's a bug to issue a
+	 * new request when an existing request is in flight and will result
+	 * in corrupt hardware state.
+	 */
+	return -ETIMEDOUT;
+}
 
 /**
  *	t4_seeprom_read - read a serial EEPROM location
@@ -2570,23 +2621,44 @@ struct t4_vpd_hdr {
  */
 int t4_seeprom_read(struct adapter *adapter, u32 addr, u32 *data)
 {
-	u16 val;
-	int attempts = EEPROM_MAX_RD_POLL;
 	unsigned int base = adapter->params.pci.vpd_cap_addr;
+	int ret;
 
+	/*
+	 * VPD Accesses must alway be 4-byte aligned!
+	 */
 	if (addr >= EEPROMVSIZE || (addr & 3))
 		return -EINVAL;
 
-	t4_os_pci_write_cfg2(adapter, base + PCI_VPD_ADDR, (u16)addr);
-	do {
-		udelay(10);
-		t4_os_pci_read_cfg2(adapter, base + PCI_VPD_ADDR, &val);
-	} while (!(val & PCI_VPD_ADDR_F) && --attempts);
+	/*
+	 * Wait for any previous operation which may still be in flight to
+	 * complete.
+	 */
+	ret = t4_seeprom_wait(adapter);
+	if (ret) {
+		CH_ERR(adapter, "VPD still busy from previous operation\n");
+		return ret;
+	}
 
-	if (!(val & PCI_VPD_ADDR_F)) {
-		CH_ERR(adapter, "reading EEPROM address 0x%x failed\n", addr);
-		return -EIO;
+	/*
+	 * Issue our new VPD Read request, mark the VPD as being busy and wait
+	 * for our request to complete.  If it doesn't complete, note the
+	 * error and return it to our caller.  Note that we do not reset the
+	 * VPD Busy status!
+	 */
+	t4_os_pci_write_cfg2(adapter, base + PCI_VPD_ADDR, (u16)addr);
+	adapter->vpd_busy = 1;
+	adapter->vpd_flag = PCI_VPD_ADDR_F;
+	ret = t4_seeprom_wait(adapter);
+	if (ret) {
+		CH_ERR(adapter, "VPD read of address %#x failed\n", addr);
+		return ret;
 	}
+
+	/*
+	 * Grab the returned data, swizzle it into our endianess and
+	 * return success.
+	 */
 	t4_os_pci_read_cfg4(adapter, base + PCI_VPD_DATA, data);
 	*data = le32_to_cpu(*data);
 	return 0;
@@ -2604,26 +2676,59 @@ int t4_seeprom_read(struct adapter *adap
  */
 int t4_seeprom_write(struct adapter *adapter, u32 addr, u32 data)
 {
-	u16 val;
-	int attempts = EEPROM_MAX_WR_POLL;
 	unsigned int base = adapter->params.pci.vpd_cap_addr;
+	int ret;
+	u32 stats_reg;
+	int max_poll;
 
+	/*
+	 * VPD Accesses must alway be 4-byte aligned!
+	 */
 	if (addr >= EEPROMVSIZE || (addr & 3))
 		return -EINVAL;
 
+	/*
+	 * Wait for any previous operation which may still be in flight to
+	 * complete.
+	 */
+	ret = t4_seeprom_wait(adapter);
+	if (ret) {
+		CH_ERR(adapter, "VPD still busy from previous operation\n");
+		return ret;
+	}
+
+	/*
+	 * Issue our new VPD Read request, mark the VPD as being busy and wait
+	 * for our request to complete.  If it doesn't complete, note the
+	 * error and return it to our caller.  Note that we do not reset the
+	 * VPD Busy status!
+	 */
 	t4_os_pci_write_cfg4(adapter, base + PCI_VPD_DATA,
 				 cpu_to_le32(data));
 	t4_os_pci_write_cfg2(adapter, base + PCI_VPD_ADDR,
 				 (u16)addr | PCI_VPD_ADDR_F);
+	adapter->vpd_busy = 1;
+	adapter->vpd_flag = 0;
+	ret = t4_seeprom_wait(adapter);
+	if (ret) {
+		CH_ERR(adapter, "VPD write of address %#x failed\n", addr);
+		return ret;
+	}
+
+	/*
+	 * Reset PCI_VPD_DATA register after a transaction and wait for our
+	 * request to complete. If it doesn't complete, return error.
+	 */
+	t4_os_pci_write_cfg4(adapter, base + PCI_VPD_DATA, 0);
+	max_poll = EEPROM_MAX_POLL;
 	do {
-		msleep(1);
-		t4_os_pci_read_cfg2(adapter, base + PCI_VPD_ADDR, &val);
-	} while ((val & PCI_VPD_ADDR_F) && --attempts);
+		udelay(EEPROM_DELAY);
+		t4_seeprom_read(adapter, EEPROM_STAT_ADDR, &stats_reg);
+	} while ((stats_reg & 0x1) && --max_poll);
+	if (!max_poll)
+		return -ETIMEDOUT;
 
-	if (val & PCI_VPD_ADDR_F) {
-		CH_ERR(adapter, "write to EEPROM address 0x%x failed\n", addr);
-		return -EIO;
-	}
+	/* Return success! */
 	return 0;
 }
 
@@ -2672,33 +2777,33 @@ int t4_seeprom_wp(struct adapter *adapte
  *	get_vpd_keyword_val - Locates an information field keyword in the VPD
  *	@v: Pointer to buffered vpd data structure
  *	@kw: The keyword to search for
- *	
+ *
  *	Returns the value of the information field keyword or
  *	-ENOENT otherwise.
  */
 static int get_vpd_keyword_val(const struct t4_vpd_hdr *v, const char *kw)
 {
-         int i;
-	 unsigned int offset , len;
-	 const u8 *buf = &v->id_tag;
-	 const u8 *vpdr_len = &v->vpdr_tag; 
-	 offset = sizeof(struct t4_vpd_hdr);
-	 len =  (u16)vpdr_len[1] + ((u16)vpdr_len[2] << 8);
-	 
-	 if (len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
-		 return -ENOENT;
-	 }
-
-         for (i = offset; i + VPD_INFO_FLD_HDR_SIZE <= offset + len;) {
-		 if(memcmp(buf + i , kw , 2) == 0){
-			 i += VPD_INFO_FLD_HDR_SIZE;
-                         return i;
-		  }
+	int i;
+	unsigned int offset , len;
+	const u8 *buf = (const u8 *)v;
+	const u8 *vpdr_len = &v->vpdr_len[0];
+	offset = sizeof(struct t4_vpd_hdr);
+	len =  (u16)vpdr_len[0] + ((u16)vpdr_len[1] << 8);
+
+	if (len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
+		return -ENOENT;
+	}
+
+	for (i = offset; i + VPD_INFO_FLD_HDR_SIZE <= offset + len;) {
+		if(memcmp(buf + i , kw , 2) == 0){
+			i += VPD_INFO_FLD_HDR_SIZE;
+			return i;
+		}
 
-                 i += VPD_INFO_FLD_HDR_SIZE + buf[i+2];
-         }
+		i += VPD_INFO_FLD_HDR_SIZE + buf[i+2];
+	}
 
-         return -ENOENT;
+	return -ENOENT;
 }
 
 
@@ -2706,14 +2811,16 @@ static int get_vpd_keyword_val(const str
  *	get_vpd_params - read VPD parameters from VPD EEPROM
  *	@adapter: adapter to read
  *	@p: where to store the parameters
+ *	@vpd: caller provided temporary space to read the VPD into
  *
  *	Reads card parameters stored in VPD EEPROM.
  */
-static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
+static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
+    u8 *vpd)
 {
 	int i, ret, addr;
 	int ec, sn, pn, na;
-	u8 vpd[VPD_LEN], csum;
+	u8 csum;
 	const struct t4_vpd_hdr *v;
 
 	/*
@@ -2721,31 +2828,43 @@ static int get_vpd_params(struct adapter
 	 * it at 0.
 	 */
 	ret = t4_seeprom_read(adapter, VPD_BASE, (u32 *)(vpd));
+	if (ret)
+		return (ret);
+
+	/*
+	 * The VPD shall have a unique identifier specified by the PCI SIG.
+	 * For chelsio adapters, the identifier is 0x82. The first byte of a VPD
+	 * shall be CHELSIO_VPD_UNIQUE_ID (0x82). The VPD programming software
+	 * is expected to automatically put this entry at the
+	 * beginning of the VPD.
+	 */
 	addr = *vpd == CHELSIO_VPD_UNIQUE_ID ? VPD_BASE : VPD_BASE_OLD;
 
-	for (i = 0; i < sizeof(vpd); i += 4) {
+	for (i = 0; i < VPD_LEN; i += 4) {
 		ret = t4_seeprom_read(adapter, addr + i, (u32 *)(vpd + i));
 		if (ret)
 			return ret;
 	}
  	v = (const struct t4_vpd_hdr *)vpd;
-	
+
 #define FIND_VPD_KW(var,name) do { \
 	var = get_vpd_keyword_val(v , name); \
 	if (var < 0) { \
 		CH_ERR(adapter, "missing VPD keyword " name "\n"); \
 		return -EINVAL; \
 	} \
-} while (0)	
+} while (0)
 
 	FIND_VPD_KW(i, "RV");
 	for (csum = 0; i >= 0; i--)
 		csum += vpd[i];
 
 	if (csum) {
-		CH_ERR(adapter, "corrupted VPD EEPROM, actual csum %u\n", csum);
+		CH_ERR(adapter,
+			"corrupted VPD EEPROM, actual csum %u\n", csum);
 		return -EINVAL;
 	}
+
 	FIND_VPD_KW(ec, "EC");
 	FIND_VPD_KW(sn, "SN");
 	FIND_VPD_KW(pn, "PN");
@@ -2771,16 +2890,16 @@ static int get_vpd_params(struct adapter
 
 /* serial flash and firmware constants and flash config file constants */
 enum {
-	SF_ATTEMPTS = 10,             /* max retries for SF operations */
+	SF_ATTEMPTS = 10,	/* max retries for SF operations */
 
 	/* flash command opcodes */
-	SF_PROG_PAGE    = 2,          /* program page */
-	SF_WR_DISABLE   = 4,          /* disable writes */
-	SF_RD_STATUS    = 5,          /* read status register */
-	SF_WR_ENABLE    = 6,          /* enable writes */
-	SF_RD_DATA_FAST = 0xb,        /* read flash */
-	SF_RD_ID        = 0x9f,       /* read ID */
-	SF_ERASE_SECTOR = 0xd8,       /* erase sector */
+	SF_PROG_PAGE    = 2,	/* program page */
+	SF_WR_DISABLE   = 4,	/* disable writes */
+	SF_RD_STATUS    = 5,	/* read status register */
+	SF_WR_ENABLE    = 6,	/* enable writes */
+	SF_RD_DATA_FAST = 0xb,	/* read flash */
+	SF_RD_ID	= 0x9f,	/* read ID */
+	SF_ERASE_SECTOR = 0xd8,	/* erase sector */
 };
 
 /**
@@ -2874,7 +2993,7 @@ static int flash_wait_op(struct adapter 
  *	Read the specified number of 32-bit words from the serial flash.
  *	If @byte_oriented is set the read data is stored as a byte array
  *	(i.e., big-endian), otherwise as 32-bit words in the platform's
- *	natural endianess.
+ *	natural endianness.
  */
 int t4_read_flash(struct adapter *adapter, unsigned int addr,
 		  unsigned int nwords, u32 *data, int byte_oriented)
@@ -2897,7 +3016,7 @@ int t4_read_flash(struct adapter *adapte
 		if (ret)
 			return ret;
 		if (byte_oriented)
-			*data = htonl(*data);
+			*data = (__force __u32)(cpu_to_be32(*data));
 	}
 	return 0;
 }
@@ -2912,10 +3031,10 @@ int t4_read_flash(struct adapter *adapte
  *
  *	Writes up to a page of data (256 bytes) to the serial flash starting
  *	at the given address.  All the data must be written to the same page.
- *	If @byte_oriented is set the write data is stored as byte stream 
+ *	If @byte_oriented is set the write data is stored as byte stream
  *	(i.e. matches what on disk), otherwise in big-endian.
  */
-static int t4_write_flash(struct adapter *adapter, unsigned int addr,
+int t4_write_flash(struct adapter *adapter, unsigned int addr,
 			  unsigned int n, const u8 *data, int byte_oriented)
 {
 	int ret;
@@ -2937,7 +3056,7 @@ static int t4_write_flash(struct adapter
 			val = (val << 8) + *data++;
 
 		if (!byte_oriented)
-			val = htonl(val);
+			val = cpu_to_be32(val);
 
 		ret = sf1_write(adapter, c, c != left, 1, val);
 		if (ret)
@@ -2956,8 +3075,9 @@ static int t4_write_flash(struct adapter
 		return ret;
 
 	if (memcmp(data - n, (u8 *)buf + offset, n)) {
-		CH_ERR(adapter, "failed to correctly write the flash page "
-		       "at %#x\n", addr);
+		CH_ERR(adapter,
+			"failed to correctly write the flash page at %#x\n",
+			addr);
 		return -EIO;
 	}
 	return 0;
@@ -3057,17 +3177,21 @@ int t4_check_fw_version(struct adapter *
  *
  *	Erases the sectors in the given inclusive range.
  */
-static int t4_flash_erase_sectors(struct adapter *adapter, int start, int end)
+int t4_flash_erase_sectors(struct adapter *adapter, int start, int end)
 {
 	int ret = 0;
 
+	if (end >= adapter->params.sf_nsec)
+		return -EINVAL;
+
 	while (start <= end) {
 		if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 ||
 		    (ret = sf1_write(adapter, 4, 0, 1,
 				     SF_ERASE_SECTOR | (start << 8))) != 0 ||
 		    (ret = flash_wait_op(adapter, 14, 500)) != 0) {
-			CH_ERR(adapter, "erase of flash sector %d failed, "
-			       "error %d\n", start, ret);
+			CH_ERR(adapter,
+				"erase of flash sector %d failed, error %d\n",
+				start, ret);
 			break;
 		}
 		start++;
@@ -3096,66 +3220,6 @@ int t4_flash_cfg_addr(struct adapter *ad
 	return FLASH_CFG_START;
 }
 
-/**
- *	t4_load_cfg - download config file
- *	@adap: the adapter
- *	@cfg_data: the cfg text file to write
- *	@size: text file size
- *
- *	Write the supplied config text file to the card's serial flash.
- */
-int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
-{
-	int ret, i, n, cfg_addr;
-	unsigned int addr;
-	unsigned int flash_cfg_start_sec;
-	unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
-
-	cfg_addr = t4_flash_cfg_addr(adap);
-	if (cfg_addr < 0)
-		return cfg_addr;
-
-	addr = cfg_addr;
-	flash_cfg_start_sec = addr / SF_SEC_SIZE;
-
-	if (size > FLASH_CFG_MAX_SIZE) {
-		CH_ERR(adap, "cfg file too large, max is %u bytes\n",
-		       FLASH_CFG_MAX_SIZE);
-		return -EFBIG;
-	}
-
-	i = DIV_ROUND_UP(FLASH_CFG_MAX_SIZE,	/* # of sectors spanned */
-			 sf_sec_size);
-	ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec,
-				     flash_cfg_start_sec + i - 1);
-	/*
-	 * If size == 0 then we're simply erasing the FLASH sectors associated
-	 * with the on-adapter Firmware Configuration File.
-	 */
-	if (ret || size == 0)
-		goto out;
-
-	/* this will write to the flash up to SF_PAGE_SIZE at a time */
-	for (i = 0; i< size; i+= SF_PAGE_SIZE) {
-		if ( (size - i) <  SF_PAGE_SIZE) 
-			n = size - i;
-		else 
-			n = SF_PAGE_SIZE;
-		ret = t4_write_flash(adap, addr, n, cfg_data, 1);
-		if (ret)
-			goto out;
-		
-		addr += SF_PAGE_SIZE;
-		cfg_data += SF_PAGE_SIZE;
-	} 
-                
-out:
-	if (ret)
-		CH_ERR(adap, "config file %s failed %d\n",
-		       (size == 0 ? "clear" : "download"), ret);
-	return ret;
-}
-
 
 /**
  *	t4_load_fw - download firmware
@@ -3254,341 +3318,64 @@ out:
 	return ret;
 }
 
-/* BIOS boot headers */
-typedef struct pci_expansion_rom_header {
-	u8	signature[2]; /* ROM Signature. Should be 0xaa55 */
-	u8	reserved[22]; /* Reserved per processor Architecture data */
-	u8	pcir_offset[2]; /* Offset to PCI Data Structure */
-} pci_exp_rom_header_t; /* PCI_EXPANSION_ROM_HEADER */
-
-/* Legacy PCI Expansion ROM Header */
-typedef struct legacy_pci_expansion_rom_header {
-	u8	signature[2]; /* ROM Signature. Should be 0xaa55 */
-	u8	size512; /* Current Image Size in units of 512 bytes */
-	u8	initentry_point[4];
-	u8	cksum; /* Checksum computed on the entire Image */
-	u8	reserved[16]; /* Reserved */
-	u8	pcir_offset[2]; /* Offset to PCI Data Struture */
-} legacy_pci_exp_rom_header_t; /* LEGACY_PCI_EXPANSION_ROM_HEADER */
-
-/* EFI PCI Expansion ROM Header */
-typedef struct efi_pci_expansion_rom_header {
-	u8	signature[2]; // ROM signature. The value 0xaa55
-	u8	initialization_size[2]; /* Units 512. Includes this header */
-	u8	efi_signature[4]; /* Signature from EFI image header. 0x0EF1 */
-	u8	efi_subsystem[2]; /* Subsystem value for EFI image header */
-	u8	efi_machine_type[2]; /* Machine type from EFI image header */
-	u8	compression_type[2]; /* Compression type. */
-		/* 
-		 * Compression type definition
-		 * 0x0: uncompressed
-		 * 0x1: Compressed
-		 * 0x2-0xFFFF: Reserved
-		 */
-	u8	reserved[8]; /* Reserved */
-	u8	efi_image_header_offset[2]; /* Offset to EFI Image */
-	u8	pcir_offset[2]; /* Offset to PCI Data Structure */
-} efi_pci_exp_rom_header_t; /* EFI PCI Expansion ROM Header */
-
-/* PCI Data Structure Format */
-typedef struct pcir_data_structure { /* PCI Data Structure */
-	u8	signature[4]; /* Signature. The string "PCIR" */
-	u8	vendor_id[2]; /* Vendor Identification */
-	u8	device_id[2]; /* Device Identification */
-	u8	vital_product[2]; /* Pointer to Vital Product Data */
-	u8	length[2]; /* PCIR Data Structure Length */
-	u8	revision; /* PCIR Data Structure Revision */
-	u8	class_code[3]; /* Class Code */
-	u8	image_length[2]; /* Image Length. Multiple of 512B */
-	u8	code_revision[2]; /* Revision Level of Code/Data */
-	u8	code_type; /* Code Type. */
-		/*
-		 * PCI Expansion ROM Code Types
-		 * 0x00: Intel IA-32, PC-AT compatible. Legacy
-		 * 0x01: Open Firmware standard for PCI. FCODE
-		 * 0x02: Hewlett-Packard PA RISC. HP reserved
-		 * 0x03: EFI Image. EFI
-		 * 0x04-0xFF: Reserved.
-		 */
-	u8	indicator; /* Indicator. Identifies the last image in the ROM */
-	u8	reserved[2]; /* Reserved */
-} pcir_data_t; /* PCI__DATA_STRUCTURE */
+/**
+ *	t4_read_cimq_cfg - read CIM queue configuration
+ *	@adap: the adapter
+ *	@base: holds the queue base addresses in bytes
+ *	@size: holds the queue sizes in bytes
+ *	@thres: holds the queue full thresholds in bytes
+ *
+ *	Returns the current configuration of the CIM queues, starting with
+ *	the IBQs, then the OBQs.
+ */
+void t4_read_cimq_cfg(struct adapter *adap, u16 *base, u16 *size, u16 *thres)
+{
+	unsigned int i, v;
 
-/* BOOT constants */
-enum {
-	BOOT_FLASH_BOOT_ADDR = 0x0,/* start address of boot image in flash */
-	BOOT_SIGNATURE = 0xaa55,   /* signature of BIOS boot ROM */
-	BOOT_SIZE_INC = 512,       /* image size measured in 512B chunks */
-	BOOT_MIN_SIZE = sizeof(pci_exp_rom_header_t), /* basic header */
-	BOOT_MAX_SIZE = 1024*BOOT_SIZE_INC, /* 1 byte * length increment  */
-	VENDOR_ID = 0x1425, /* Vendor ID */
-	PCIR_SIGNATURE = 0x52494350 /* PCIR signature */
-};
+	for (i = 0; i < CIM_NUM_IBQ; i++) {
+		t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_IBQSELECT |
+			     V_QUENUMSELECT(i));
+		v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
+		*base++ = G_CIMQBASE(v) * 256; /* value is in 256-byte units */
+		*size++ = G_CIMQSIZE(v) * 256; /* value is in 256-byte units */
+		*thres++ = G_QUEFULLTHRSH(v) * 8;   /* 8-byte unit */
+	}
+	for (i = 0; i < adap->chip_params->cim_num_obq; i++) {
+		t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
+			     V_QUENUMSELECT(i));
+		v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
+		*base++ = G_CIMQBASE(v) * 256; /* value is in 256-byte units */
+		*size++ = G_CIMQSIZE(v) * 256; /* value is in 256-byte units */
+	}
+}
 
-/*
- *	modify_device_id - Modifies the device ID of the Boot BIOS image 
- *	@adatper: the device ID to write.
- *	@boot_data: the boot image to modify.
+/**
+ *	t4_read_cim_ibq - read the contents of a CIM inbound queue
+ *	@adap: the adapter
+ *	@qid: the queue index
+ *	@data: where to store the queue contents
+ *	@n: capacity of @data in 32-bit words
  *
- *	Write the supplied device ID to the boot BIOS image.
+ *	Reads the contents of the selected CIM queue starting at address 0 up
+ *	to the capacity of @data.  @n must be a multiple of 4.  Returns < 0 on
+ *	error and the number of 32-bit words actually read on success.
  */
-static void modify_device_id(int device_id, u8 *boot_data)
+int t4_read_cim_ibq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
 {
-	legacy_pci_exp_rom_header_t *header;
-	pcir_data_t *pcir_header;
-	u32 cur_header = 0;
+	int i, err;
+	unsigned int addr;
+	const unsigned int nwords = CIM_IBQ_SIZE * 4;
 
-	/*
-	 * Loop through all chained images and change the device ID's
-	 */
-	while (1) {
-		header = (legacy_pci_exp_rom_header_t *) &boot_data[cur_header];
-		pcir_header = (pcir_data_t *) &boot_data[cur_header +
-		    le16_to_cpu(*(u16*)header->pcir_offset)];
+	if (qid > 5 || (n & 3))
+		return -EINVAL;
+
+	addr = qid * nwords;
+	if (n > nwords)
+		n = nwords;
 
-		/*
-		 * Only modify the Device ID if code type is Legacy or HP.
-		 * 0x00: Okay to modify
-		 * 0x01: FCODE. Do not be modify
-		 * 0x03: Okay to modify
-		 * 0x04-0xFF: Do not modify
-		 */
-		if (pcir_header->code_type == 0x00) {
-			u8 csum = 0;
-			int i;
-
-			/*
-			 * Modify Device ID to match current adatper
-			 */
-			*(u16*) pcir_header->device_id = device_id;
-
-			/*
-			 * Set checksum temporarily to 0.
-			 * We will recalculate it later.
-			 */
-			header->cksum = 0x0;
-
-			/*
-			 * Calculate and update checksum
-			 */
-			for (i = 0; i < (header->size512 * 512); i++)
-				csum += (u8)boot_data[cur_header + i];
-
-			/*
-			 * Invert summed value to create the checksum
-			 * Writing new checksum value directly to the boot data
-			 */
-			boot_data[cur_header + 7] = -csum;
-
-		} else if (pcir_header->code_type == 0x03) {
-
-			/*
-			 * Modify Device ID to match current adatper
-			 */
-			*(u16*) pcir_header->device_id = device_id;
-
-		}
-
-
-		/*
-		 * Check indicator element to identify if this is the last
-		 * image in the ROM.
-		 */
-		if (pcir_header->indicator & 0x80)
-			break;
-
-		/*
-		 * Move header pointer up to the next image in the ROM.
-		 */
-		cur_header += header->size512 * 512;
-	}
-}
-
-/*
- *	t4_load_boot - download boot flash
- *	@adapter: the adapter
- *	@boot_data: the boot image to write
- *	@boot_addr: offset in flash to write boot_data
- *	@size: image size
- *
- *	Write the supplied boot image to the card's serial flash.
- *	The boot image has the following sections: a 28-byte header and the
- *	boot image.
- */
-int t4_load_boot(struct adapter *adap, u8 *boot_data, 
-		 unsigned int boot_addr, unsigned int size)
-{
-	pci_exp_rom_header_t *header;
-	int pcir_offset ;
-	pcir_data_t *pcir_header;
-	int ret, addr;
-	uint16_t device_id;
-	unsigned int i;
-	unsigned int boot_sector = boot_addr * 1024;
-	unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
-
-	/*
-	 * Make sure the boot image does not encroach on the firmware region
-	 */
-	if ((boot_sector + size) >> 16 > FLASH_FW_START_SEC) {
-		CH_ERR(adap, "boot image encroaching on firmware region\n");
-		return -EFBIG;
-	}
-
-	/*
-	 * Number of sectors spanned
-	 */
-	i = DIV_ROUND_UP(size ? size : FLASH_BOOTCFG_MAX_SIZE,
-			sf_sec_size);
-	ret = t4_flash_erase_sectors(adap, boot_sector >> 16,
-				     (boot_sector >> 16) + i - 1);
-
-	/*
-	 * If size == 0 then we're simply erasing the FLASH sectors associated
-	 * with the on-adapter option ROM file
-	 */
-	if (ret || (size == 0))
-		goto out;
-
-	/* Get boot header */
-	header = (pci_exp_rom_header_t *)boot_data;
-	pcir_offset = le16_to_cpu(*(u16 *)header->pcir_offset);
-	/* PCIR Data Structure */
-	pcir_header = (pcir_data_t *) &boot_data[pcir_offset];
-
-	/*
-	 * Perform some primitive sanity testing to avoid accidentally
-	 * writing garbage over the boot sectors.  We ought to check for
-	 * more but it's not worth it for now ...
-	 */
-	if (size < BOOT_MIN_SIZE || size > BOOT_MAX_SIZE) {
-		CH_ERR(adap, "boot image too small/large\n");
-		return -EFBIG;
-	}
-
-	/*
-	 * Check BOOT ROM header signature
-	 */
-	if (le16_to_cpu(*(u16*)header->signature) != BOOT_SIGNATURE ) {
-		CH_ERR(adap, "Boot image missing signature\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Check PCI header signature
-	 */
-	if (le32_to_cpu(*(u32*)pcir_header->signature) != PCIR_SIGNATURE) {
-		CH_ERR(adap, "PCI header missing signature\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Check Vendor ID matches Chelsio ID
-	 */
-	if (le16_to_cpu(*(u16*)pcir_header->vendor_id) != VENDOR_ID) {
-		CH_ERR(adap, "Vendor ID missing signature\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Retrieve adapter's device ID
-	 */
-	t4_os_pci_read_cfg2(adap, PCI_DEVICE_ID, &device_id);
-	/* Want to deal with PF 0 so I strip off PF 4 indicator */
-	device_id = (device_id & 0xff) | 0x4000;
-
-	/*
-	 * Check PCIE Device ID
-	 */
-	if (le16_to_cpu(*(u16*)pcir_header->device_id) != device_id) {
-		/*
-		 * Change the device ID in the Boot BIOS image to match
-		 * the Device ID of the current adapter.
-		 */
-		modify_device_id(device_id, boot_data);
-	}
-
-	/*
-	 * Skip over the first SF_PAGE_SIZE worth of data and write it after
-	 * we finish copying the rest of the boot image. This will ensure
-	 * that the BIOS boot header will only be written if the boot image
-	 * was written in full.
-	 */
-	addr = boot_sector;
-	for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
-		addr += SF_PAGE_SIZE; 
-		boot_data += SF_PAGE_SIZE;
-		ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, boot_data, 0);
-		if (ret)
-			goto out;
-	}
-
-	ret = t4_write_flash(adap, boot_sector, SF_PAGE_SIZE, boot_data, 0);
-
-out:
-	if (ret)
-		CH_ERR(adap, "boot image download failed, error %d\n", ret);
-	return ret;
-}
-
-/**
- *	t4_read_cimq_cfg - read CIM queue configuration
- *	@adap: the adapter
- *	@base: holds the queue base addresses in bytes
- *	@size: holds the queue sizes in bytes
- *	@thres: holds the queue full thresholds in bytes
- *
- *	Returns the current configuration of the CIM queues, starting with
- *	the IBQs, then the OBQs.
- */
-void t4_read_cimq_cfg(struct adapter *adap, u16 *base, u16 *size, u16 *thres)
-{
-	unsigned int i, v;
-
-	for (i = 0; i < CIM_NUM_IBQ; i++) {
-		t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_IBQSELECT |
-			     V_QUENUMSELECT(i));
-		v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
-		*base++ = G_CIMQBASE(v) * 256; /* value is in 256-byte units */
-		*size++ = G_CIMQSIZE(v) * 256; /* value is in 256-byte units */
-		*thres++ = G_QUEFULLTHRSH(v) * 8;   /* 8-byte unit */
-	}
-	for (i = 0; i < adap->chip_params->cim_num_obq; i++) {
-		t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
-			     V_QUENUMSELECT(i));
-		v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
-		*base++ = G_CIMQBASE(v) * 256; /* value is in 256-byte units */
-		*size++ = G_CIMQSIZE(v) * 256; /* value is in 256-byte units */
-	}
-}
-
-/**
- *	t4_read_cim_ibq - read the contents of a CIM inbound queue
- *	@adap: the adapter
- *	@qid: the queue index
- *	@data: where to store the queue contents
- *	@n: capacity of @data in 32-bit words
- *
- *	Reads the contents of the selected CIM queue starting at address 0 up
- *	to the capacity of @data.  @n must be a multiple of 4.  Returns < 0 on
- *	error and the number of 32-bit words actually read on success.
- */
-int t4_read_cim_ibq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
-{
-	int i, err;
-	unsigned int addr;
-	const unsigned int nwords = CIM_IBQ_SIZE * 4;
-
-	if (qid > 5 || (n & 3))
-		return -EINVAL;
-
-	addr = qid * nwords;
-	if (n > nwords)
-		n = nwords;
-
-	for (i = 0; i < n; i++, addr++) {
-		t4_write_reg(adap, A_CIM_IBQ_DBG_CFG, V_IBQDBGADDR(addr) |
-			     F_IBQDBGEN);
+	for (i = 0; i < n; i++, addr++) {
+		t4_write_reg(adap, A_CIM_IBQ_DBG_CFG, V_IBQDBGADDR(addr) |
+			     F_IBQDBGEN);
 		/*
 		 * It might take 3-10ms before the IBQ debug read access is
 		 * allowed.  Wait for 1 Sec with a delay of 1 usec.
@@ -6029,7 +5816,7 @@ void t4_pmrx_get_stats(struct adapter *a
 }
 
 /**
- *	get_mps_bg_map - return the buffer groups associated with a port
+ *	t4_get_mps_bg_map - return the buffer groups associated with a port
  *	@adap: the adapter
  *	@idx: the port index
  *
@@ -6037,7 +5824,7 @@ void t4_pmrx_get_stats(struct adapter *a
  *	with the given port.  Bit i is set if buffer group i is used by the
  *	port.
  */
-static unsigned int get_mps_bg_map(struct adapter *adap, int idx)
+static unsigned int t4_get_mps_bg_map(struct adapter *adap, int idx)
 {
 	u32 n = G_NUMPORTS(t4_read_reg(adap, A_MPS_CMN_CTL));
 
@@ -6110,7 +5897,7 @@ void t4_get_port_stats_offset(struct ada
  */
 void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
 {
-	u32 bgmap = get_mps_bg_map(adap, idx);
+	u32 bgmap = t4_get_mps_bg_map(adap, idx);
 
 #define GET_STAT(name) \
 	t4_read_reg64(adap, \
@@ -6193,7 +5980,7 @@ void t4_get_port_stats(struct adapter *a
 void t4_clr_port_stats(struct adapter *adap, int idx)
 {
 	unsigned int i;
-	u32 bgmap = get_mps_bg_map(adap, idx);
+	u32 bgmap = t4_get_mps_bg_map(adap, idx);
 	u32 port_base_addr;
 
 	if (is_t4(adap))
@@ -6226,7 +6013,7 @@ void t4_clr_port_stats(struct adapter *a
  */
 void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
 {
-	u32 bgmap = get_mps_bg_map(adap, idx);
+	u32 bgmap = t4_get_mps_bg_map(adap, idx);
 
 #define GET_STAT(name) \
 	t4_read_reg64(adap, \
@@ -7702,21 +7489,43 @@ static void __devinit init_link_config(s
 	}
 }
 
-static int __devinit get_flash_params(struct adapter *adapter)
+struct flash_desc {
+	u32 vendor_and_model_id;
+	u32 size_mb;
+};
+
+int t4_get_flash_params(struct adapter *adapter)
 {
+	/*
+	 * Table for non-Numonix supported flash parts.  Numonix parts are left
+	 * to the preexisting well-tested code.  All flash parts have 64KB
+	 * sectors.

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201603080748.u287muuq070817>