svn commit: r296489 - in head/sys/dev/cxgbe: . common
Navdeep Parhar
np at FreeBSD.org
Tue Mar 8 07:48:57 UTC 2016
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 ***
More information about the svn-src-all
mailing list