linux/drivers/net/ethernet/intel/iavf/iavf_client.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2013 - 2018 Intel Corporation. */
   3
   4#include <linux/list.h>
   5#include <linux/errno.h>
   6
   7#include "iavf.h"
   8#include "iavf_prototype.h"
   9#include "iavf_client.h"
  10
  11static
  12const char iavf_client_interface_version_str[] = IAVF_CLIENT_VERSION_STR;
  13static struct i40e_client *vf_registered_client;
  14static LIST_HEAD(i40e_devices);
  15static DEFINE_MUTEX(iavf_device_mutex);
  16
  17static u32 iavf_client_virtchnl_send(struct i40e_info *ldev,
  18                                     struct i40e_client *client,
  19                                     u8 *msg, u16 len);
  20
  21static int iavf_client_setup_qvlist(struct i40e_info *ldev,
  22                                    struct i40e_client *client,
  23                                    struct i40e_qvlist_info *qvlist_info);
  24
  25static struct i40e_ops iavf_lan_ops = {
  26        .virtchnl_send = iavf_client_virtchnl_send,
  27        .setup_qvlist = iavf_client_setup_qvlist,
  28};
  29
  30/**
  31 * iavf_client_get_params - retrieve relevant client parameters
  32 * @vsi: VSI with parameters
  33 * @params: client param struct
  34 **/
  35static
  36void iavf_client_get_params(struct iavf_vsi *vsi, struct i40e_params *params)
  37{
  38        int i;
  39
  40        memset(params, 0, sizeof(struct i40e_params));
  41        params->mtu = vsi->netdev->mtu;
  42        params->link_up = vsi->back->link_up;
  43
  44        for (i = 0; i < IAVF_MAX_USER_PRIORITY; i++) {
  45                params->qos.prio_qos[i].tc = 0;
  46                params->qos.prio_qos[i].qs_handle = vsi->qs_handle;
  47        }
  48}
  49
  50/**
  51 * iavf_notify_client_message - call the client message receive callback
  52 * @vsi: the VSI associated with this client
  53 * @msg: message buffer
  54 * @len: length of message
  55 *
  56 * If there is a client to this VSI, call the client
  57 **/
  58void iavf_notify_client_message(struct iavf_vsi *vsi, u8 *msg, u16 len)
  59{
  60        struct i40e_client_instance *cinst;
  61
  62        if (!vsi)
  63                return;
  64
  65        cinst = vsi->back->cinst;
  66        if (!cinst || !cinst->client || !cinst->client->ops ||
  67            !cinst->client->ops->virtchnl_receive) {
  68                dev_dbg(&vsi->back->pdev->dev,
  69                        "Cannot locate client instance virtchnl_receive function\n");
  70                return;
  71        }
  72        cinst->client->ops->virtchnl_receive(&cinst->lan_info,  cinst->client,
  73                                             msg, len);
  74}
  75
  76/**
  77 * iavf_notify_client_l2_params - call the client notify callback
  78 * @vsi: the VSI with l2 param changes
  79 *
  80 * If there is a client to this VSI, call the client
  81 **/
  82void iavf_notify_client_l2_params(struct iavf_vsi *vsi)
  83{
  84        struct i40e_client_instance *cinst;
  85        struct i40e_params params;
  86
  87        if (!vsi)
  88                return;
  89
  90        cinst = vsi->back->cinst;
  91
  92        if (!cinst || !cinst->client || !cinst->client->ops ||
  93            !cinst->client->ops->l2_param_change) {
  94                dev_dbg(&vsi->back->pdev->dev,
  95                        "Cannot locate client instance l2_param_change function\n");
  96                return;
  97        }
  98        iavf_client_get_params(vsi, &params);
  99        cinst->lan_info.params = params;
 100        cinst->client->ops->l2_param_change(&cinst->lan_info, cinst->client,
 101                                            &params);
 102}
 103
 104/**
 105 * iavf_notify_client_open - call the client open callback
 106 * @vsi: the VSI with netdev opened
 107 *
 108 * If there is a client to this netdev, call the client with open
 109 **/
 110void iavf_notify_client_open(struct iavf_vsi *vsi)
 111{
 112        struct iavf_adapter *adapter = vsi->back;
 113        struct i40e_client_instance *cinst = adapter->cinst;
 114        int ret;
 115
 116        if (!cinst || !cinst->client || !cinst->client->ops ||
 117            !cinst->client->ops->open) {
 118                dev_dbg(&vsi->back->pdev->dev,
 119                        "Cannot locate client instance open function\n");
 120                return;
 121        }
 122        if (!(test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state))) {
 123                ret = cinst->client->ops->open(&cinst->lan_info, cinst->client);
 124                if (!ret)
 125                        set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
 126        }
 127}
 128
 129/**
 130 * iavf_client_release_qvlist - send a message to the PF to release iwarp qv map
 131 * @ldev: pointer to L2 context.
 132 *
 133 * Return 0 on success or < 0 on error
 134 **/
 135static int iavf_client_release_qvlist(struct i40e_info *ldev)
 136{
 137        struct iavf_adapter *adapter = ldev->vf;
 138        iavf_status err;
 139
 140        if (adapter->aq_required)
 141                return -EAGAIN;
 142
 143        err = iavf_aq_send_msg_to_pf(&adapter->hw,
 144                                     VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP,
 145                                     I40E_SUCCESS, NULL, 0, NULL);
 146
 147        if (err)
 148                dev_err(&adapter->pdev->dev,
 149                        "Unable to send iWarp vector release message to PF, error %d, aq status %d\n",
 150                        err, adapter->hw.aq.asq_last_status);
 151
 152        return err;
 153}
 154
 155/**
 156 * iavf_notify_client_close - call the client close callback
 157 * @vsi: the VSI with netdev closed
 158 * @reset: true when close called due to reset pending
 159 *
 160 * If there is a client to this netdev, call the client with close
 161 **/
 162void iavf_notify_client_close(struct iavf_vsi *vsi, bool reset)
 163{
 164        struct iavf_adapter *adapter = vsi->back;
 165        struct i40e_client_instance *cinst = adapter->cinst;
 166
 167        if (!cinst || !cinst->client || !cinst->client->ops ||
 168            !cinst->client->ops->close) {
 169                dev_dbg(&vsi->back->pdev->dev,
 170                        "Cannot locate client instance close function\n");
 171                return;
 172        }
 173        cinst->client->ops->close(&cinst->lan_info, cinst->client, reset);
 174        iavf_client_release_qvlist(&cinst->lan_info);
 175        clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
 176}
 177
 178/**
 179 * iavf_client_add_instance - add a client instance to the instance list
 180 * @adapter: pointer to the board struct
 181 *
 182 * Returns cinst ptr on success, NULL on failure
 183 **/
 184static struct i40e_client_instance *
 185iavf_client_add_instance(struct iavf_adapter *adapter)
 186{
 187        struct i40e_client_instance *cinst = NULL;
 188        struct iavf_vsi *vsi = &adapter->vsi;
 189        struct netdev_hw_addr *mac = NULL;
 190        struct i40e_params params;
 191
 192        if (!vf_registered_client)
 193                goto out;
 194
 195        if (adapter->cinst) {
 196                cinst = adapter->cinst;
 197                goto out;
 198        }
 199
 200        cinst = kzalloc(sizeof(*cinst), GFP_KERNEL);
 201        if (!cinst)
 202                goto out;
 203
 204        cinst->lan_info.vf = (void *)adapter;
 205        cinst->lan_info.netdev = vsi->netdev;
 206        cinst->lan_info.pcidev = adapter->pdev;
 207        cinst->lan_info.fid = 0;
 208        cinst->lan_info.ftype = I40E_CLIENT_FTYPE_VF;
 209        cinst->lan_info.hw_addr = adapter->hw.hw_addr;
 210        cinst->lan_info.ops = &iavf_lan_ops;
 211        cinst->lan_info.version.major = IAVF_CLIENT_VERSION_MAJOR;
 212        cinst->lan_info.version.minor = IAVF_CLIENT_VERSION_MINOR;
 213        cinst->lan_info.version.build = IAVF_CLIENT_VERSION_BUILD;
 214        iavf_client_get_params(vsi, &params);
 215        cinst->lan_info.params = params;
 216        set_bit(__I40E_CLIENT_INSTANCE_NONE, &cinst->state);
 217
 218        cinst->lan_info.msix_count = adapter->num_iwarp_msix;
 219        cinst->lan_info.msix_entries =
 220                        &adapter->msix_entries[adapter->iwarp_base_vector];
 221
 222        mac = list_first_entry(&cinst->lan_info.netdev->dev_addrs.list,
 223                               struct netdev_hw_addr, list);
 224        if (mac)
 225                ether_addr_copy(cinst->lan_info.lanmac, mac->addr);
 226        else
 227                dev_err(&adapter->pdev->dev, "MAC address list is empty!\n");
 228
 229        cinst->client = vf_registered_client;
 230        adapter->cinst = cinst;
 231out:
 232        return cinst;
 233}
 234
 235/**
 236 * iavf_client_del_instance - removes a client instance from the list
 237 * @adapter: pointer to the board struct
 238 *
 239 **/
 240static
 241void iavf_client_del_instance(struct iavf_adapter *adapter)
 242{
 243        kfree(adapter->cinst);
 244        adapter->cinst = NULL;
 245}
 246
 247/**
 248 * iavf_client_subtask - client maintenance work
 249 * @adapter: board private structure
 250 **/
 251void iavf_client_subtask(struct iavf_adapter *adapter)
 252{
 253        struct i40e_client *client = vf_registered_client;
 254        struct i40e_client_instance *cinst;
 255        int ret = 0;
 256
 257        if (adapter->state < __IAVF_DOWN)
 258                return;
 259
 260        /* first check client is registered */
 261        if (!client)
 262                return;
 263
 264        /* Add the client instance to the instance list */
 265        cinst = iavf_client_add_instance(adapter);
 266        if (!cinst)
 267                return;
 268
 269        dev_info(&adapter->pdev->dev, "Added instance of Client %s\n",
 270                 client->name);
 271
 272        if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {
 273                /* Send an Open request to the client */
 274
 275                if (client->ops && client->ops->open)
 276                        ret = client->ops->open(&cinst->lan_info, client);
 277                if (!ret)
 278                        set_bit(__I40E_CLIENT_INSTANCE_OPENED,
 279                                &cinst->state);
 280                else
 281                        /* remove client instance */
 282                        iavf_client_del_instance(adapter);
 283        }
 284}
 285
 286/**
 287 * iavf_lan_add_device - add a lan device struct to the list of lan devices
 288 * @adapter: pointer to the board struct
 289 *
 290 * Returns 0 on success or none 0 on error
 291 **/
 292int iavf_lan_add_device(struct iavf_adapter *adapter)
 293{
 294        struct i40e_device *ldev;
 295        int ret = 0;
 296
 297        mutex_lock(&iavf_device_mutex);
 298        list_for_each_entry(ldev, &i40e_devices, list) {
 299                if (ldev->vf == adapter) {
 300                        ret = -EEXIST;
 301                        goto out;
 302                }
 303        }
 304        ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
 305        if (!ldev) {
 306                ret = -ENOMEM;
 307                goto out;
 308        }
 309        ldev->vf = adapter;
 310        INIT_LIST_HEAD(&ldev->list);
 311        list_add(&ldev->list, &i40e_devices);
 312        dev_info(&adapter->pdev->dev, "Added LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
 313                 adapter->hw.bus.bus_id, adapter->hw.bus.device,
 314                 adapter->hw.bus.func);
 315
 316        /* Since in some cases register may have happened before a device gets
 317         * added, we can schedule a subtask to go initiate the clients.
 318         */
 319        adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
 320
 321out:
 322        mutex_unlock(&iavf_device_mutex);
 323        return ret;
 324}
 325
 326/**
 327 * iavf_lan_del_device - removes a lan device from the device list
 328 * @adapter: pointer to the board struct
 329 *
 330 * Returns 0 on success or non-0 on error
 331 **/
 332int iavf_lan_del_device(struct iavf_adapter *adapter)
 333{
 334        struct i40e_device *ldev, *tmp;
 335        int ret = -ENODEV;
 336
 337        mutex_lock(&iavf_device_mutex);
 338        list_for_each_entry_safe(ldev, tmp, &i40e_devices, list) {
 339                if (ldev->vf == adapter) {
 340                        dev_info(&adapter->pdev->dev,
 341                                 "Deleted LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
 342                                 adapter->hw.bus.bus_id, adapter->hw.bus.device,
 343                                 adapter->hw.bus.func);
 344                        list_del(&ldev->list);
 345                        kfree(ldev);
 346                        ret = 0;
 347                        break;
 348                }
 349        }
 350
 351        mutex_unlock(&iavf_device_mutex);
 352        return ret;
 353}
 354
 355/**
 356 * iavf_client_release - release client specific resources
 357 * @client: pointer to the registered client
 358 *
 359 **/
 360static void iavf_client_release(struct i40e_client *client)
 361{
 362        struct i40e_client_instance *cinst;
 363        struct i40e_device *ldev;
 364        struct iavf_adapter *adapter;
 365
 366        mutex_lock(&iavf_device_mutex);
 367        list_for_each_entry(ldev, &i40e_devices, list) {
 368                adapter = ldev->vf;
 369                cinst = adapter->cinst;
 370                if (!cinst)
 371                        continue;
 372                if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {
 373                        if (client->ops && client->ops->close)
 374                                client->ops->close(&cinst->lan_info, client,
 375                                                   false);
 376                        iavf_client_release_qvlist(&cinst->lan_info);
 377                        clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
 378
 379                        dev_warn(&adapter->pdev->dev,
 380                                 "Client %s instance closed\n", client->name);
 381                }
 382                /* delete the client instance */
 383                iavf_client_del_instance(adapter);
 384                dev_info(&adapter->pdev->dev, "Deleted client instance of Client %s\n",
 385                         client->name);
 386        }
 387        mutex_unlock(&iavf_device_mutex);
 388}
 389
 390/**
 391 * iavf_client_prepare - prepare client specific resources
 392 * @client: pointer to the registered client
 393 *
 394 **/
 395static void iavf_client_prepare(struct i40e_client *client)
 396{
 397        struct i40e_device *ldev;
 398        struct iavf_adapter *adapter;
 399
 400        mutex_lock(&iavf_device_mutex);
 401        list_for_each_entry(ldev, &i40e_devices, list) {
 402                adapter = ldev->vf;
 403                /* Signal the watchdog to service the client */
 404                adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
 405        }
 406        mutex_unlock(&iavf_device_mutex);
 407}
 408
 409/**
 410 * iavf_client_virtchnl_send - send a message to the PF instance
 411 * @ldev: pointer to L2 context.
 412 * @client: Client pointer.
 413 * @msg: pointer to message buffer
 414 * @len: message length
 415 *
 416 * Return 0 on success or < 0 on error
 417 **/
 418static u32 iavf_client_virtchnl_send(struct i40e_info *ldev,
 419                                     struct i40e_client *client,
 420                                     u8 *msg, u16 len)
 421{
 422        struct iavf_adapter *adapter = ldev->vf;
 423        iavf_status err;
 424
 425        if (adapter->aq_required)
 426                return -EAGAIN;
 427
 428        err = iavf_aq_send_msg_to_pf(&adapter->hw, VIRTCHNL_OP_IWARP,
 429                                     I40E_SUCCESS, msg, len, NULL);
 430        if (err)
 431                dev_err(&adapter->pdev->dev, "Unable to send iWarp message to PF, error %d, aq status %d\n",
 432                        err, adapter->hw.aq.asq_last_status);
 433
 434        return err;
 435}
 436
 437/**
 438 * iavf_client_setup_qvlist - send a message to the PF to setup iwarp qv map
 439 * @ldev: pointer to L2 context.
 440 * @client: Client pointer.
 441 * @qvlist_info: queue and vector list
 442 *
 443 * Return 0 on success or < 0 on error
 444 **/
 445static int iavf_client_setup_qvlist(struct i40e_info *ldev,
 446                                    struct i40e_client *client,
 447                                    struct i40e_qvlist_info *qvlist_info)
 448{
 449        struct virtchnl_iwarp_qvlist_info *v_qvlist_info;
 450        struct iavf_adapter *adapter = ldev->vf;
 451        struct i40e_qv_info *qv_info;
 452        iavf_status err;
 453        u32 v_idx, i;
 454        u32 msg_size;
 455
 456        if (adapter->aq_required)
 457                return -EAGAIN;
 458
 459        /* A quick check on whether the vectors belong to the client */
 460        for (i = 0; i < qvlist_info->num_vectors; i++) {
 461                qv_info = &qvlist_info->qv_info[i];
 462                if (!qv_info)
 463                        continue;
 464                v_idx = qv_info->v_idx;
 465                if ((v_idx >=
 466                    (adapter->iwarp_base_vector + adapter->num_iwarp_msix)) ||
 467                    (v_idx < adapter->iwarp_base_vector))
 468                        return -EINVAL;
 469        }
 470
 471        v_qvlist_info = (struct virtchnl_iwarp_qvlist_info *)qvlist_info;
 472        msg_size = sizeof(struct virtchnl_iwarp_qvlist_info) +
 473                        (sizeof(struct virtchnl_iwarp_qv_info) *
 474                        (v_qvlist_info->num_vectors - 1));
 475
 476        adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP);
 477        err = iavf_aq_send_msg_to_pf(&adapter->hw,
 478                                VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP, I40E_SUCCESS,
 479                                (u8 *)v_qvlist_info, msg_size, NULL);
 480
 481        if (err) {
 482                dev_err(&adapter->pdev->dev,
 483                        "Unable to send iWarp vector config message to PF, error %d, aq status %d\n",
 484                        err, adapter->hw.aq.asq_last_status);
 485                goto out;
 486        }
 487
 488        err = -EBUSY;
 489        for (i = 0; i < 5; i++) {
 490                msleep(100);
 491                if (!(adapter->client_pending &
 492                      BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP))) {
 493                        err = 0;
 494                        break;
 495                }
 496        }
 497out:
 498        return err;
 499}
 500
 501/**
 502 * iavf_register_client - Register a i40e client driver with the L2 driver
 503 * @client: pointer to the i40e_client struct
 504 *
 505 * Returns 0 on success or non-0 on error
 506 **/
 507int iavf_register_client(struct i40e_client *client)
 508{
 509        int ret = 0;
 510
 511        if (!client) {
 512                ret = -EIO;
 513                goto out;
 514        }
 515
 516        if (strlen(client->name) == 0) {
 517                pr_info("iavf: Failed to register client with no name\n");
 518                ret = -EIO;
 519                goto out;
 520        }
 521
 522        if (vf_registered_client) {
 523                pr_info("iavf: Client %s has already been registered!\n",
 524                        client->name);
 525                ret = -EEXIST;
 526                goto out;
 527        }
 528
 529        if ((client->version.major != IAVF_CLIENT_VERSION_MAJOR) ||
 530            (client->version.minor != IAVF_CLIENT_VERSION_MINOR)) {
 531                pr_info("iavf: Failed to register client %s due to mismatched client interface version\n",
 532                        client->name);
 533                pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n",
 534                        client->version.major, client->version.minor,
 535                        client->version.build,
 536                        iavf_client_interface_version_str);
 537                ret = -EIO;
 538                goto out;
 539        }
 540
 541        vf_registered_client = client;
 542
 543        iavf_client_prepare(client);
 544
 545        pr_info("iavf: Registered client %s with return code %d\n",
 546                client->name, ret);
 547out:
 548        return ret;
 549}
 550EXPORT_SYMBOL(iavf_register_client);
 551
 552/**
 553 * iavf_unregister_client - Unregister a i40e client driver with the L2 driver
 554 * @client: pointer to the i40e_client struct
 555 *
 556 * Returns 0 on success or non-0 on error
 557 **/
 558int iavf_unregister_client(struct i40e_client *client)
 559{
 560        int ret = 0;
 561
 562        /* When a unregister request comes through we would have to send
 563         * a close for each of the client instances that were opened.
 564         * client_release function is called to handle this.
 565         */
 566        iavf_client_release(client);
 567
 568        if (vf_registered_client != client) {
 569                pr_info("iavf: Client %s has not been registered\n",
 570                        client->name);
 571                ret = -ENODEV;
 572                goto out;
 573        }
 574        vf_registered_client = NULL;
 575        pr_info("iavf: Unregistered client %s\n", client->name);
 576out:
 577        return ret;
 578}
 579EXPORT_SYMBOL(iavf_unregister_client);
 580