Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2013 - 2018 Intel Corporation. */
0003 
0004 #include <linux/list.h>
0005 #include <linux/errno.h>
0006 
0007 #include "iavf.h"
0008 #include "iavf_prototype.h"
0009 #include "iavf_client.h"
0010 
0011 static
0012 const char iavf_client_interface_version_str[] = IAVF_CLIENT_VERSION_STR;
0013 static struct iavf_client *vf_registered_client;
0014 static LIST_HEAD(iavf_devices);
0015 static DEFINE_MUTEX(iavf_device_mutex);
0016 
0017 static u32 iavf_client_virtchnl_send(struct iavf_info *ldev,
0018                      struct iavf_client *client,
0019                      u8 *msg, u16 len);
0020 
0021 static int iavf_client_setup_qvlist(struct iavf_info *ldev,
0022                     struct iavf_client *client,
0023                     struct iavf_qvlist_info *qvlist_info);
0024 
0025 static struct iavf_ops iavf_lan_ops = {
0026     .virtchnl_send = iavf_client_virtchnl_send,
0027     .setup_qvlist = iavf_client_setup_qvlist,
0028 };
0029 
0030 /**
0031  * iavf_client_get_params - retrieve relevant client parameters
0032  * @vsi: VSI with parameters
0033  * @params: client param struct
0034  **/
0035 static
0036 void iavf_client_get_params(struct iavf_vsi *vsi, struct iavf_params *params)
0037 {
0038     int i;
0039 
0040     memset(params, 0, sizeof(struct iavf_params));
0041     params->mtu = vsi->netdev->mtu;
0042     params->link_up = vsi->back->link_up;
0043 
0044     for (i = 0; i < IAVF_MAX_USER_PRIORITY; i++) {
0045         params->qos.prio_qos[i].tc = 0;
0046         params->qos.prio_qos[i].qs_handle = vsi->qs_handle;
0047     }
0048 }
0049 
0050 /**
0051  * iavf_notify_client_message - call the client message receive callback
0052  * @vsi: the VSI associated with this client
0053  * @msg: message buffer
0054  * @len: length of message
0055  *
0056  * If there is a client to this VSI, call the client
0057  **/
0058 void iavf_notify_client_message(struct iavf_vsi *vsi, u8 *msg, u16 len)
0059 {
0060     struct iavf_client_instance *cinst;
0061 
0062     if (!vsi)
0063         return;
0064 
0065     cinst = vsi->back->cinst;
0066     if (!cinst || !cinst->client || !cinst->client->ops ||
0067         !cinst->client->ops->virtchnl_receive) {
0068         dev_dbg(&vsi->back->pdev->dev,
0069             "Cannot locate client instance virtchnl_receive function\n");
0070         return;
0071     }
0072     cinst->client->ops->virtchnl_receive(&cinst->lan_info,  cinst->client,
0073                          msg, len);
0074 }
0075 
0076 /**
0077  * iavf_notify_client_l2_params - call the client notify callback
0078  * @vsi: the VSI with l2 param changes
0079  *
0080  * If there is a client to this VSI, call the client
0081  **/
0082 void iavf_notify_client_l2_params(struct iavf_vsi *vsi)
0083 {
0084     struct iavf_client_instance *cinst;
0085     struct iavf_params params;
0086 
0087     if (!vsi)
0088         return;
0089 
0090     cinst = vsi->back->cinst;
0091 
0092     if (!cinst || !cinst->client || !cinst->client->ops ||
0093         !cinst->client->ops->l2_param_change) {
0094         dev_dbg(&vsi->back->pdev->dev,
0095             "Cannot locate client instance l2_param_change function\n");
0096         return;
0097     }
0098     iavf_client_get_params(vsi, &params);
0099     cinst->lan_info.params = params;
0100     cinst->client->ops->l2_param_change(&cinst->lan_info, cinst->client,
0101                         &params);
0102 }
0103 
0104 /**
0105  * iavf_notify_client_open - call the client open callback
0106  * @vsi: the VSI with netdev opened
0107  *
0108  * If there is a client to this netdev, call the client with open
0109  **/
0110 void iavf_notify_client_open(struct iavf_vsi *vsi)
0111 {
0112     struct iavf_adapter *adapter = vsi->back;
0113     struct iavf_client_instance *cinst = adapter->cinst;
0114     int ret;
0115 
0116     if (!cinst || !cinst->client || !cinst->client->ops ||
0117         !cinst->client->ops->open) {
0118         dev_dbg(&vsi->back->pdev->dev,
0119             "Cannot locate client instance open function\n");
0120         return;
0121     }
0122     if (!(test_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state))) {
0123         ret = cinst->client->ops->open(&cinst->lan_info, cinst->client);
0124         if (!ret)
0125             set_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state);
0126     }
0127 }
0128 
0129 /**
0130  * iavf_client_release_qvlist - send a message to the PF to release iwarp qv map
0131  * @ldev: pointer to L2 context.
0132  *
0133  * Return 0 on success or < 0 on error
0134  **/
0135 static int iavf_client_release_qvlist(struct iavf_info *ldev)
0136 {
0137     struct iavf_adapter *adapter = ldev->vf;
0138     enum iavf_status err;
0139 
0140     if (adapter->aq_required)
0141         return -EAGAIN;
0142 
0143     err = iavf_aq_send_msg_to_pf(&adapter->hw,
0144                      VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP,
0145                      IAVF_SUCCESS, NULL, 0, NULL);
0146 
0147     if (err)
0148         dev_err(&adapter->pdev->dev,
0149             "Unable to send iWarp vector release message to PF, error %d, aq status %d\n",
0150             err, adapter->hw.aq.asq_last_status);
0151 
0152     return err;
0153 }
0154 
0155 /**
0156  * iavf_notify_client_close - call the client close callback
0157  * @vsi: the VSI with netdev closed
0158  * @reset: true when close called due to reset pending
0159  *
0160  * If there is a client to this netdev, call the client with close
0161  **/
0162 void iavf_notify_client_close(struct iavf_vsi *vsi, bool reset)
0163 {
0164     struct iavf_adapter *adapter = vsi->back;
0165     struct iavf_client_instance *cinst = adapter->cinst;
0166 
0167     if (!cinst || !cinst->client || !cinst->client->ops ||
0168         !cinst->client->ops->close) {
0169         dev_dbg(&vsi->back->pdev->dev,
0170             "Cannot locate client instance close function\n");
0171         return;
0172     }
0173     cinst->client->ops->close(&cinst->lan_info, cinst->client, reset);
0174     iavf_client_release_qvlist(&cinst->lan_info);
0175     clear_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state);
0176 }
0177 
0178 /**
0179  * iavf_client_add_instance - add a client instance to the instance list
0180  * @adapter: pointer to the board struct
0181  *
0182  * Returns cinst ptr on success, NULL on failure
0183  **/
0184 static struct iavf_client_instance *
0185 iavf_client_add_instance(struct iavf_adapter *adapter)
0186 {
0187     struct iavf_client_instance *cinst = NULL;
0188     struct iavf_vsi *vsi = &adapter->vsi;
0189     struct netdev_hw_addr *mac = NULL;
0190     struct iavf_params params;
0191 
0192     if (!vf_registered_client)
0193         goto out;
0194 
0195     if (adapter->cinst) {
0196         cinst = adapter->cinst;
0197         goto out;
0198     }
0199 
0200     cinst = kzalloc(sizeof(*cinst), GFP_KERNEL);
0201     if (!cinst)
0202         goto out;
0203 
0204     cinst->lan_info.vf = (void *)adapter;
0205     cinst->lan_info.netdev = vsi->netdev;
0206     cinst->lan_info.pcidev = adapter->pdev;
0207     cinst->lan_info.fid = 0;
0208     cinst->lan_info.ftype = IAVF_CLIENT_FTYPE_VF;
0209     cinst->lan_info.hw_addr = adapter->hw.hw_addr;
0210     cinst->lan_info.ops = &iavf_lan_ops;
0211     cinst->lan_info.version.major = IAVF_CLIENT_VERSION_MAJOR;
0212     cinst->lan_info.version.minor = IAVF_CLIENT_VERSION_MINOR;
0213     cinst->lan_info.version.build = IAVF_CLIENT_VERSION_BUILD;
0214     iavf_client_get_params(vsi, &params);
0215     cinst->lan_info.params = params;
0216     set_bit(__IAVF_CLIENT_INSTANCE_NONE, &cinst->state);
0217 
0218     cinst->lan_info.msix_count = adapter->num_iwarp_msix;
0219     cinst->lan_info.msix_entries =
0220             &adapter->msix_entries[adapter->iwarp_base_vector];
0221 
0222     mac = list_first_entry(&cinst->lan_info.netdev->dev_addrs.list,
0223                    struct netdev_hw_addr, list);
0224     if (mac)
0225         ether_addr_copy(cinst->lan_info.lanmac, mac->addr);
0226     else
0227         dev_err(&adapter->pdev->dev, "MAC address list is empty!\n");
0228 
0229     cinst->client = vf_registered_client;
0230     adapter->cinst = cinst;
0231 out:
0232     return cinst;
0233 }
0234 
0235 /**
0236  * iavf_client_del_instance - removes a client instance from the list
0237  * @adapter: pointer to the board struct
0238  *
0239  **/
0240 static
0241 void iavf_client_del_instance(struct iavf_adapter *adapter)
0242 {
0243     kfree(adapter->cinst);
0244     adapter->cinst = NULL;
0245 }
0246 
0247 /**
0248  * iavf_client_subtask - client maintenance work
0249  * @adapter: board private structure
0250  **/
0251 void iavf_client_subtask(struct iavf_adapter *adapter)
0252 {
0253     struct iavf_client *client = vf_registered_client;
0254     struct iavf_client_instance *cinst;
0255     int ret = 0;
0256 
0257     if (adapter->state < __IAVF_DOWN)
0258         return;
0259 
0260     /* first check client is registered */
0261     if (!client)
0262         return;
0263 
0264     /* Add the client instance to the instance list */
0265     cinst = iavf_client_add_instance(adapter);
0266     if (!cinst)
0267         return;
0268 
0269     dev_info(&adapter->pdev->dev, "Added instance of Client %s\n",
0270          client->name);
0271 
0272     if (!test_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state)) {
0273         /* Send an Open request to the client */
0274 
0275         if (client->ops && client->ops->open)
0276             ret = client->ops->open(&cinst->lan_info, client);
0277         if (!ret)
0278             set_bit(__IAVF_CLIENT_INSTANCE_OPENED,
0279                 &cinst->state);
0280         else
0281             /* remove client instance */
0282             iavf_client_del_instance(adapter);
0283     }
0284 }
0285 
0286 /**
0287  * iavf_lan_add_device - add a lan device struct to the list of lan devices
0288  * @adapter: pointer to the board struct
0289  *
0290  * Returns 0 on success or none 0 on error
0291  **/
0292 int iavf_lan_add_device(struct iavf_adapter *adapter)
0293 {
0294     struct iavf_device *ldev;
0295     int ret = 0;
0296 
0297     mutex_lock(&iavf_device_mutex);
0298     list_for_each_entry(ldev, &iavf_devices, list) {
0299         if (ldev->vf == adapter) {
0300             ret = -EEXIST;
0301             goto out;
0302         }
0303     }
0304     ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
0305     if (!ldev) {
0306         ret = -ENOMEM;
0307         goto out;
0308     }
0309     ldev->vf = adapter;
0310     INIT_LIST_HEAD(&ldev->list);
0311     list_add(&ldev->list, &iavf_devices);
0312     dev_info(&adapter->pdev->dev, "Added LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
0313          adapter->hw.bus.bus_id, adapter->hw.bus.device,
0314          adapter->hw.bus.func);
0315 
0316     /* Since in some cases register may have happened before a device gets
0317      * added, we can schedule a subtask to go initiate the clients.
0318      */
0319     adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
0320 
0321 out:
0322     mutex_unlock(&iavf_device_mutex);
0323     return ret;
0324 }
0325 
0326 /**
0327  * iavf_lan_del_device - removes a lan device from the device list
0328  * @adapter: pointer to the board struct
0329  *
0330  * Returns 0 on success or non-0 on error
0331  **/
0332 int iavf_lan_del_device(struct iavf_adapter *adapter)
0333 {
0334     struct iavf_device *ldev, *tmp;
0335     int ret = -ENODEV;
0336 
0337     mutex_lock(&iavf_device_mutex);
0338     list_for_each_entry_safe(ldev, tmp, &iavf_devices, list) {
0339         if (ldev->vf == adapter) {
0340             dev_info(&adapter->pdev->dev,
0341                  "Deleted LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
0342                  adapter->hw.bus.bus_id, adapter->hw.bus.device,
0343                  adapter->hw.bus.func);
0344             list_del(&ldev->list);
0345             kfree(ldev);
0346             ret = 0;
0347             break;
0348         }
0349     }
0350 
0351     mutex_unlock(&iavf_device_mutex);
0352     return ret;
0353 }
0354 
0355 /**
0356  * iavf_client_release - release client specific resources
0357  * @client: pointer to the registered client
0358  *
0359  **/
0360 static void iavf_client_release(struct iavf_client *client)
0361 {
0362     struct iavf_client_instance *cinst;
0363     struct iavf_device *ldev;
0364     struct iavf_adapter *adapter;
0365 
0366     mutex_lock(&iavf_device_mutex);
0367     list_for_each_entry(ldev, &iavf_devices, list) {
0368         adapter = ldev->vf;
0369         cinst = adapter->cinst;
0370         if (!cinst)
0371             continue;
0372         if (test_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state)) {
0373             if (client->ops && client->ops->close)
0374                 client->ops->close(&cinst->lan_info, client,
0375                            false);
0376             iavf_client_release_qvlist(&cinst->lan_info);
0377             clear_bit(__IAVF_CLIENT_INSTANCE_OPENED, &cinst->state);
0378 
0379             dev_warn(&adapter->pdev->dev,
0380                  "Client %s instance closed\n", client->name);
0381         }
0382         /* delete the client instance */
0383         iavf_client_del_instance(adapter);
0384         dev_info(&adapter->pdev->dev, "Deleted client instance of Client %s\n",
0385              client->name);
0386     }
0387     mutex_unlock(&iavf_device_mutex);
0388 }
0389 
0390 /**
0391  * iavf_client_prepare - prepare client specific resources
0392  * @client: pointer to the registered client
0393  *
0394  **/
0395 static void iavf_client_prepare(struct iavf_client *client)
0396 {
0397     struct iavf_device *ldev;
0398     struct iavf_adapter *adapter;
0399 
0400     mutex_lock(&iavf_device_mutex);
0401     list_for_each_entry(ldev, &iavf_devices, list) {
0402         adapter = ldev->vf;
0403         /* Signal the watchdog to service the client */
0404         adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
0405     }
0406     mutex_unlock(&iavf_device_mutex);
0407 }
0408 
0409 /**
0410  * iavf_client_virtchnl_send - send a message to the PF instance
0411  * @ldev: pointer to L2 context.
0412  * @client: Client pointer.
0413  * @msg: pointer to message buffer
0414  * @len: message length
0415  *
0416  * Return 0 on success or < 0 on error
0417  **/
0418 static u32 iavf_client_virtchnl_send(struct iavf_info *ldev,
0419                      struct iavf_client *client,
0420                      u8 *msg, u16 len)
0421 {
0422     struct iavf_adapter *adapter = ldev->vf;
0423     enum iavf_status err;
0424 
0425     if (adapter->aq_required)
0426         return -EAGAIN;
0427 
0428     err = iavf_aq_send_msg_to_pf(&adapter->hw, VIRTCHNL_OP_IWARP,
0429                      IAVF_SUCCESS, msg, len, NULL);
0430     if (err)
0431         dev_err(&adapter->pdev->dev, "Unable to send iWarp message to PF, error %d, aq status %d\n",
0432             err, adapter->hw.aq.asq_last_status);
0433 
0434     return err;
0435 }
0436 
0437 /**
0438  * iavf_client_setup_qvlist - send a message to the PF to setup iwarp qv map
0439  * @ldev: pointer to L2 context.
0440  * @client: Client pointer.
0441  * @qvlist_info: queue and vector list
0442  *
0443  * Return 0 on success or < 0 on error
0444  **/
0445 static int iavf_client_setup_qvlist(struct iavf_info *ldev,
0446                     struct iavf_client *client,
0447                     struct iavf_qvlist_info *qvlist_info)
0448 {
0449     struct virtchnl_iwarp_qvlist_info *v_qvlist_info;
0450     struct iavf_adapter *adapter = ldev->vf;
0451     struct iavf_qv_info *qv_info;
0452     enum iavf_status err;
0453     u32 v_idx, i;
0454     size_t msg_size;
0455 
0456     if (adapter->aq_required)
0457         return -EAGAIN;
0458 
0459     /* A quick check on whether the vectors belong to the client */
0460     for (i = 0; i < qvlist_info->num_vectors; i++) {
0461         qv_info = &qvlist_info->qv_info[i];
0462         if (!qv_info)
0463             continue;
0464         v_idx = qv_info->v_idx;
0465         if ((v_idx >=
0466             (adapter->iwarp_base_vector + adapter->num_iwarp_msix)) ||
0467             (v_idx < adapter->iwarp_base_vector))
0468             return -EINVAL;
0469     }
0470 
0471     v_qvlist_info = (struct virtchnl_iwarp_qvlist_info *)qvlist_info;
0472     msg_size = struct_size(v_qvlist_info, qv_info,
0473                    v_qvlist_info->num_vectors - 1);
0474 
0475     adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP);
0476     err = iavf_aq_send_msg_to_pf(&adapter->hw,
0477                 VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP, IAVF_SUCCESS,
0478                 (u8 *)v_qvlist_info, msg_size, NULL);
0479 
0480     if (err) {
0481         dev_err(&adapter->pdev->dev,
0482             "Unable to send iWarp vector config message to PF, error %d, aq status %d\n",
0483             err, adapter->hw.aq.asq_last_status);
0484         goto out;
0485     }
0486 
0487     err = -EBUSY;
0488     for (i = 0; i < 5; i++) {
0489         msleep(100);
0490         if (!(adapter->client_pending &
0491               BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP))) {
0492             err = 0;
0493             break;
0494         }
0495     }
0496 out:
0497     return err;
0498 }
0499 
0500 /**
0501  * iavf_register_client - Register a iavf client driver with the L2 driver
0502  * @client: pointer to the iavf_client struct
0503  *
0504  * Returns 0 on success or non-0 on error
0505  **/
0506 int iavf_register_client(struct iavf_client *client)
0507 {
0508     int ret = 0;
0509 
0510     if (!client) {
0511         ret = -EIO;
0512         goto out;
0513     }
0514 
0515     if (strlen(client->name) == 0) {
0516         pr_info("iavf: Failed to register client with no name\n");
0517         ret = -EIO;
0518         goto out;
0519     }
0520 
0521     if (vf_registered_client) {
0522         pr_info("iavf: Client %s has already been registered!\n",
0523             client->name);
0524         ret = -EEXIST;
0525         goto out;
0526     }
0527 
0528     if ((client->version.major != IAVF_CLIENT_VERSION_MAJOR) ||
0529         (client->version.minor != IAVF_CLIENT_VERSION_MINOR)) {
0530         pr_info("iavf: Failed to register client %s due to mismatched client interface version\n",
0531             client->name);
0532         pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n",
0533             client->version.major, client->version.minor,
0534             client->version.build,
0535             iavf_client_interface_version_str);
0536         ret = -EIO;
0537         goto out;
0538     }
0539 
0540     vf_registered_client = client;
0541 
0542     iavf_client_prepare(client);
0543 
0544     pr_info("iavf: Registered client %s with return code %d\n",
0545         client->name, ret);
0546 out:
0547     return ret;
0548 }
0549 EXPORT_SYMBOL(iavf_register_client);
0550 
0551 /**
0552  * iavf_unregister_client - Unregister a iavf client driver with the L2 driver
0553  * @client: pointer to the iavf_client struct
0554  *
0555  * Returns 0 on success or non-0 on error
0556  **/
0557 int iavf_unregister_client(struct iavf_client *client)
0558 {
0559     int ret = 0;
0560 
0561     /* When a unregister request comes through we would have to send
0562      * a close for each of the client instances that were opened.
0563      * client_release function is called to handle this.
0564      */
0565     iavf_client_release(client);
0566 
0567     if (vf_registered_client != client) {
0568         pr_info("iavf: Client %s has not been registered\n",
0569             client->name);
0570         ret = -ENODEV;
0571         goto out;
0572     }
0573     vf_registered_client = NULL;
0574     pr_info("iavf: Unregistered client %s\n", client->name);
0575 out:
0576     return ret;
0577 }
0578 EXPORT_SYMBOL(iavf_unregister_client);