Commit ef215e64 authored by Ben Hutchings's avatar Ben Hutchings

sfc: Store VPD serial number at probe time

Original version by Stuart Hodgson.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent bd9a265d
...@@ -2628,6 +2628,8 @@ static void efx_fini_struct(struct efx_nic *efx) ...@@ -2628,6 +2628,8 @@ static void efx_fini_struct(struct efx_nic *efx)
for (i = 0; i < EFX_MAX_CHANNELS; i++) for (i = 0; i < EFX_MAX_CHANNELS; i++)
kfree(efx->channel[i]); kfree(efx->channel[i]);
kfree(efx->vpd_sn);
if (efx->workqueue) { if (efx->workqueue) {
destroy_workqueue(efx->workqueue); destroy_workqueue(efx->workqueue);
efx->workqueue = NULL; efx->workqueue = NULL;
...@@ -2699,12 +2701,12 @@ static void efx_pci_remove(struct pci_dev *pci_dev) ...@@ -2699,12 +2701,12 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
* always appear within the first 512 bytes. * always appear within the first 512 bytes.
*/ */
#define SFC_VPD_LEN 512 #define SFC_VPD_LEN 512
static void efx_print_product_vpd(struct efx_nic *efx) static void efx_probe_vpd_strings(struct efx_nic *efx)
{ {
struct pci_dev *dev = efx->pci_dev; struct pci_dev *dev = efx->pci_dev;
char vpd_data[SFC_VPD_LEN]; char vpd_data[SFC_VPD_LEN];
ssize_t vpd_size; ssize_t vpd_size;
int i, j; int ro_start, ro_size, i, j;
/* Get the vpd data from the device */ /* Get the vpd data from the device */
vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data); vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data);
...@@ -2714,14 +2716,15 @@ static void efx_print_product_vpd(struct efx_nic *efx) ...@@ -2714,14 +2716,15 @@ static void efx_print_product_vpd(struct efx_nic *efx)
} }
/* Get the Read only section */ /* Get the Read only section */
i = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA); ro_start = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA);
if (i < 0) { if (ro_start < 0) {
netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n"); netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n");
return; return;
} }
j = pci_vpd_lrdt_size(&vpd_data[i]); ro_size = pci_vpd_lrdt_size(&vpd_data[ro_start]);
i += PCI_VPD_LRDT_TAG_SIZE; j = ro_size;
i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
if (i + j > vpd_size) if (i + j > vpd_size)
j = vpd_size - i; j = vpd_size - i;
...@@ -2741,6 +2744,27 @@ static void efx_print_product_vpd(struct efx_nic *efx) ...@@ -2741,6 +2744,27 @@ static void efx_print_product_vpd(struct efx_nic *efx)
netif_info(efx, drv, efx->net_dev, netif_info(efx, drv, efx->net_dev,
"Part Number : %.*s\n", j, &vpd_data[i]); "Part Number : %.*s\n", j, &vpd_data[i]);
i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
j = ro_size;
i = pci_vpd_find_info_keyword(vpd_data, i, j, "SN");
if (i < 0) {
netif_err(efx, drv, efx->net_dev, "Serial number not found\n");
return;
}
j = pci_vpd_info_field_size(&vpd_data[i]);
i += PCI_VPD_INFO_FLD_HDR_SIZE;
if (i + j > vpd_size) {
netif_err(efx, drv, efx->net_dev, "Incomplete serial number\n");
return;
}
efx->vpd_sn = kmalloc(j + 1, GFP_KERNEL);
if (!efx->vpd_sn)
return;
snprintf(efx->vpd_sn, j + 1, "%s", &vpd_data[i]);
} }
...@@ -2837,7 +2861,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev, ...@@ -2837,7 +2861,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
netif_info(efx, probe, efx->net_dev, netif_info(efx, probe, efx->net_dev,
"Solarflare NIC detected\n"); "Solarflare NIC detected\n");
efx_print_product_vpd(efx); efx_probe_vpd_strings(efx);
/* Set up basic I/O (BAR mappings etc) */ /* Set up basic I/O (BAR mappings etc) */
rc = efx_init_io(efx); rc = efx_init_io(efx);
......
...@@ -771,6 +771,7 @@ struct vfdi_status; ...@@ -771,6 +771,7 @@ struct vfdi_status;
* @local_lock: Mutex protecting %local_addr_list and %local_page_list. * @local_lock: Mutex protecting %local_addr_list and %local_page_list.
* @peer_work: Work item to broadcast peer addresses to VMs. * @peer_work: Work item to broadcast peer addresses to VMs.
* @ptp_data: PTP state data * @ptp_data: PTP state data
* @vpd_sn: Serial number read from VPD
* @monitor_work: Hardware monitor workitem * @monitor_work: Hardware monitor workitem
* @biu_lock: BIU (bus interface unit) lock * @biu_lock: BIU (bus interface unit) lock
* @last_irq_cpu: Last CPU to handle a possible test interrupt. This * @last_irq_cpu: Last CPU to handle a possible test interrupt. This
...@@ -920,6 +921,8 @@ struct efx_nic { ...@@ -920,6 +921,8 @@ struct efx_nic {
struct efx_ptp_data *ptp_data; struct efx_ptp_data *ptp_data;
char *vpd_sn;
/* The following fields may be written more often */ /* The following fields may be written more often */
struct delayed_work monitor_work ____cacheline_aligned_in_smp; struct delayed_work monitor_work ____cacheline_aligned_in_smp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment