Skip to content

Commit 4e6759b

Browse files
Desnes Augusto Nunes do Rosariodavem330
authored andcommitted
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 <[email protected]> Signed-off-by: Thomas Falcon <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fbec443 commit 4e6759b

File tree

2 files changed

+176
-4
lines changed

2 files changed

+176
-4
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 151 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,15 @@ static int reset_tx_pools(struct ibmvnic_adapter *adapter)
574574
return 0;
575575
}
576576

577+
static 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+
577586
static void release_tx_pools(struct ibmvnic_adapter *adapter)
578587
{
579588
struct ibmvnic_tx_pool *tx_pool;
@@ -754,6 +763,8 @@ static void release_resources(struct ibmvnic_adapter *adapter)
754763
{
755764
int i;
756765

766+
release_vpd_data(adapter);
767+
757768
release_tx_pools(adapter);
758769
release_rx_pools(adapter);
759770

@@ -834,6 +845,57 @@ static int set_real_num_queues(struct net_device *netdev)
834845
return rc;
835846
}
836847

848+
static 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+
837899
static int init_resources(struct ibmvnic_adapter *adapter)
838900
{
839901
struct net_device *netdev = adapter->netdev;
@@ -851,6 +913,10 @@ static int init_resources(struct ibmvnic_adapter *adapter)
851913
if (rc)
852914
return rc;
853915

916+
adapter->vpd = kzalloc(sizeof(*adapter->vpd), GFP_KERNEL);
917+
if (!adapter->vpd)
918+
return -ENOMEM;
919+
854920
adapter->map_id = 1;
855921
adapter->napi = kcalloc(adapter->req_rx_queues,
856922
sizeof(struct napi_struct), GFP_KERNEL);
@@ -924,7 +990,7 @@ static int __ibmvnic_open(struct net_device *netdev)
924990
static int ibmvnic_open(struct net_device *netdev)
925991
{
926992
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
927-
int rc;
993+
int rc, vpd;
928994

929995
mutex_lock(&adapter->reset_lock);
930996

@@ -951,6 +1017,12 @@ static int ibmvnic_open(struct net_device *netdev)
9511017

9521018
rc = __ibmvnic_open(netdev);
9531019
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+
9541026
mutex_unlock(&adapter->reset_lock);
9551027

9561028
return rc;
@@ -1879,11 +1951,15 @@ static int ibmvnic_get_link_ksettings(struct net_device *netdev,
18791951
return 0;
18801952
}
18811953

1882-
static void ibmvnic_get_drvinfo(struct net_device *dev,
1954+
static void ibmvnic_get_drvinfo(struct net_device *netdev,
18831955
struct ethtool_drvinfo *info)
18841956
{
1957+
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
1958+
18851959
strlcpy(info->driver, ibmvnic_driver_name, sizeof(info->driver));
18861960
strlcpy(info->version, IBMVNIC_DRIVER_VERSION, sizeof(info->version));
1961+
strlcpy(info->fw_version, adapter->fw_version,
1962+
sizeof(info->fw_version));
18871963
}
18881964

18891965
static u32 ibmvnic_get_msglevel(struct net_device *netdev)
@@ -3140,6 +3216,73 @@ static void send_cap_queries(struct ibmvnic_adapter *adapter)
31403216
ibmvnic_send_crq(adapter, &crq);
31413217
}
31423218

3219+
static 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+
3235+
static 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+
3282+
complete:
3283+
complete(&adapter->fw_done);
3284+
}
3285+
31433286
static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
31443287
{
31453288
struct device *dev = &adapter->vdev->dev;
@@ -3871,6 +4014,12 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
38714014
netdev_dbg(netdev, "Got Collect firmware trace Response\n");
38724015
complete(&adapter->fw_done);
38734016
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;
38744023
default:
38754024
netdev_err(netdev, "Got an invalid cmd type 0x%02x\n",
38764025
gen_crq->cmd);

drivers/net/ethernet/ibm/ibmvnic.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,12 @@ struct ibmvnic_multicast_ctrl {
560560
struct ibmvnic_rc rc;
561561
} __packed __aligned(8);
562562

563+
struct ibmvnic_get_vpd_size {
564+
u8 first;
565+
u8 cmd;
566+
u8 reserved[14];
567+
} __packed __aligned(8);
568+
563569
struct ibmvnic_get_vpd_size_rsp {
564570
u8 first;
565571
u8 cmd;
@@ -577,6 +583,13 @@ struct ibmvnic_get_vpd {
577583
u8 reserved[4];
578584
} __packed __aligned(8);
579585

586+
struct ibmvnic_get_vpd_rsp {
587+
u8 first;
588+
u8 cmd;
589+
u8 reserved[10];
590+
struct ibmvnic_rc rc;
591+
} __packed __aligned(8);
592+
580593
struct ibmvnic_acl_change_indication {
581594
u8 first;
582595
u8 cmd;
@@ -702,10 +715,10 @@ union ibmvnic_crq {
702715
struct ibmvnic_change_mac_addr change_mac_addr_rsp;
703716
struct ibmvnic_multicast_ctrl multicast_ctrl;
704717
struct ibmvnic_multicast_ctrl multicast_ctrl_rsp;
705-
struct ibmvnic_generic_crq get_vpd_size;
718+
struct ibmvnic_get_vpd_size get_vpd_size;
706719
struct ibmvnic_get_vpd_size_rsp get_vpd_size_rsp;
707720
struct ibmvnic_get_vpd get_vpd;
708-
struct ibmvnic_generic_crq get_vpd_rsp;
721+
struct ibmvnic_get_vpd_rsp get_vpd_rsp;
709722
struct ibmvnic_acl_change_indication acl_change_indication;
710723
struct ibmvnic_acl_query acl_query;
711724
struct ibmvnic_generic_crq acl_query_rsp;
@@ -939,6 +952,12 @@ struct ibmvnic_error_buff {
939952
__be32 error_id;
940953
};
941954

955+
struct ibmvnic_vpd {
956+
unsigned char *buff;
957+
dma_addr_t dma_addr;
958+
u64 len;
959+
};
960+
942961
enum vnic_state {VNIC_PROBING = 1,
943962
VNIC_PROBED,
944963
VNIC_OPENING,
@@ -980,6 +999,10 @@ struct ibmvnic_adapter {
980999
dma_addr_t ip_offload_ctrl_tok;
9811000
u32 msg_enable;
9821001

1002+
/* Vital Product Data (VPD) */
1003+
struct ibmvnic_vpd *vpd;
1004+
char fw_version[32];
1005+
9831006
/* Statistics */
9841007
struct ibmvnic_statistics stats;
9851008
dma_addr_t stats_token;

0 commit comments

Comments
 (0)