File Index
Files and directories
Sign in
FILE

nitrox_sriov.c

File preview with syntax highlighting.

linux-6.19.14/drivers/crypto/cavium/nitrox/nitrox_sriov.c 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#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 AQM queues */
113	nitrox_config_aqm_rings(ndev);
114
115	/* configure the packet queues */
116	nitrox_config_pkt_input_rings(ndev);
117	nitrox_config_pkt_solicit_ports(ndev);
118
119	/* set device to ready state */
120	atomic_set(&ndev->state, __NDEV_READY);
121
122	/* register crypto algorithms */
123	return nitrox_crypto_register();
124}
125
126static void nitrox_sriov_cleanup(struct nitrox_device *ndev)
127{
128	/* unregister interrupts for PF in SR-IOV */
129	nitrox_sriov_unregister_interrupts(ndev);
130	nitrox_mbox_cleanup(ndev);
131}
132
133static int nitrox_sriov_init(struct nitrox_device *ndev)
134{
135	int ret;
136
137	/* register interrupts for PF in SR-IOV */
138	ret = nitrox_sriov_register_interupts(ndev);
139	if (ret)
140		return ret;
141
142	ret = nitrox_mbox_init(ndev);
143	if (ret)
144		goto sriov_init_fail;
145
146	return 0;
147
148sriov_init_fail:
149	nitrox_sriov_cleanup(ndev);
150	return ret;
151}
152
153static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs)
154{
155	struct nitrox_device *ndev = pci_get_drvdata(pdev);
156	int err;
157
158	if (!num_vfs_valid(num_vfs)) {
159		dev_err(DEV(ndev), "Invalid num_vfs %d\n", num_vfs);
160		return -EINVAL;
161	}
162
163	if (pci_num_vf(pdev) == num_vfs)
164		return num_vfs;
165
166	err = pci_enable_sriov(pdev, num_vfs);
167	if (err) {
168		dev_err(DEV(ndev), "failed to enable PCI sriov %d\n", err);
169		return err;
170	}
171	dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs);
172
173	ndev->mode = num_vfs_to_mode(num_vfs);
174	ndev->iov.num_vfs = num_vfs;
175	ndev->iov.max_vf_queues = vf_mode_to_nr_queues(ndev->mode);
176	/* set bit in flags */
177	set_bit(__NDEV_SRIOV_BIT, &ndev->flags);
178
179	/* cleanup PF resources */
180	nitrox_pf_cleanup(ndev);
181
182	/* PF SR-IOV mode initialization */
183	err = nitrox_sriov_init(ndev);
184	if (err)
185		goto iov_fail;
186
187	config_nps_core_vfcfg_mode(ndev, ndev->mode);
188	return num_vfs;
189
190iov_fail:
191	pci_disable_sriov(pdev);
192	/* clear bit in flags */
193	clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
194	ndev->iov.num_vfs = 0;
195	ndev->mode = __NDEV_MODE_PF;
196	/* reset back to working mode in PF */
197	nitrox_pf_reinit(ndev);
198	return err;
199}
200
201static int nitrox_sriov_disable(struct pci_dev *pdev)
202{
203	struct nitrox_device *ndev = pci_get_drvdata(pdev);
204
205	if (!test_bit(__NDEV_SRIOV_BIT, &ndev->flags))
206		return 0;
207
208	if (pci_vfs_assigned(pdev)) {
209		dev_warn(DEV(ndev), "VFs are attached to VM. Can't disable SR-IOV\n");
210		return -EPERM;
211	}
212	pci_disable_sriov(pdev);
213	/* clear bit in flags */
214	clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
215
216	ndev->iov.num_vfs = 0;
217	ndev->iov.max_vf_queues = 0;
218	ndev->mode = __NDEV_MODE_PF;
219
220	/* cleanup PF SR-IOV resources */
221	nitrox_sriov_cleanup(ndev);
222
223	config_nps_core_vfcfg_mode(ndev, ndev->mode);
224
225	return nitrox_pf_reinit(ndev);
226}
227
228int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs)
229{
230	if (!num_vfs)
231		return nitrox_sriov_disable(pdev);
232
233	return nitrox_sriov_enable(pdev, num_vfs);
234}
~/ Read-only file preview.