Skip to content

Commit

Permalink
cxgb4: collect vpd info directly from hardware
Browse files Browse the repository at this point in the history
Collect vpd information directly from hardware instead of software
adapter context. Move EEPROM physical address to virtual address
translation logic to t4_hw.c and update relevant files.

Fixes: 6f92a65 ("cxgb4: collect hardware misc dumps")
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Rahul Lakkireddy authored and David S. Miller committed Nov 11, 2017
1 parent 40cff8f commit 940c9c4
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 42 deletions.
6 changes: 6 additions & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ struct cudbg_mps_tcam {
u8 reserved[2];
};

#define CUDBG_VPD_PF_SIZE 0x800
#define CUDBG_SCFG_VER_ADDR 0x06
#define CUDBG_SCFG_VER_LEN 4
#define CUDBG_VPD_VER_ADDR 0x18c7
#define CUDBG_VPD_VER_LEN 2

struct cudbg_vpd_data {
u8 sn[SERNUM_LEN + 1];
u8 bn[PN_LEN + 1];
Expand Down
77 changes: 66 additions & 11 deletions drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ struct cudbg_entity_hdr *cudbg_get_entity_hdr(void *outbuf, int i)
(sizeof(struct cudbg_entity_hdr) * (i - 1)));
}

static int cudbg_read_vpd_reg(struct adapter *padap, u32 addr, u32 len,
void *dest)
{
int vaddr, rc;

vaddr = t4_eeprom_ptov(addr, padap->pf, EEPROMPFSIZE);
if (vaddr < 0)
return vaddr;

rc = pci_read_vpd(padap->pdev, vaddr, len, dest);
if (rc < 0)
return rc;

return 0;
}

int cudbg_collect_reg_dump(struct cudbg_init *pdbg_init,
struct cudbg_buffer *dbg_buff,
struct cudbg_error *cudbg_err)
Expand Down Expand Up @@ -1289,25 +1305,64 @@ int cudbg_collect_vpd_data(struct cudbg_init *pdbg_init,
{
struct adapter *padap = pdbg_init->adap;
struct cudbg_buffer temp_buff = { 0 };
char vpd_str[CUDBG_VPD_VER_LEN + 1];
u32 scfg_vers, vpd_vers, fw_vers;
struct cudbg_vpd_data *vpd_data;
int rc;
struct vpd_params vpd = { 0 };
int rc, ret;

rc = t4_get_raw_vpd_params(padap, &vpd);
if (rc)
return rc;

rc = t4_get_fw_version(padap, &fw_vers);
if (rc)
return rc;

/* Serial Configuration Version is located beyond the PF's vpd size.
* Temporarily give access to entire EEPROM to get it.
*/
rc = pci_set_vpd_size(padap->pdev, EEPROMVSIZE);
if (rc < 0)
return rc;

ret = cudbg_read_vpd_reg(padap, CUDBG_SCFG_VER_ADDR, CUDBG_SCFG_VER_LEN,
&scfg_vers);

/* Restore back to original PF's vpd size */
rc = pci_set_vpd_size(padap->pdev, CUDBG_VPD_PF_SIZE);
if (rc < 0)
return rc;

if (ret)
return ret;

rc = cudbg_read_vpd_reg(padap, CUDBG_VPD_VER_ADDR, CUDBG_VPD_VER_LEN,
vpd_str);
if (rc)
return rc;

vpd_str[CUDBG_VPD_VER_LEN] = '\0';
rc = kstrtouint(vpd_str, 0, &vpd_vers);
if (rc)
return rc;

rc = cudbg_get_buff(dbg_buff, sizeof(struct cudbg_vpd_data),
&temp_buff);
if (rc)
return rc;

vpd_data = (struct cudbg_vpd_data *)temp_buff.data;
memcpy(vpd_data->sn, padap->params.vpd.sn, SERNUM_LEN + 1);
memcpy(vpd_data->bn, padap->params.vpd.pn, PN_LEN + 1);
memcpy(vpd_data->na, padap->params.vpd.na, MACADDR_LEN + 1);
memcpy(vpd_data->mn, padap->params.vpd.id, ID_LEN + 1);
vpd_data->scfg_vers = padap->params.scfg_vers;
vpd_data->vpd_vers = padap->params.vpd_vers;
vpd_data->fw_major = FW_HDR_FW_VER_MAJOR_G(padap->params.fw_vers);
vpd_data->fw_minor = FW_HDR_FW_VER_MINOR_G(padap->params.fw_vers);
vpd_data->fw_micro = FW_HDR_FW_VER_MICRO_G(padap->params.fw_vers);
vpd_data->fw_build = FW_HDR_FW_VER_BUILD_G(padap->params.fw_vers);
memcpy(vpd_data->sn, vpd.sn, SERNUM_LEN + 1);
memcpy(vpd_data->bn, vpd.pn, PN_LEN + 1);
memcpy(vpd_data->na, vpd.na, MACADDR_LEN + 1);
memcpy(vpd_data->mn, vpd.id, ID_LEN + 1);
vpd_data->scfg_vers = scfg_vers;
vpd_data->vpd_vers = vpd_vers;
vpd_data->fw_major = FW_HDR_FW_VER_MAJOR_G(fw_vers);
vpd_data->fw_minor = FW_HDR_FW_VER_MINOR_G(fw_vers);
vpd_data->fw_micro = FW_HDR_FW_VER_MICRO_G(fw_vers);
vpd_data->fw_build = FW_HDR_FW_VER_BUILD_G(fw_vers);
cudbg_write_and_release_buff(&temp_buff, dbg_buff);
return rc;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,7 @@ static inline int t4_memory_write(struct adapter *adap, int mtype, u32 addr,
unsigned int t4_get_regs_len(struct adapter *adapter);
void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size);

int t4_eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz);
int t4_seeprom_wp(struct adapter *adapter, bool enable);
int t4_get_raw_vpd_params(struct adapter *adapter, struct vpd_params *p);
int t4_get_vpd_params(struct adapter *adapter, struct vpd_params *p);
Expand Down
33 changes: 2 additions & 31 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1064,40 +1064,11 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
return 0;
}

