summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornp <np@FreeBSD.org>2016-03-08 07:48:55 +0000
committernp <np@FreeBSD.org>2016-03-08 07:48:55 +0000
commit54eec7a19dd772dad64c0aafee6cad6981dc8910 (patch)
tree352d5273c7594e90a04077e19e62564598a0c3ee
parent475b5a6654dcd3f42eff929b1a113d1fcf7bb686 (diff)
downloadFreeBSD-src-54eec7a19dd772dad64c0aafee6cad6981dc8910.zip
FreeBSD-src-54eec7a19dd772dad64c0aafee6cad6981dc8910.tar.gz
cxgbe(4): Updates to the shared routines that deal with the serial EEPROM,
flash, and VPD. Obtained from: Chelsio Communications
-rw-r--r--sys/dev/cxgbe/adapter.h2
-rw-r--r--sys/dev/cxgbe/common/common.h9
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c1024
-rw-r--r--sys/dev/cxgbe/osdep.h2
-rw-r--r--sys/dev/cxgbe/t4_main.c9
5 files changed, 616 insertions, 430 deletions
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index 3d54c65..358f618 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -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;
diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h
index a2ec22f..ad3b827 100644
--- a/sys/dev/cxgbe/common/common.h
+++ b/sys/dev/cxgbe/common/common.h
@@ -499,20 +499,24 @@ int t4_eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz);
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, u32 *la_buf, unsigned int *wrptr);
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);
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index e8293c7..bcdf33a 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -2536,7 +2536,7 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size)
/*
* 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 *adapter, u32 addr, u32 *data)
*/
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 *adapter, int enable)
* 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;
- }
+ 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;
- }
+ 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 struct t4_vpd_hdr *v, const char *kw)
* 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 *adapter, struct vpd_params *p)
* 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 *adapter, struct vpd_params *p)
/* 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 *adapter, int attempts, int delay)
* 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 *adapter, unsigned int addr,
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 *adapter, unsigned int addr,
*
* 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 *adapter, unsigned int addr,
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 *adapter, unsigned int addr,
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 *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 *adapter)
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,283 +3318,6 @@ 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 */
-
-/* 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 */
-};
-
-/*
- * 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.
- *
- * Write the supplied device ID to the boot BIOS image.
- */
-static void modify_device_id(int device_id, u8 *boot_data)
-{
- legacy_pci_exp_rom_header_t *header;
- pcir_data_t *pcir_header;
- u32 cur_header = 0;
-
- /*
- * 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)];
-
- /*
- * 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
@@ -6029,7 +5816,7 @@ void t4_pmrx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
}
/**
- * 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 *adap, u32 cnt[], u64 cycles[])
* 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 adapter *adap, int idx,
*/
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 *adap, int idx, struct port_stats *p)
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 *adap, int idx)
*/
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(struct link_config *lc,
}
}
-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.
+ */
+ static struct flash_desc supported_flash[] = {
+ { 0x150201, 4 << 20 }, /* Spansion 4MB S25FL032P */
+ };
+
int ret;
u32 info = 0;
ret = sf1_write(adapter, 1, 1, 0, SF_RD_ID);
if (!ret)
ret = sf1_read(adapter, 3, 0, 1, &info);
- t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */
+ t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */
if (ret < 0)
return ret;
- if ((info & 0xff) != 0x20) /* not a Numonix flash */
+ for (ret = 0; ret < ARRAY_SIZE(supported_flash); ++ret)
+ if (supported_flash[ret].vendor_and_model_id == info) {
+ adapter->params.sf_size = supported_flash[ret].size_mb;
+ adapter->params.sf_nsec =
+ adapter->params.sf_size / SF_SEC_SIZE;
+ return 0;
+ }
+
+ if ((info & 0xff) != 0x20) /* not a Numonix flash */
return -EINVAL;
- info >>= 16; /* log2 of size */
+ info >>= 16; /* log2 of size */
if (info >= 0x14 && info < 0x18)
adapter->params.sf_nsec = 1 << (info - 16);
else if (info == 0x18)
@@ -7724,6 +7533,16 @@ static int __devinit get_flash_params(struct adapter *adapter)
else
return -EINVAL;
adapter->params.sf_size = 1 << info;
+
+ /*
+ * We should ~probably~ reject adapters with FLASHes which are too
+ * small but we have some legacy FPGAs with small FLASHes that we'd
+ * still like to use. So instead we emit a scary message ...
+ */
+ if (adapter->params.sf_size < FLASH_MIN_SIZE)
+ CH_WARN(adapter, "WARNING!!! FLASH size %#x < %#x!!!\n",
+ adapter->params.sf_size, FLASH_MIN_SIZE);
+
return 0;
}
@@ -7793,13 +7612,13 @@ static const struct chip_params *get_chip_params(int chipid)
/**
* t4_prep_adapter - prepare SW and HW for operation
* @adapter: the adapter
- * @reset: if true perform a HW reset
+ * @buf: temporary space of at least VPD_LEN size provided by the caller.
*
* Initialize adapter SW state for the various HW modules, set initial
* values for some adapter tunables, take PHYs out of reset, and
* initialize the MDIO interface.
*/
-int __devinit t4_prep_adapter(struct adapter *adapter)
+int t4_prep_adapter(struct adapter *adapter, u8 *buf)
{
int ret;
uint16_t device_id;
@@ -7828,11 +7647,11 @@ int __devinit t4_prep_adapter(struct adapter *adapter)
adapter->params.pci.vpd_cap_addr =
t4_os_find_pci_capability(adapter, PCI_CAP_ID_VPD);
- ret = get_flash_params(adapter);
+ ret = t4_get_flash_params(adapter);
if (ret < 0)
return ret;
- ret = get_vpd_params(adapter, &adapter->params.vpd);
+ ret = get_vpd_params(adapter, &adapter->params.vpd, buf);
if (ret < 0)
return ret;
@@ -8060,13 +7879,13 @@ int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
return field_shift;
}
-int __devinit 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)
{
u8 addr[6];
int ret, i, j;
struct fw_port_cmd c;
u16 rss_size;
- adapter_t *adap = p->adapter;
+ struct port_info *p = adap2pinfo(adap, port_id);
u32 param, val;
memset(&c, 0, sizeof(c));
@@ -8093,18 +7912,18 @@ int __devinit t4_port_init(struct port_info *p, int mbox, int pf, int vf)
p->vi[0].viid = ret;
p->tx_chan = j;
- p->rx_chan_map = get_mps_bg_map(adap, j);
+ p->rx_chan_map = t4_get_mps_bg_map(adap, j);
p->lport = j;
p->vi[0].rss_size = rss_size;
t4_os_set_hw_addr(adap, p->port_id, addr);
- ret = ntohl(c.u.info.lstatus_to_modtype);
+ ret = be32_to_cpu(c.u.info.lstatus_to_modtype);
p->mdio_addr = (ret & F_FW_PORT_CMD_MDIOCAP) ?
G_FW_PORT_CMD_MDIOADDR(ret) : -1;
p->port_type = G_FW_PORT_CMD_PTYPE(ret);
p->mod_type = G_FW_PORT_CMD_MODTYPE(ret);
- init_link_config(&p->link_cfg, ntohs(c.u.info.pcap));
+ init_link_config(&p->link_cfg, be16_to_cpu(c.u.info.pcap));
param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_RSSINFO) |
@@ -8120,6 +7939,361 @@ int __devinit t4_port_init(struct port_info *p, int mbox, int pf, int vf)
return 0;
}
+/* 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 */
+
+/* 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 */
+};
+
+/*
+ * 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.
+ *
+ * Write the supplied device ID to the boot BIOS image.
+ */
+static void modify_device_id(int device_id, u8 *boot_data)
+{
+ legacy_pci_exp_rom_header_t *header;
+ pcir_data_t *pcir_header;
+ u32 cur_header = 0;
+
+ /*
+ * 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)];
+
+ /*
+ * 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;
+ }
+
+ /*
+ * The boot sector is comprised of the Expansion-ROM boot, iSCSI boot,
+ * and Boot configuration data sections. These 3 boot sections span
+ * sectors 0 to 7 in flash and live right before the FW image location.
+ */
+ i = DIV_ROUND_UP(size ? size : FLASH_FW_START,
+ 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;
+ }
+
+#ifndef CHELSIO_T4_DIAGS
+ /*
+ * 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;
+ }
+#endif
+
+ /*
+ * 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 & 0xf0ff;
+
+ /*
+ * 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,
+ (const u8 *)header, 0);
+
+out:
+ if (ret)
+ CH_ERR(adap, "boot image download failed, error %d\n", ret);
+ return ret;
+}
+
+/*
+ * t4_flash_bootcfg_addr - return the address of the flash optionrom configuration
+ * @adapter: the adapter
+ *
+ * Return the address within the flash where the OptionROM Configuration
+ * is stored, or an error if the device FLASH is too small to contain
+ * a OptionROM Configuration.
+ */
+static int t4_flash_bootcfg_addr(struct adapter *adapter)
+{
+ /*
+ * If the device FLASH isn't large enough to hold a Firmware
+ * Configuration File, return an error.
+ */
+ if (adapter->params.sf_size < FLASH_BOOTCFG_START + FLASH_BOOTCFG_MAX_SIZE)
+ return -ENOSPC;
+
+ return FLASH_BOOTCFG_START;
+}
+
+int t4_load_bootcfg(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_bootcfg_addr(adap);
+ if (cfg_addr < 0)
+ return cfg_addr;
+
+ addr = cfg_addr;
+ flash_cfg_start_sec = addr / SF_SEC_SIZE;
+
+ if (size > FLASH_BOOTCFG_MAX_SIZE) {
+ CH_ERR(adap, "bootcfg file too large, max is %u bytes\n",
+ FLASH_BOOTCFG_MAX_SIZE);
+ return -EFBIG;
+ }
+
+ i = DIV_ROUND_UP(FLASH_BOOTCFG_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 OptionROM 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, 0);
+ if (ret)
+ goto out;
+
+ addr += SF_PAGE_SIZE;
+ cfg_data += SF_PAGE_SIZE;
+ }
+
+out:
+ if (ret)
+ CH_ERR(adap, "boot config data %s failed %d\n",
+ (size == 0 ? "clear" : "download"), ret);
+ return ret;
+}
+
/**
* t4_set_filter_mode - configure the optional components of filter tuples
* @adap: the adapter
diff --git a/sys/dev/cxgbe/osdep.h b/sys/dev/cxgbe/osdep.h
index 403b535..cc12da3 100644
--- a/sys/dev/cxgbe/osdep.h
+++ b/sys/dev/cxgbe/osdep.h
@@ -80,6 +80,8 @@ typedef boolean_t bool;
#define true TRUE
#endif
+#define __force
+
#define mdelay(x) DELAY((x) * 1000)
#define udelay(x) DELAY(x)
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 80f1e1c..a29a751 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -645,6 +645,7 @@ t4_attach(device_t dev)
int rc = 0, i, j, n10g, n1g, rqidx, tqidx;
struct intrs_and_queues iaq;
struct sge *s;
+ uint8_t *buf;
#ifdef TCP_OFFLOAD
int ofld_rqidx, ofld_tqidx;
#endif
@@ -713,8 +714,10 @@ t4_attach(device_t dev)
t4_register_cpl_handler(sc, CPL_T5_TRACE_PKT, t5_trace_pkt);
t4_init_sge_cpl_handlers(sc);
- /* Prepare the adapter for operation */
- rc = -t4_prep_adapter(sc);
+ /* Prepare the adapter for operation. */
+ buf = malloc(PAGE_SIZE, M_CXGBE, M_ZERO | M_WAITOK);
+ rc = -t4_prep_adapter(sc, buf);
+ free(buf, M_CXGBE);
if (rc != 0) {
device_printf(dev, "failed to prepare adapter: %d.\n", rc);
goto done;
@@ -815,7 +818,7 @@ t4_attach(device_t dev)
* Allocate the "main" VI and initialize parameters
* like mac addr.
*/
- rc = -t4_port_init(pi, sc->mbox, sc->pf, 0);
+ rc = -t4_port_init(sc, sc->mbox, sc->pf, 0, i);
if (rc != 0) {
device_printf(dev, "unable to initialize port %d: %d\n",
i, rc);
OpenPOWER on IntegriCloud