OSDN Git Service

crypto: cavium/nitrox - Added support for SR-IOV configuration.
authorSrikanth Jampala <Jampala.Srikanth@cavium.com>
Fri, 7 Sep 2018 07:01:18 +0000 (12:31 +0530)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 14 Sep 2018 06:08:53 +0000 (14:08 +0800)
Added support to configure SR-IOV using sysfs interface.
Supported VF modes are 16, 32, 64 and 128. Grouped the
hardware configuration functions to "nitrox_hal.h" file.
Changed driver version to "1.1".

Signed-off-by: Srikanth Jampala <Jampala.Srikanth@cavium.com>
Reviewed-by: Gadam Sreerama <sgadam@cavium.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/cavium/nitrox/Makefile
drivers/crypto/cavium/nitrox/nitrox_common.h
drivers/crypto/cavium/nitrox/nitrox_dev.h
drivers/crypto/cavium/nitrox/nitrox_hal.c
drivers/crypto/cavium/nitrox/nitrox_hal.h [new file with mode: 0644]
drivers/crypto/cavium/nitrox/nitrox_isr.c
drivers/crypto/cavium/nitrox/nitrox_main.c
drivers/crypto/cavium/nitrox/nitrox_sriov.c [new file with mode: 0644]

index 45b7379..6fcda6b 100644 (file)
@@ -7,3 +7,5 @@ n5pf-objs := nitrox_main.o \
        nitrox_hal.o \
        nitrox_reqmgr.o \
        nitrox_algs.o
+
+n5pf-$(CONFIG_PCI_IOV) += nitrox_sriov.o
index 312f728..00ef931 100644 (file)
@@ -25,19 +25,5 @@ int nitrox_process_se_request(struct nitrox_device *ndev,
                              struct skcipher_request *skreq);
 void backlog_qflush_work(struct work_struct *work);
 
-void nitrox_config_emu_unit(struct nitrox_device *ndev);
-void nitrox_config_pkt_input_rings(struct nitrox_device *ndev);
-void nitrox_config_pkt_solicit_ports(struct nitrox_device *ndev);
-void nitrox_config_vfmode(struct nitrox_device *ndev, int mode);
-void nitrox_config_nps_unit(struct nitrox_device *ndev);
-void nitrox_config_pom_unit(struct nitrox_device *ndev);
-void nitrox_config_rand_unit(struct nitrox_device *ndev);
-void nitrox_config_efl_unit(struct nitrox_device *ndev);
-void nitrox_config_bmi_unit(struct nitrox_device *ndev);
-void nitrox_config_bmo_unit(struct nitrox_device *ndev);
-void nitrox_config_lbc_unit(struct nitrox_device *ndev);
-void invalidate_lbc(struct nitrox_device *ndev);
-void enable_pkt_input_ring(struct nitrox_device *ndev, int ring);
-void enable_pkt_solicit_port(struct nitrox_device *ndev, int port);
 
 #endif /* __NITROX_COMMON_H */
index af59645..4f560ce 100644 (file)
@@ -88,9 +88,25 @@ struct nitrox_bh {
        struct bh_data *slc;
 };
 
-/* NITROX-V driver state */
-#define NITROX_UCODE_LOADED    0
-#define NITROX_READY           1
+/*
+ * NITROX Device states
+ */
+enum ndev_state {
+       __NDEV_NOT_READY,
+       __NDEV_READY,
+       __NDEV_IN_RESET,
+};
+
+/* NITROX support modes for VF(s) */
+enum vf_mode {
+       __NDEV_MODE_PF,
+       __NDEV_MODE_VF16,
+       __NDEV_MODE_VF32,
+       __NDEV_MODE_VF64,
+       __NDEV_MODE_VF128,
+};
+
+#define __NDEV_SRIOV_BIT 0
 
 /* command queue size */
 #define DEFAULT_CMD_QLEN 2048
