diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2013-12-05 15:13:22 -0500 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2013-12-12 17:07:14 -0500 |
commit | ef215e64760ef6bd756c2999e7c8cee95b98e30a (patch) | |
tree | 016f4bea6a557f132808c118a0cad6360eea0740 | |
parent | bd9a265db26cdbfe74a303111381d90e66f56877 (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.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/net_driver.h | 3 |
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 |
2702 | static void efx_print_product_vpd(struct efx_nic *efx) | 2704 | static 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; |