cxgbe(4): Read the MFG diags version from the VPD and make it available
in the sysctl MIB. MFC after: 1 week Sponsored by: Chelsio Communications
This commit is contained in:
parent
5e6e2d38c1
commit
426b6bd53c
@ -44,6 +44,7 @@ enum {
|
||||
EC_LEN = 16, /* E/C length */
|
||||
ID_LEN = 16, /* ID length */
|
||||
PN_LEN = 16, /* Part Number length */
|
||||
MD_LEN = 16, /* MFG diags version length */
|
||||
MACADDR_LEN = 12, /* MAC Address length */
|
||||
};
|
||||
|
||||
@ -258,6 +259,7 @@ struct vpd_params {
|
||||
u8 id[ID_LEN + 1];
|
||||
u8 pn[PN_LEN + 1];
|
||||
u8 na[MACADDR_LEN + 1];
|
||||
u8 md[MD_LEN + 1];
|
||||
};
|
||||
|
||||
struct pci_params {
|
||||
@ -590,7 +592,7 @@ int t4_get_vpd_version(struct adapter *adapter, u32 *vers);
|
||||
int t4_get_version_info(struct adapter *adapter);
|
||||
int t4_init_hw(struct adapter *adapter, u32 fw_params);
|
||||
const struct chip_params *t4_get_chip_params(int chipid);
|
||||
int t4_prep_adapter(struct adapter *adapter, u8 *buf);
|
||||
int t4_prep_adapter(struct adapter *adapter, u32 *buf);
|
||||
int t4_shutdown_adapter(struct adapter *adapter);
|
||||
int t4_init_devlog_params(struct adapter *adapter, int fw_attach);
|
||||
int t4_init_sge_params(struct adapter *adapter);
|
||||
|
@ -2664,13 +2664,16 @@ 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 sections.
|
||||
* Partial EEPROM Vital Product Data structure. The VPD starts with one ID
|
||||
* header followed by one or more VPD-R sections, each with its own header.
|
||||
*/
|
||||
struct t4_vpd_hdr {
|
||||
u8 id_tag;
|
||||
u8 id_len[2];
|
||||
u8 id_data[ID_LEN];
|
||||
};
|
||||
|
||||
struct t4_vpdr_hdr {
|
||||
u8 vpdr_tag;
|
||||
u8 vpdr_len[2];
|
||||
};
|
||||
@ -2905,32 +2908,43 @@ 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
|
||||
* @vpd: Pointer to buffered vpd data structure
|
||||
* @kw: The keyword to search for
|
||||
* @region: VPD region to search (starting from 0)
|
||||
*
|
||||
* 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)
|
||||
static int get_vpd_keyword_val(const u8 *vpd, const char *kw, int region)
|
||||
{
|
||||
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);
|
||||
int i, tag;
|
||||
unsigned int offset, len;
|
||||
const struct t4_vpdr_hdr *vpdr;
|
||||
|
||||
if (len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
|
||||
offset = sizeof(struct t4_vpd_hdr);
|
||||
vpdr = (const void *)(vpd + offset);
|
||||
tag = vpdr->vpdr_tag;
|
||||
len = (u16)vpdr->vpdr_len[0] + ((u16)vpdr->vpdr_len[1] << 8);
|
||||
while (region--) {
|
||||
offset += sizeof(struct t4_vpdr_hdr) + len;
|
||||
vpdr = (const void *)(vpd + offset);
|
||||
if (++tag != vpdr->vpdr_tag)
|
||||
return -ENOENT;
|
||||
len = (u16)vpdr->vpdr_len[0] + ((u16)vpdr->vpdr_len[1] << 8);
|
||||
}
|
||||
offset += sizeof(struct t4_vpdr_hdr);
|
||||
|
||||
if (offset + len > VPD_LEN) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
for (i = offset; i + VPD_INFO_FLD_HDR_SIZE <= offset + len;) {
|
||||
if(memcmp(buf + i , kw , 2) == 0){
|
||||
if (memcmp(vpd + 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 + vpd[i+2];
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
@ -2946,18 +2960,18 @@ static int get_vpd_keyword_val(const struct t4_vpd_hdr *v, const char *kw)
|
||||
* Reads card parameters stored in VPD EEPROM.
|
||||
*/
|
||||
static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
|
||||
u8 *vpd)
|
||||
u32 *buf)
|
||||
{
|
||||
int i, ret, addr;
|
||||
int ec, sn, pn, na;
|
||||
int ec, sn, pn, na, md;
|
||||
u8 csum;
|
||||
const struct t4_vpd_hdr *v;
|
||||
const u8 *vpd = (const u8 *)buf;
|
||||
|
||||
/*
|
||||
* Card information normally starts at VPD_BASE but early cards had
|
||||
* it at 0.
|
||||
*/
|
||||
ret = t4_seeprom_read(adapter, VPD_BASE, (u32 *)(vpd));
|
||||
ret = t4_seeprom_read(adapter, VPD_BASE, buf);
|
||||
if (ret)
|
||||
return (ret);
|
||||
|
||||
@ -2971,14 +2985,13 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
|
||||
addr = *vpd == CHELSIO_VPD_UNIQUE_ID ? VPD_BASE : VPD_BASE_OLD;
|
||||
|
||||
for (i = 0; i < VPD_LEN; i += 4) {
|
||||
ret = t4_seeprom_read(adapter, addr + i, (u32 *)(vpd + i));
|
||||
ret = t4_seeprom_read(adapter, addr + i, buf++);
|
||||
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); \
|
||||
var = get_vpd_keyword_val(vpd, name, 0); \
|
||||
if (var < 0) { \
|
||||
CH_ERR(adapter, "missing VPD keyword " name "\n"); \
|
||||
return -EINVAL; \
|
||||
@ -3001,7 +3014,7 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
|
||||
FIND_VPD_KW(na, "NA");
|
||||
#undef FIND_VPD_KW
|
||||
|
||||
memcpy(p->id, v->id_data, ID_LEN);
|
||||
memcpy(p->id, vpd + offsetof(struct t4_vpd_hdr, id_data), ID_LEN);
|
||||
strstrip(p->id);
|
||||
memcpy(p->ec, vpd + ec, EC_LEN);
|
||||
strstrip(p->ec);
|
||||
@ -3015,6 +3028,14 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
|
||||
memcpy(p->na, vpd + na, min(i, MACADDR_LEN));
|
||||
strstrip((char *)p->na);
|
||||
|
||||
md = get_vpd_keyword_val(vpd, "VF", 1);
|
||||
if (md < 0) {
|
||||
snprintf(p->md, sizeof(p->md), "unknown");
|
||||
} else {
|
||||
i = vpd[md - VPD_INFO_FLD_HDR_SIZE + 2];
|
||||
memcpy(p->md, vpd + md, min(i, MD_LEN));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -7997,7 +8018,7 @@ const struct chip_params *t4_get_chip_params(int chipid)
|
||||
* values for some adapter tunables, take PHYs out of reset, and
|
||||
* initialize the MDIO interface.
|
||||
*/
|
||||
int t4_prep_adapter(struct adapter *adapter, u8 *buf)
|
||||
int t4_prep_adapter(struct adapter *adapter, u32 *buf)
|
||||
{
|
||||
int ret;
|
||||
uint16_t device_id;
|
||||
|
@ -836,7 +836,7 @@ t4_attach(device_t dev)
|
||||
struct make_dev_args mda;
|
||||
struct intrs_and_queues iaq;
|
||||
struct sge *s;
|
||||
uint8_t *buf;
|
||||
uint32_t *buf;
|
||||
#ifdef TCP_OFFLOAD
|
||||
int ofld_rqidx, ofld_tqidx;
|
||||
#endif
|
||||
@ -5127,6 +5127,9 @@ t4_sysctls(struct adapter *sc)
|
||||
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "ec",
|
||||
CTLFLAG_RD, sc->params.vpd.ec, 0, "engineering change");
|
||||
|
||||
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "md_version",
|
||||
CTLFLAG_RD, sc->params.vpd.md, 0, "manufacturing diags version");
|
||||
|
||||
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "na",
|
||||
CTLFLAG_RD, sc->params.vpd.na, 0, "network address");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user