]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/crypto/cavium/nitrox/nitrox_sriov.c
crypto: cavium/nitrox - Enable interrups for PF in SR-IOV mode.
[linux.git] / drivers / crypto / cavium / nitrox / nitrox_sriov.c
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
10 /**
11  * num_vfs_valid - validate VF count
12  * @num_vfs: number of VF(s)
13  */
14 static inline bool num_vfs_valid(int num_vfs)
15 {
16         bool valid = false;
17
18         switch (num_vfs) {
19         case 16:
20         case 32:
21         case 64:
22         case 128:
23                 valid = true;
24                 break;
25         }
26
27         return valid;
28 }
29
30 static inline enum vf_mode num_vfs_to_mode(int num_vfs)
31 {
32         enum vf_mode mode = 0;
33
34         switch (num_vfs) {
35         case 0:
36                 mode = __NDEV_MODE_PF;
37                 break;
38         case 16:
39                 mode = __NDEV_MODE_VF16;
40                 break;
41         case 32:
42                 mode = __NDEV_MODE_VF32;
43                 break;
44         case 64:
45                 mode = __NDEV_MODE_VF64;
46                 break;
47         case 128:
48                 mode = __NDEV_MODE_VF128;
49                 break;
50         }
51
52         return mode;
53 }
54
55 static void nitrox_pf_cleanup(struct nitrox_device *ndev)
56 {
57          /* PF has no queues in SR-IOV mode */
58         atomic_set(&ndev->state, __NDEV_NOT_READY);
59         /* unregister crypto algorithms */
60         nitrox_crypto_unregister();
61
62         /* cleanup PF resources */
63         nitrox_unregister_interrupts(ndev);
64         nitrox_common_sw_cleanup(ndev);
65 }
66
67 /**
68  * nitrox_pf_reinit - re-initialize PF resources once SR-IOV is disabled
69  * @ndev: NITROX device
70  */
71 static int nitrox_pf_reinit(struct nitrox_device *ndev)
72 {
73         int err;
74
75         /* allocate resources for PF */
76         err = nitrox_common_sw_init(ndev);
77         if (err)
78                 return err;
79
80         err = nitrox_register_interrupts(ndev);
81         if (err) {
82                 nitrox_common_sw_cleanup(ndev);
83                 return err;
84         }
85
86         /* configure the packet queues */
87         nitrox_config_pkt_input_rings(ndev);
88         nitrox_config_pkt_solicit_ports(ndev);
89
90         /* set device to ready state */
91         atomic_set(&ndev->state, __NDEV_READY);
92
93         /* register crypto algorithms */
94         return nitrox_crypto_register();
95 }
96
97 static int nitrox_sriov_init(struct nitrox_device *ndev)
98 {
99         /* register interrupts for PF in SR-IOV */
100         return nitrox_sriov_register_interupts(ndev);
101 }
102
103 static void nitrox_sriov_cleanup(struct nitrox_device *ndev)
104 {
105         /* unregister interrupts for PF in SR-IOV */
106         nitrox_sriov_unregister_interrupts(ndev);
107 }
108
109 static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs)
110 {
111         struct nitrox_device *ndev = pci_get_drvdata(pdev);
112         int err;
113
114         if (!num_vfs_valid(num_vfs)) {
115                 dev_err(DEV(ndev), "Invalid num_vfs %d\n", num_vfs);
116                 return -EINVAL;
117         }
118
119         if (pci_num_vf(pdev) == num_vfs)
120                 return num_vfs;
121
122         err = pci_enable_sriov(pdev, num_vfs);
123         if (err) {
124                 dev_err(DEV(ndev), "failed to enable PCI sriov %d\n", err);
125                 return err;
126         }
127         dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs);
128
129         ndev->iov.num_vfs = num_vfs;
130         ndev->mode = num_vfs_to_mode(num_vfs);
131         /* set bit in flags */
132         set_bit(__NDEV_SRIOV_BIT, &ndev->flags);
133
134         /* cleanup PF resources */
135         nitrox_pf_cleanup(ndev);
136
137         /* PF SR-IOV mode initialization */
138         err = nitrox_sriov_init(ndev);
139         if (err)
140                 goto iov_fail;
141
142         config_nps_core_vfcfg_mode(ndev, ndev->mode);
143         return num_vfs;
144
145 iov_fail:
146         pci_disable_sriov(pdev);
147         /* clear bit in flags */
148         clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
149         ndev->iov.num_vfs = 0;
150         ndev->mode = __NDEV_MODE_PF;
151         /* reset back to working mode in PF */
152         nitrox_pf_reinit(ndev);
153         return err;
154 }
155
156 static int nitrox_sriov_disable(struct pci_dev *pdev)
157 {
158         struct nitrox_device *ndev = pci_get_drvdata(pdev);
159
160         if (!test_bit(__NDEV_SRIOV_BIT, &ndev->flags))
161                 return 0;
162
163         if (pci_vfs_assigned(pdev)) {
164                 dev_warn(DEV(ndev), "VFs are attached to VM. Can't disable SR-IOV\n");
165                 return -EPERM;
166         }
167         pci_disable_sriov(pdev);
168         /* clear bit in flags */
169         clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
170
171         ndev->iov.num_vfs = 0;
172         ndev->mode = __NDEV_MODE_PF;
173
174         /* cleanup PF SR-IOV resources */
175         nitrox_sriov_cleanup(ndev);
176
177         config_nps_core_vfcfg_mode(ndev, ndev->mode);
178
179         return nitrox_pf_reinit(ndev);
180 }
181
182 int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs)
183 {
184         if (!num_vfs)
185                 return nitrox_sriov_disable(pdev);
186
187         return nitrox_sriov_enable(pdev, num_vfs);
188 }