aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2013-12-05 15:13:22 -0500
committerBen Hutchings <bhutchings@solarflare.com>2013-12-12 17:07:14 -0500
commitef215e64760ef6bd756c2999e7c8cee95b98e30a (patch)
tree016f4bea6a557f132808c118a0cad6360eea0740
parentbd9a265db26cdbfe74a303111381d90e66f56877 (diff)
sfc: Store VPD serial number at probe time
Original version by Stuart Hodgson. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
-rw-r--r--drivers/net/ethernet/sfc/efx.c38
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h3
2 files changed, 34 insertions, 7 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index b9929d9ed69d..5745a9fd034e 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -2628,6 +2628,8 @@ static void efx_fini_struct(struct efx_nic *efx)
2628 for (i = 0; i < EFX_MAX_CHANNELS; i++) 2628 for (i = 0; i < EFX_MAX_CHANNELS; i++)
2629 kfree(efx->channel[i]); 2629 kfree(efx->channel[i]);
2630 2630
2631 kfree(efx->vpd_sn);
2632
2631 if (efx->workqueue) { 2633 if (efx->workqueue) {
2632 destroy_workqueue(efx->workqueue); 2634 destroy_workqueue(efx->workqueue);
2633 efx->workqueue = NULL; 2635 efx->workqueue = NULL;
@@ -2699,12 +2701,12 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
2699 * always appear within the first 512 bytes. 2701 * always appear within the first 512 bytes.
2700 */ 2702 */
2701#define SFC_VPD_LEN 512 2703#define SFC_VPD_LEN 512
2702static void efx_print_product_vpd(struct efx_nic *efx) 2704static void efx_probe_vpd_strings(struct efx_nic *efx)
2703{ 2705{
2704 struct pci_dev *dev = efx->pci_dev; 2706 struct pci_dev *dev = efx->pci_dev;
2705 char vpd_data[SFC_VPD_LEN]; 2707 char vpd_data[SFC_VPD_LEN];
2706 ssize_t vpd_size; 2708 ssize_t vpd_size;
2707 int i, j; 2709 int ro_start, ro_size, i, j;
2708 2710
2709 /* Get the vpd data from the device */ 2711 /* Get the vpd data from the device */
2710 vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data); 2712 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 } 2716 }
2715 2717
2716 /* Get the Read only section */ 2718 /* Get the Read only section */
2717 i = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA); 2719 ro_start = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA);
2718 if (i < 0) { 2720 if (ro_start < 0) {
2719 netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n"); 2721 netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n");
2720 return; 2722 return;
2721 } 2723 }
2722 2724
2723 j = pci_vpd_lrdt_size(&vpd_data[i]); 2725 ro_size = pci_vpd_lrdt_size(&vpd_data[ro_start]);
2724 i += PCI_VPD_LRDT_TAG_SIZE; 2726 j = ro_size;
2727 i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
2725 if (i + j > vpd_size) 2728 if (i + j > vpd_size)
2726 j = vpd_size - i; 2729 j = vpd_size - i;
2727 2730
@@ -2741,6 +2744,27 @@ static void efx_print_product_vpd(struct efx_nic *efx)
2741 2744
2742 netif_info(efx, drv, efx->net_dev, 2745 netif_info(efx, drv, efx->net_dev,
2743 "Part Number : %.*s\n", j, &vpd_data[i]); 2746 "Part Number : %.*s\n", j, &vpd_data[i]);
2747
2748 i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
2749 j = ro_size;
2750 i = pci_vpd_find_info_keyword(vpd_data, i, j, "SN");
2751 if (i < 0) {
2752 netif_err(efx, drv, efx->net_dev, "Serial number not found\n");
2753 return;
2754 }
2755
2756 j = pci_vpd_info_field_size(&vpd_data[i]);
2757 i += PCI_VPD_INFO_FLD_HDR_SIZE;
2758 if (i + j > vpd_size) {
2759 netif_err(efx, drv, efx->net_dev, "Incomplete serial number\n");
2760 return;
2761 }
2762
2763 efx->vpd_sn = kmalloc(j + 1, GFP_KERNEL);
2764 if (!efx->vpd_sn)
2765 return;
2766
2767 snprintf(efx->vpd_sn, j + 1, "%s", &vpd_data[i]);
2744} 2768}
2745 2769
2746 2770
@@ -2837,7 +2861,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
2837 netif_info(efx, probe, efx->net_dev, 2861 netif_info(efx, probe, efx->net_dev,
2838 "Solarflare NIC detected\n"); 2862 "Solarflare NIC detected\n");
2839 2863
2840 efx_print_product_vpd(efx); 2864 efx_probe_vpd_strings(efx);
2841 2865
2842 /* Set up basic I/O (BAR mappings etc) */ 2866 /* Set up basic I/O (BAR mappings etc) */
2843 rc = efx_init_io(efx); 2867 rc = efx_init_io(efx);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 0d0e8eb88332..be8a616a1649 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -771,6 +771,7 @@ struct vfdi_status;
771 * @local_lock: Mutex protecting %local_addr_list and %local_page_list. 771 * @local_lock: Mutex protecting %local_addr_list and %local_page_list.
772 * @peer_work: Work item to broadcast peer addresses to VMs. 772 * @peer_work: Work item to broadcast peer addresses to VMs.
773 * @ptp_data: PTP state data 773 * @ptp_data: PTP state data
774 * @vpd_sn: Serial number read from VPD
774 * @monitor_work: Hardware monitor workitem 775 * @monitor_work: Hardware monitor workitem
775 * @biu_lock: BIU (bus interface unit) lock 776 * @biu_lock: BIU (bus interface unit) lock
776 * @last_irq_cpu: Last CPU to handle a possible test interrupt. This 777 * @last_irq_cpu: Last CPU to handle a possible test interrupt. This
@@ -920,6 +921,8 @@ struct efx_nic {
920 921
921 struct efx_ptp_data *ptp_data; 922 struct efx_ptp_data *ptp_data;
922 923
924 char *vpd_sn;
925
923 /* The following fields may be written more often */ 926 /* The following fields may be written more often */
924 927
925 struct delayed_work monitor_work ____cacheline_aligned_in_smp; 928 struct delayed_work monitor_work ____cacheline_aligned_in_smp;