/**
* eeprom_ptov - translate a physical EEPROM address to virtual
* @phys_addr: the physical EEPROM address
* @fn: the PCI function number
* @sz: size of function-specific area
*
* Translate a physical EEPROM address to virtual. The first 1K is
* accessed through virtual addresses starting at 31K, the rest is
* accessed through virtual addresses starting at 0.
*
* The mapping is as follows:
* [0..1K) -> [31K..32K)
* [1K..1K+A) -> [31K-A..31K)
* [1K+A..ES) -> [0..ES-A-1K)
*
* where A = @fn * @sz, and ES = EEPROM size.
*/
static int eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz)
{
fn *= sz;
if (phys_addr < 1024)
return phys_addr + (31 << 10);
if (phys_addr < 1024 + fn)
return 31744 - fn + phys_addr - 1024;
if (phys_addr < EEPROMSIZE)
return phys_addr - 1024 - fn;
return -EINVAL;
}

/* The next two routines implement eeprom read/write from physical addresses.
*/
static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v)
{
int vaddr = eeprom_ptov(phys_addr, adap->pf, EEPROMPFSIZE);
int vaddr = t4_eeprom_ptov(phys_addr, adap->pf, EEPROMPFSIZE);

if (vaddr >= 0)
vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v);
Expand All @@ -1106,7 +1077,7 @@ static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v)

static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v)
{
int vaddr = eeprom_ptov(phys_addr, adap->pf, EEPROMPFSIZE);
int vaddr = t4_eeprom_ptov(phys_addr, adap->pf, EEPROMPFSIZE);

if (vaddr >= 0)
vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v);
Expand Down
29 changes: 29 additions & 0 deletions drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -2638,6 +2638,35 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
#define VPD_LEN 1024
#define CHELSIO_VPD_UNIQUE_ID 0x82

/**
* t4_eeprom_ptov - translate a physical EEPROM address to virtual
* @phys_addr: the physical EEPROM address
* @fn: the PCI function number
* @sz: size of function-specific area
*
* Translate a physical EEPROM address to virtual. The first 1K is
* accessed through virtual addresses starting at 31K, the rest is
* accessed through virtual addresses starting at 0.
*
* The mapping is as follows:
* [0..1K) -> [31K..32K)
* [1K..1K+A) -> [31K-A..31K)
* [1K+A..ES) -> [0..ES-A-1K)
*
* where A = @fn * @sz, and ES = EEPROM size.
*/
int t4_eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz)
{
fn *= sz;
if (phys_addr < 1024)
return phys_addr + (31 << 10);
if (phys_addr < 1024 + fn)
return 31744 - fn + phys_addr - 1024;
if (phys_addr < EEPROMSIZE)
return phys_addr - 1024 - fn;
return -EINVAL;
}

/**
* t4_seeprom_wp - enable/disable EEPROM write protection
* @adapter: the adapter
Expand Down

0 comments on commit 940c9c4

Please sign in to comment.