linux/drivers/crypto/cavium/nitrox/nitrox_sriov.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/pci.h>
   3#include <linux/delay.h>
   4
   5#include "nitrox_dev.h"
   6#include "nitrox_hal.h"
   7#include "nitrox_common.h"
   8#include "nitrox_isr.h"
   9#include "nitrox_mbx.h"
  10
  11/**
  12 * num_vfs_valid - validate VF count
  13 * @num_vfs: number of VF(s)
  14 */
  15static inline bool num_vfs_valid(int num_vfs)
  16{
  17        bool valid = false;
  18
  19        switch (num_vfs) {
  20        case 16:
  21        case 32:
  22        case 64:
  23        case 128:
  24                valid = true;
  25                break;
  26        }
  27
  28        return valid;
  29}
  30
  31static inline enum vf_mode num_vfs_to_mode(int num_vfs)
  32{
  33        enum vf_mode mode = 0;
  34
  35        switch (num_vfs) {
  36        case 0:
  37                mode = __NDEV_MODE_PF;
  38                break;
  39        case 16:
  40                mode = __NDEV_MODE_VF16;
  41                break;
  42        case 32:
  43                mode = __NDEV_MODE_VF32;
  44                break;
  45        case 64:
  46                mode = __NDEV_MODE_VF64;
  47                break;
  48        case 128:
  49                mode = __NDEV_MODE_VF128;
  50                break;
  51        }
  52
  53        return mode;
  54}
  55
  56static inline int vf_mode_to_nr_queues(enum vf_mode mode)
  57{
  58        int nr_queues = 0;
  59
  60        switch (mode) {
  61        case __NDEV_MODE_PF:
  62                nr_queues = MAX_PF_QUEUES;
  63                break;
  64        case __NDEV_MODE_VF16:
  65                nr_queues = 8;
  66                break;
  67        case __NDEV_MODE_VF32:
  68                nr_queues = 4;
  69                break;
  70        case __NDEV_MODE_VF64:
  71                nr_queues = 2;
  72                break;
  73        case __NDEV_MODE_VF128:
  74                nr_queues = 1;
  75                break;
  76        }
  77
  78        return nr_queues;
  79}
  80
  81static void nitrox_pf_cleanup(struct nitrox_device *ndev)
  82{
  83         /* PF has no queues in SR-IOV mode */
  84        atomic_set(&ndev->state, __NDEV_NOT_READY);
  85        /* unregister crypto algorithms */
  86        nitrox_crypto_unregister();
  87
  88        /* cleanup PF resources */
  89        nitrox_unregister_interrupts(ndev);
  90        nitrox_common_sw_cleanup(ndev);
  91}
  92
  93/**
  94 * nitrox_pf_reinit - re-initialize PF resources once SR-IOV is disabled
  95 * @ndev: NITROX device
  96 */
  97static int nitrox_pf_reinit(struct nitrox_device *ndev)
  98{
  99        int err;
 100
 101        /* allocate resources for PF */
 102        err = nitrox_common_sw_init(ndev);
 103        if (err)
 104                return err;
 105
 106        err = nitrox_register_interrupts(ndev);
 107        if (err) {
 108                nitrox_common_sw_cleanup(ndev);
 109                return err;
 110        }
 111
 112        /* configure the packet queues */
 113        nitrox_config_pkt_input_rings(ndev);
 114        nitrox_config_pkt_solicit_ports(ndev);
 115
 116        /* set device to ready state */
 117        atomic_set(&ndev->state, __NDEV_READY);
 118
 119        /* register crypto algorithms */
 120        return nitrox_crypto_register();
 121}
 122
 123static void nitrox_sriov_cleanup(struct nitrox_device *ndev)
 124{
 125        /* unregister interrupts for PF in SR-IOV */
 126        nitrox_sriov_unregister_interrupts(ndev);
 127        nitrox_mbox_cleanup(ndev);
 128}
 129
 130static int nitrox_sriov_init(struct nitrox_device *ndev)
 131{
 132        int ret;
 133
 134        /* register interrupts for PF in SR-IOV */
 135        ret = nitrox_sriov_register_interupts(ndev);
 136        if (ret)
 137                return ret;
 138
 139        ret = nitrox_mbox_init(ndev);
 140        if (ret)
 141                goto sriov_init_fail;
 142
 143        return 0;
 144
 145sriov_init_fail:
 146        nitrox_sriov_cleanup(ndev);
 147        return ret;
 148}
 149
 150static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs)
 151{
 152        struct nitrox_device *ndev = pci_get_drvdata(pdev);
 153        int err;
 154
 155        if (!num_vfs_valid(num_vfs)) {
 156                dev_err(DEV(ndev), "Invalid num_vfs %d\n", num_vfs);
 157                return -EINVAL;
 158        }
 159
 160        if (pci_num_vf(pdev) == num_vfs)
 161                return num_vfs;
 162
 163        err = pci_enable_sriov(pdev, num_vfs);
 164        if (err) {
 165                dev_err(DEV(ndev), "failed to enable PCI sriov %d\n", err);
 166                return err;
 167        }
 168        dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs);
 169
 170        ndev->mode = num_vfs_to_mode(num_vfs);
 171        ndev->iov.num_vfs = num_vfs;
 172        ndev->iov.max_vf_queues = vf_mode_to_nr_queues(ndev->mode);
 173        /* set bit in flags */
 174        set_bit(__NDEV_SRIOV_BIT, &ndev->flags);
 175
 176        /* cleanup PF resources */
 177        nitrox_pf_cleanup(ndev);
 178
 179        /* PF SR-IOV mode initialization */
 180        err = nitrox_sriov_init(ndev);
 181        if (err)
 182                goto iov_fail;
 183
 184        config_nps_core_vfcfg_mode(ndev, ndev->mode);
 185        return num_vfs;
 186
 187iov_fail:
 188        pci_disable_sriov(pdev);
 189        /* clear bit in flags */
 190        clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
 191        ndev->iov.num_vfs = 0;
 192        ndev->mode = __NDEV_MODE_PF;
 193        /* reset back to working mode in PF */
 194        nitrox_pf_reinit(ndev);
 195        return err;
 196}
 197
 198static int nitrox_sriov_disable(struct pci_dev *pdev)
 199{
 200        struct nitrox_device *ndev = pci_get_drvdata(pdev);
 201
 202        if (!test_bit(__NDEV_SRIOV_BIT, &ndev->flags))
 203                return 0;
 204
 205        if (pci_vfs_assigned(pdev)) {
 206                dev_warn(DEV(ndev), "VFs are attached to VM. Can't disable SR-IOV\n");
 207                return -EPERM;
 208        }
 209        pci_disable_sriov(pdev);
 210        /* clear bit in flags */
 211        clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
 212
 213        ndev->iov.num_vfs = 0;
 214        ndev->iov.max_vf_queues = 0;
 215        ndev->mode = __NDEV_MODE_PF;
 216
 217        /* cleanup PF SR-IOV resources */
 218        nitrox_sriov_cleanup(ndev);
 219
 220        config_nps_core_vfcfg_mode(ndev, ndev->mode);
 221
 222        return nitrox_pf_reinit(ndev);
 223}
 224
 225int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs)
 226{
 227        if (!num_vfs)
 228                return nitrox_sriov_disable(pdev);
 229
 230        return nitrox_sriov_enable(pdev, num_vfs);
 231}
 232