@@ -98,7 +114,6 @@ struct nitrox_bh {
 #define CMD_TIMEOUT 2000
 
 #define DEV(ndev) ((struct device *)(&(ndev)->pdev->dev))
-#define PF_MODE 0
 
 #define NITROX_CSR_ADDR(ndev, offset) \
        ((ndev)->bar_addr + (offset))
@@ -108,13 +123,15 @@ struct nitrox_bh {
  * @list: pointer to linked list of devices
  * @bar_addr: iomap address
  * @pdev: PCI device information
- * @status: NITROX status
+ * @state: NITROX device state
+ * @flags: flags to indicate device the features
  * @timeout: Request timeout in jiffies
  * @refcnt: Device usage count
  * @idx: device index (0..N)
  * @node: NUMA node id attached
  * @qlen: Command queue length
  * @nr_queues: Number of command queues
+ * @mode: Device mode PF/VF
  * @ctx_pool: DMA pool for crypto context
  * @pkt_cmdqs: SE Command queues
  * @msix: MSI-X information
@@ -128,7 +145,8 @@ struct nitrox_device {
        u8 __iomem *bar_addr;
        struct pci_dev *pdev;
 
-       unsigned long status;
+       atomic_t state;
+       unsigned long flags;
        unsigned long timeout;
        refcount_t refcnt;
 
@@ -136,6 +154,8 @@ struct nitrox_device {
        int node;
        u16 qlen;
        u16 nr_queues;
+       int num_vfs;
+       enum vf_mode mode;
 
        struct dma_pool *ctx_pool;
        struct nitrox_cmdq *pkt_cmdqs;
@@ -173,9 +193,9 @@ static inline void nitrox_write_csr(struct nitrox_device *ndev, u64 offset,
        writeq(value, (ndev->bar_addr + offset));
 }
 
-static inline int nitrox_ready(struct nitrox_device *ndev)
+static inline bool nitrox_ready(struct nitrox_device *ndev)
 {
-       return test_bit(NITROX_READY, &ndev->status);
+       return atomic_read(&ndev->state) == __NDEV_READY;
 }
 
 #endif /* __NITROX_DEV_H */
index ab4ccf2..2b256ba 100644 (file)
@@ -256,7 +256,7 @@ void nitrox_config_nps_unit(struct nitrox_device *ndev)
        /* disable ILK interface */
        core_gbl_vfcfg.value = 0;
        core_gbl_vfcfg.s.ilk_disable = 1;
-       core_gbl_vfcfg.s.cfg = PF_MODE;
+       core_gbl_vfcfg.s.cfg = __NDEV_MODE_PF;
        nitrox_write_csr(ndev, NPS_CORE_GBL_VFCFG, core_gbl_vfcfg.value);
        /* config input and solicit ports */
        nitrox_config_pkt_input_rings(ndev);
@@ -400,3 +400,13 @@ void nitrox_config_lbc_unit(struct nitrox_device *ndev)
        offset = LBC_ELM_VF65_128_INT_ENA_W1S;
        nitrox_write_csr(ndev, offset, (~0ULL));
 }
+
+void config_nps_core_vfcfg_mode(struct nitrox_device *ndev, enum vf_mode mode)
+{
+       union nps_core_gbl_vfcfg vfcfg;
+
+       vfcfg.value = nitrox_read_csr(ndev, NPS_CORE_GBL_VFCFG);
+       vfcfg.s.cfg = mode & 0x7;
+
+       nitrox_write_csr(ndev, NPS_CORE_GBL_VFCFG, vfcfg.value);
+}
diff --git a/drivers/crypto/cavium/nitrox/nitrox_hal.h b/drivers/crypto/cavium/nitrox/nitrox_hal.h
new file mode 100644 (file)
index 0000000..3baef86
--- /dev/null
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NITROX_HAL_H
+#define __NITROX_HAL_H
+
+#include "nitrox_dev.h"
+
+void nitrox_config_emu_unit(struct nitrox_device *ndev);
+void nitrox_config_pkt_input_rings(struct nitrox_device *ndev);
+void nitrox_config_pkt_solicit_ports(struct nitrox_device *ndev);
+void nitrox_config_nps_unit(struct nitrox_device *ndev);
+void nitrox_config_pom_unit(struct nitrox_device *ndev);
+void nitrox_config_rand_unit(struct nitrox_device *ndev);
+void nitrox_config_efl_unit(struct nitrox_device *ndev);
+void nitrox_config_bmi_unit(struct nitrox_device *ndev);
+void nitrox_config_bmo_unit(struct nitrox_device *ndev);
+void nitrox_config_lbc_unit(struct nitrox_device *ndev);
+void invalidate_lbc(struct nitrox_device *ndev);
+void enable_pkt_input_ring(struct nitrox_device *ndev, int ring);
+void enable_pkt_solicit_port(struct nitrox_device *ndev, int port);
+void config_nps_core_vfcfg_mode(struct nitrox_device *ndev, enum vf_mode mode);
+
+#endif /* __NITROX_HAL_H */
index ee0d70b..4f43349 100644 (file)
@@ -6,6 +6,7 @@
 #include "nitrox_dev.h"
 #include "nitrox_csr.h"
 #include "nitrox_common.h"
+#include "nitrox_hal.h"
 
 #define NR_RING_VECTORS 3
 #define NPS_CORE_INT_ACTIVE_ENTRY 192
index fee7cb2..6d7a421 100644 (file)
 #include "nitrox_dev.h"
 #include "nitrox_common.h"
 #include "nitrox_csr.h"
+#include "nitrox_hal.h"
 
 #define CNN55XX_DEV_ID 0x12
 #define MAX_PF_QUEUES  64
 #define UCODE_HLEN 48
 #define SE_GROUP 0
 
-#define DRIVER_VERSION "1.0"
+#define DRIVER_VERSION "1.1"
 #define FW_DIR "cavium/"
 /* SE microcode */
 #define SE_FW  FW_DIR "cnn55xx_se.fw"
@@ -42,6 +43,15 @@ static unsigned int qlen = DEFAULT_CMD_QLEN;
 module_param(qlen, uint, 0644);
 MODULE_PARM_DESC(qlen, "Command queue length - default 2048");
 
+#ifdef CONFIG_PCI_IOV
+int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs);
+#else
+int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs)
+{
+       return 0;
+}
+#endif
+
 /**
  * struct ucode - Firmware Header
  * @id: microcode ID
@@ -136,9 +146,6 @@ static int nitrox_load_fw(struct nitrox_device *ndev, const char *fw_name)
        write_to_ucd_unit(ndev, ucode);
        release_firmware(fw);
 
-       set_bit(NITROX_UCODE_LOADED, &ndev->status);
-       /* barrier to sync with other cpus */
-       smp_mb__after_atomic();
        return 0;
 }
 
@@ -555,7 +562,7 @@ static int nitrox_probe(struct pci_dev *pdev,
        if (err)
                goto pf_hw_fail;
 
-       set_bit(NITROX_READY, &ndev->status);
+       atomic_set(&ndev->state, __NDEV_READY);
        /* barrier to sync with other cpus */
        smp_mb__after_atomic();
 
@@ -567,7 +574,7 @@ static int nitrox_probe(struct pci_dev *pdev,
 
 crypto_fail:
        nitrox_debugfs_exit(ndev);
-       clear_bit(NITROX_READY, &ndev->status);
+       atomic_set(&ndev->state, __NDEV_NOT_READY);
        /* barrier to sync with other cpus */
        smp_mb__after_atomic();
 pf_hw_fail:
@@ -602,11 +609,16 @@ static void nitrox_remove(struct pci_dev *pdev)
        dev_info(DEV(ndev), "Removing Device %x:%x\n",
                 ndev->hw.vendor_id, ndev->hw.device_id);
 
-       clear_bit(NITROX_READY, &ndev->status);
+       atomic_set(&ndev->state, __NDEV_NOT_READY);
        /* barrier to sync with other cpus */
        smp_mb__after_atomic();
 
        nitrox_remove_from_devlist(ndev);
+
+#ifdef CONFIG_PCI_IOV
+       /* disable SR-IOV */
+       nitrox_sriov_configure(pdev, 0);
+#endif
        nitrox_crypto_unregister();
        nitrox_debugfs_exit(ndev);
        nitrox_pf_sw_cleanup(ndev);
@@ -632,6 +644,9 @@ static struct pci_driver nitrox_driver = {
        .probe = nitrox_probe,
        .remove = nitrox_remove,
        .shutdown = nitrox_shutdown,
+#ifdef CONFIG_PCI_IOV
+       .sriov_configure = nitrox_sriov_configure,
+#endif
 };
 
 module_pci_driver(nitrox_driver);
diff --git a/drivers/crypto/cavium/nitrox/nitrox_sriov.c b/drivers/crypto/cavium/nitrox/nitrox_sriov.c
new file mode 100644 (file)
index 0000000..453d920
--- /dev/null
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "nitrox_dev.h"
+#include "nitrox_hal.h"
+#include "nitrox_common.h"
+
+static inline bool num_vfs_valid(int num_vfs)
+{
+       bool valid = false;
+
+       switch (num_vfs) {
+       case 16:
+       case 32:
+       case 64:
+       case 128:
+               valid = true;
+               break;
+       }
+
+       return valid;
+}
+
+static inline enum vf_mode num_vfs_to_mode(int num_vfs)
+{
+       enum vf_mode mode = 0;
+
+       switch (num_vfs) {
+       case 0:
+               mode = __NDEV_MODE_PF;
+               break;
+       case 16:
+               mode = __NDEV_MODE_VF16;
+               break;
+       case 32:
+               mode = __NDEV_MODE_VF32;
+               break;
+       case 64:
+               mode = __NDEV_MODE_VF64;
+               break;
+       case 128:
+               mode = __NDEV_MODE_VF128;
+               break;
+       }
+
+       return mode;
+}
+
+static void pf_sriov_cleanup(struct nitrox_device *ndev)
+{
+        /* PF has no queues in SR-IOV mode */
+       atomic_set(&ndev->state, __NDEV_NOT_READY);
+       /* unregister crypto algorithms */
+       nitrox_crypto_unregister();
+
+       /* cleanup PF resources */
+       nitrox_pf_cleanup_isr(ndev);
+       nitrox_common_sw_cleanup(ndev);
+}
+
+static int pf_sriov_init(struct nitrox_device *ndev)
+{
+       int err;
+
+       /* allocate resources for PF */
+       err = nitrox_common_sw_init(ndev);
+       if (err)
+               return err;
+
+       err = nitrox_pf_init_isr(ndev);
+       if (err) {
+               nitrox_common_sw_cleanup(ndev);
+               return err;
+       }
+
+       /* configure the packet queues */
+       nitrox_config_pkt_input_rings(ndev);
+       nitrox_config_pkt_solicit_ports(ndev);
+
+       /* set device to ready state */
+       atomic_set(&ndev->state, __NDEV_READY);
+
+       /* register crypto algorithms */
+       return nitrox_crypto_register();
+}
+
+static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs)
+{
+       struct nitrox_device *ndev = pci_get_drvdata(pdev);
+       int err;
+
+       if (!num_vfs_valid(num_vfs)) {
+               dev_err(DEV(ndev), "Invalid num_vfs %d\n", num_vfs);
+               return -EINVAL;
+       }
+
+       if (pci_num_vf(pdev) == num_vfs)
+               return num_vfs;
+
+       err = pci_enable_sriov(pdev, num_vfs);
+       if (err) {
+               dev_err(DEV(ndev), "failed to enable PCI sriov %d\n", err);
+               return err;
+       }
+       dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs);
+
+       ndev->num_vfs = num_vfs;
+       ndev->mode = num_vfs_to_mode(num_vfs);
+       /* set bit in flags */
+       set_bit(__NDEV_SRIOV_BIT, &ndev->flags);
+
+       /* cleanup PF resources */
+       pf_sriov_cleanup(ndev);
+
+       config_nps_core_vfcfg_mode(ndev, ndev->mode);
+
+       return num_vfs;
+}
+
+static int nitrox_sriov_disable(struct pci_dev *pdev)
+{
+       struct nitrox_device *ndev = pci_get_drvdata(pdev);
+
+       if (!test_bit(__NDEV_SRIOV_BIT, &ndev->flags))
+               return 0;
+
+       if (pci_vfs_assigned(pdev)) {
+               dev_warn(DEV(ndev), "VFs are attached to VM. Can't disable SR-IOV\n");
+               return -EPERM;
+       }
+       pci_disable_sriov(pdev);
+       /* clear bit in flags */
+       clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
+
+       ndev->num_vfs = 0;
+       ndev->mode = __NDEV_MODE_PF;
+
+       config_nps_core_vfcfg_mode(ndev, ndev->mode);
+
+       return pf_sriov_init(ndev);
+}
+
+int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs)
+{
+       if (!num_vfs)
+               return nitrox_sriov_disable(pdev);
+
+       return nitrox_sriov_enable(pdev, num_vfs);
+}