aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/ibm/ibmvnic.c
diff options
context:
space:
mode:
authorDesnes Augusto Nunes do Rosario <desnesn@linux.vnet.ibm.com>2017-11-13 12:59:19 -0500
committerDavid S. Miller <davem@davemloft.net>2017-11-14 07:55:50 -0500
commit4e6759be28e4e69c397ab58c1e780b0a15d8a6fd (patch)
tree5ef0eea58a23a618531834daa9eba5fd2d150361 /drivers/net/ethernet/ibm/ibmvnic.c
parentfbec443bfe44f58a40e00962e969b5a9cafde457 (diff)
ibmvnic: Feature implementation of Vital Product Data (VPD) for the ibmvnic driver
This patch implements and enables VDP support for the ibmvnic driver. Moreover, it includes the implementation of suitable structs, signal transmission/handling and functions which allows the retrival of firmware information from the ibmvnic card through the ethtool command. Signed-off-by: Desnes A. Nunes do Rosario <desnesn@linux.vnet.ibm.com> Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/ibm/ibmvnic.c')
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c153
1 files changed, 151 insertions, 2 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index b918bc2f2e4f..04aaacbc3d45 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -574,6 +574,15 @@ static int reset_tx_pools(struct ibmvnic_adapter *adapter)
574 return 0; 574 return 0;
575} 575}
576 576
577static void release_vpd_data(struct ibmvnic_adapter *adapter)
578{
579 if (!adapter->vpd)
580 return;
581
582 kfree(adapter->vpd->buff);
583 kfree(adapter->vpd);
584}
585
577static void release_tx_pools(struct ibmvnic_adapter *adapter) 586static void release_tx_pools(struct ibmvnic_adapter *adapter)
578{ 587{
579 struct ibmvnic_tx_pool *tx_pool; 588 struct ibmvnic_tx_pool *tx_pool;
@@ -754,6 +763,8 @@ static void release_resources(struct ibmvnic_adapter *adapter)
754{ 763{
755 int i; 764 int i;
756 765
766 release_vpd_data(adapter);
767
757 release_tx_pools(adapter); 768 release_tx_pools(adapter);
758 release_rx_pools(adapter); 769 release_rx_pools(adapter);
759 770
@@ -834,6 +845,57 @@ static int set_real_num_queues(struct net_device *netdev)
834 return rc; 845 return rc;
835} 846}
836 847
848static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
849{
850 struct device *dev = &adapter->vdev->dev;
851 union ibmvnic_crq crq;
852 dma_addr_t dma_addr;
853 int len = 0;
854
855 if (adapter->vpd->buff)
856 len = adapter->vpd->len;
857
858 reinit_completion(&adapter->fw_done);
859 crq.get_vpd_size.first = IBMVNIC_CRQ_CMD;
860 crq.get_vpd_size.cmd = GET_VPD_SIZE;
861 ibmvnic_send_crq(adapter, &crq);
862 wait_for_completion(&adapter->fw_done);
863
864 if (!adapter->vpd->len)
865 return -ENODATA;
866
867 if (!adapter->vpd->buff)
868 adapter->vpd->buff = kzalloc(adapter->vpd->len, GFP_KERNEL);
869 else if (adapter->vpd->len != len)
870 adapter->vpd->buff =
871 krealloc(adapter->vpd->buff,
872 adapter->vpd->len, GFP_KERNEL);
873
874 if (!adapter->vpd->buff) {
875 dev_err(dev, "Could allocate VPD buffer\n");
876 return -ENOMEM;
877 }
878
879 adapter->vpd->dma_addr =
880 dma_map_single(dev, adapter->vpd->buff, adapter->vpd->len,
881 DMA_FROM_DEVICE);
882 if (dma_mapping_error(dev, dma_addr)) {
883 dev_err(dev, "Could not map VPD buffer\n");
884 kfree(adapter->vpd->buff);
885 return -ENOMEM;
886 }
887
888 reinit_completion(&adapter->fw_done);
889 crq.get_vpd.first = IBMVNIC_CRQ_CMD;
890 crq.get_vpd.cmd = GET_VPD;
891 crq.get_vpd.ioba = cpu_to_be32(adapter->vpd->dma_addr);
892 crq.get_vpd.len = cpu_to_be32((u32)adapter->vpd->len);
893 ibmvnic_send_crq(adapter, &crq);
894 wait_for_completion(&adapter->fw_done);
895
896 return 0;
897}
898
837static int init_resources(struct ibmvnic_adapter *adapter) 899static int init_resources(struct ibmvnic_adapter *adapter)
838{ 900{
839 struct net_device *netdev = adapter->netdev; 901 struct net_device *netdev = adapter->netdev;
@@ -851,6 +913,10 @@ static int init_resources(struct ibmvnic_adapter *adapter)
851 if (rc) 913 if (rc)
852 return rc; 914 return rc;
853 915
916 adapter->vpd = kzalloc(sizeof(*adapter->vpd), GFP_KERNEL);
917 if (!adapter->vpd)
918 return -ENOMEM;
919
854 adapter->map_id = 1; 920 adapter->map_id = 1;
855 adapter->napi = kcalloc(adapter->req_rx_queues, 921 adapter->napi = kcalloc(adapter->req_rx_queues,
856 sizeof(struct napi_struct), GFP_KERNEL); 922 sizeof(struct napi_struct), GFP_KERNEL);
@@ -924,7 +990,7 @@ static int __ibmvnic_open(struct net_device *netdev)
924static int ibmvnic_open(struct net_device *netdev) 990static int ibmvnic_open(struct net_device *netdev)
925{ 991{
926 struct ibmvnic_adapter *adapter = netdev_priv(netdev); 992 struct ibmvnic_adapter *adapter = netdev_priv(netdev);
927 int rc; 993 int rc, vpd;
928 994
929 mutex_lock(&adapter->reset_lock); 995 mutex_lock(&adapter->reset_lock);
930 996
@@ -951,6 +1017,12 @@ static int ibmvnic_open(struct net_device *netdev)
951 1017
952 rc = __ibmvnic_open(netdev); 1018 rc = __ibmvnic_open(netdev);
953 netif_carrier_on(netdev); 1019 netif_carrier_on(netdev);
1020
1021 /* Vital Product Data (VPD) */
1022 vpd = ibmvnic_get_vpd(adapter);
1023 if (vpd)
1024 netdev_err(netdev, "failed to initialize Vital Product Data (VPD)\n");
1025
954 mutex_unlock(&adapter->reset_lock); 1026 mutex_unlock(&adapter->reset_lock);
955 1027
956 return rc; 1028 return rc;
@@ -1879,11 +1951,15 @@ static int ibmvnic_get_link_ksettings(struct net_device *netdev,
1879 return 0; 1951 return 0;
1880} 1952}
1881 1953
1882static void ibmvnic_get_drvinfo(struct net_device *dev, 1954static void ibmvnic_get_drvinfo(struct net_device *netdev,
1883 struct ethtool_drvinfo *info) 1955 struct ethtool_drvinfo *info)
1884{ 1956{
1957 struct ibmvnic_adapter *adapter = netdev_priv(netdev);
1958
1885 strlcpy(info->driver, ibmvnic_driver_name, sizeof(info->driver)); 1959 strlcpy(info->driver, ibmvnic_driver_name, sizeof(info->driver));
1886 strlcpy(info->version, IBMVNIC_DRIVER_VERSION, sizeof(info->version)); 1960 strlcpy(info->version, IBMVNIC_DRIVER_VERSION, sizeof(info->version));
1961 strlcpy(info->fw_version, adapter->fw_version,
1962 sizeof(info->fw_version));
1887} 1963}
1888 1964
1889static u32 ibmvnic_get_msglevel(struct net_device *netdev) 1965static u32 ibmvnic_get_msglevel(struct net_device *netdev)
@@ -3140,6 +3216,73 @@ static void send_cap_queries(struct ibmvnic_adapter *adapter)
3140 ibmvnic_send_crq(adapter, &crq); 3216 ibmvnic_send_crq(adapter, &crq);
3141} 3217}
3142 3218
3219static void handle_vpd_size_rsp(union ibmvnic_crq *crq,
3220 struct ibmvnic_adapter *adapter)
3221{
3222 struct device *dev = &adapter->vdev->dev;
3223
3224 if (crq->get_vpd_size_rsp.rc.code) {
3225 dev_err(dev, "Error retrieving VPD size, rc=%x\n",
3226 crq->get_vpd_size_rsp.rc.code);
3227 complete(&adapter->fw_done);
3228 return;
3229 }
3230
3231 adapter->vpd->len = be64_to_cpu(crq->get_vpd_size_rsp.len);
3232 complete(&adapter->fw_done);
3233}
3234
3235static void handle_vpd_rsp(union ibmvnic_crq *crq,
3236 struct ibmvnic_adapter *adapter)
3237{
3238 struct device *dev = &adapter->vdev->dev;
3239 unsigned char *substr = NULL, *ptr = NULL;
3240 u8 fw_level_len = 0;
3241
3242 memset(adapter->fw_version, 0, 32);
3243
3244 dma_unmap_single(dev, adapter->vpd->dma_addr, adapter->vpd->len,
3245 DMA_FROM_DEVICE);
3246
3247 if (crq->get_vpd_rsp.rc.code) {
3248 dev_err(dev, "Error retrieving VPD from device, rc=%x\n",
3249 crq->get_vpd_rsp.rc.code);
3250 goto complete;
3251 }
3252
3253 /* get the position of the firmware version info
3254 * located after the ASCII 'RM' substring in the buffer
3255 */
3256 substr = strnstr(adapter->vpd->buff, "RM", adapter->vpd->len);
3257 if (!substr) {
3258 dev_info(dev, "No FW level provided by VPD\n");
3259 goto complete;
3260 }
3261
3262 /* get length of firmware level ASCII substring */
3263 if ((substr + 2) < (adapter->vpd->buff + adapter->vpd->len)) {
3264 fw_level_len = *(substr + 2);
3265 } else {
3266 dev_info(dev, "Length of FW substr extrapolated VDP buff\n");
3267 goto complete;
3268 }
3269
3270 /* copy firmware version string from vpd into adapter */
3271 if ((substr + 3 + fw_level_len) <
3272 (adapter->vpd->buff + adapter->vpd->len)) {
3273 ptr = strncpy((char *)adapter->fw_version,
3274 substr + 3, fw_level_len);
3275
3276 if (!ptr)
3277 dev_err(dev, "Failed to isolate FW level string\n");
3278 } else {
3279 dev_info(dev, "FW substr extrapolated VPD buff\n");
3280 }
3281
3282complete:
3283 complete(&adapter->fw_done);
3284}
3285
3143static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter) 3286static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
3144{ 3287{
3145 struct device *dev = &adapter->vdev->dev; 3288 struct device *dev = &adapter->vdev->dev;
@@ -3871,6 +4014,12 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
3871 netdev_dbg(netdev, "Got Collect firmware trace Response\n"); 4014 netdev_dbg(netdev, "Got Collect firmware trace Response\n");
3872 complete(&adapter->fw_done); 4015 complete(&adapter->fw_done);
3873 break; 4016 break;
4017 case GET_VPD_SIZE_RSP:
4018 handle_vpd_size_rsp(crq, adapter);
4019 break;
4020 case GET_VPD_RSP:
4021 handle_vpd_rsp(crq, adapter);
4022 break;
3874 default: 4023 default:
3875 netdev_err(netdev, "Got an invalid cmd type 0x%02x\n", 4024 netdev_err(netdev, "Got an invalid cmd type 0x%02x\n",
3876 gen_crq->cmd); 4025 gen_crq->cmd);