Skip to content

Commit 47698d0

Browse files
committed
crypto: qat - allow disabling SR-IOV VFs
JIRA: https://issues.redhat.com/browse/RHEL-52749 Upstream Status: merged into the linux.git commit ca88a2b Author: Michal Witwicki <michal.witwicki@intel.com> Date: Wed Jul 17 07:45:00 2024 -0400 crypto: qat - allow disabling SR-IOV VFs The QAT driver allows enabling SR-IOV VFs but does not allow them to be disabled through a write to sysfs. Disabling SR-IOV VFs can be only achieved by bringing down and up a device using the attribute /sys/bus/pci/devices/<BDF>/qat/state. The documentation for the sysfs attribute `sriov_numvfs` specifies that "a userspace application wanting to disable the VFs would write a zero to this file". Add support for disabling SR-IOV VFs by writing '0' to the 'sriov_numvfs' attribute in sysfs. Enabling or disabling SR-IOV always requires adf_dev_down() to be called. This action subsequently leads to the deletion of the ADF_KERNEL_SEC configuration section. The keys ADF_NUM_CY and ADF_NUM_DC within that section must be set to '0', otherwise, the driver will register into the Linux Crypto Framework. Because of this, the configuration in the ADF_KERNEL_SEC section must be added before every sriov_enable. Signed-off-by: Michal Witwicki <michal.witwicki@intel.com> Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com> Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Vladis Dronov <vdronov@redhat.com>
1 parent d1e2805 commit 47698d0

File tree

1 file changed

+128
-66
lines changed

1 file changed

+128
-66
lines changed

drivers/crypto/intel/qat/qat_common/adf_sriov.c

Lines changed: 128 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,133 @@ static int adf_enable_sriov(struct adf_accel_dev *accel_dev)
8686
return pci_enable_sriov(pdev, totalvfs);
8787
}
8888

89+
static int adf_add_sriov_configuration(struct adf_accel_dev *accel_dev)
90+
{
91+
unsigned long val = 0;
92+
int ret;
93+
94+
ret = adf_cfg_section_add(accel_dev, ADF_KERNEL_SEC);
95+
if (ret)
96+
return ret;
97+
98+
ret = adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_CY,
99+
&val, ADF_DEC);
100+
if (ret)
101+
return ret;
102+
103+
ret = adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_DC,
104+
&val, ADF_DEC);
105+
if (ret)
106+
return ret;
107+
108+
set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
109+
110+
return ret;
111+
}
112+
113+
static int adf_do_disable_sriov(struct adf_accel_dev *accel_dev)
114+
{
115+
int ret;
116+
117+
if (adf_dev_in_use(accel_dev)) {
118+
dev_err(&GET_DEV(accel_dev),
119+
"Cannot disable SR-IOV, device in use\n");
120+
return -EBUSY;
121+
}
122+
123+
if (adf_dev_started(accel_dev)) {
124+
if (adf_devmgr_in_reset(accel_dev)) {
125+
dev_err(&GET_DEV(accel_dev),
126+
"Cannot disable SR-IOV, device in reset\n");
127+
return -EBUSY;
128+
}
129+
130+
ret = adf_dev_down(accel_dev);
131+
if (ret)
132+
goto err_del_cfg;
133+
}
134+
135+
adf_disable_sriov(accel_dev);
136+
137+
ret = adf_dev_up(accel_dev, true);
138+
if (ret)
139+
goto err_del_cfg;
140+
141+
return 0;
142+
143+
err_del_cfg:
144+
adf_cfg_del_all_except(accel_dev, ADF_GENERAL_SEC);
145+
return ret;
146+
}
147+
148+
static int adf_do_enable_sriov(struct adf_accel_dev *accel_dev)
149+
{
150+
struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
151+
int totalvfs = pci_sriov_get_totalvfs(pdev);
152+
unsigned long val;
153+
int ret;
154+
155+
if (!device_iommu_mapped(&GET_DEV(accel_dev))) {
156+
dev_warn(&GET_DEV(accel_dev),
157+
"IOMMU should be enabled for SR-IOV to work correctly\n");
158+
return -EINVAL;
159+
}
160+
161+
if (adf_dev_started(accel_dev)) {
162+
if (adf_devmgr_in_reset(accel_dev) || adf_dev_in_use(accel_dev)) {
163+
dev_err(&GET_DEV(accel_dev), "Device busy\n");
164+
return -EBUSY;
165+
}
166+
167+
ret = adf_dev_down(accel_dev);
168+
if (ret)
169+
return ret;
170+
}
171+
172+
ret = adf_add_sriov_configuration(accel_dev);
173+
if (ret)
174+
goto err_del_cfg;
175+
176+
/* Allocate memory for VF info structs */
177+
accel_dev->pf.vf_info = kcalloc(totalvfs, sizeof(struct adf_accel_vf_info),
178+
GFP_KERNEL);
179+
ret = -ENOMEM;
180+
if (!accel_dev->pf.vf_info)
181+
goto err_del_cfg;
182+
183+
ret = adf_dev_up(accel_dev, false);
184+
if (ret) {
185+
dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
186+
accel_dev->accel_id);
187+
goto err_free_vf_info;
188+
}
189+
190+
ret = adf_enable_sriov(accel_dev);
191+
if (ret)
192+
goto err_free_vf_info;
193+
194+
val = 1;
195+
ret = adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC, ADF_SRIOV_ENABLED,
196+
&val, ADF_DEC);
197+
if (ret)
198+
goto err_free_vf_info;
199+
200+
return totalvfs;
201+
202+
err_free_vf_info:
203+
adf_dev_down(accel_dev);
204+
kfree(accel_dev->pf.vf_info);
205+
accel_dev->pf.vf_info = NULL;
206+
return ret;
207+
err_del_cfg:
208+
adf_cfg_del_all_except(accel_dev, ADF_GENERAL_SEC);
209+
return ret;
210+
}
211+
89212
void adf_reenable_sriov(struct adf_accel_dev *accel_dev)
90213
{
91214
struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
92215
char cfg[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0};
93-
unsigned long val = 0;
94216

95217
if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
96218
ADF_SRIOV_ENABLED, cfg))
@@ -99,15 +221,9 @@ void adf_reenable_sriov(struct adf_accel_dev *accel_dev)
99221
if (!accel_dev->pf.vf_info)
100222
return;
101223

102-
if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_CY,
103-
&val, ADF_DEC))
104-
return;
105-
106-
if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_DC,
107-
&val, ADF_DEC))
224+
if (adf_add_sriov_configuration(accel_dev))
108225
return;
109226

110-
set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
111227
dev_dbg(&pdev->dev, "Re-enabling SRIOV\n");
112228
adf_enable_sriov(accel_dev);
113229
}
@@ -168,70 +284,16 @@ EXPORT_SYMBOL_GPL(adf_disable_sriov);
168284
int adf_sriov_configure(struct pci_dev *pdev, int numvfs)
169285
{
170286
struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
171-
int totalvfs = pci_sriov_get_totalvfs(pdev);
172-
unsigned long val;
173-
int ret;
174287

175288
if (!accel_dev) {
176289
dev_err(&pdev->dev, "Failed to find accel_dev\n");
177290
return -EFAULT;
178291
}
179292

180-
if (!device_iommu_mapped(&pdev->dev))
181-
dev_warn(&pdev->dev, "IOMMU should be enabled for SR-IOV to work correctly\n");
182-
183-
if (accel_dev->pf.vf_info) {
184-
dev_info(&pdev->dev, "Already enabled for this device\n");
185-
return -EINVAL;
186-
}
187-
188-
if (adf_dev_started(accel_dev)) {
189-
if (adf_devmgr_in_reset(accel_dev) ||
190-
adf_dev_in_use(accel_dev)) {
191-
dev_err(&GET_DEV(accel_dev), "Device busy\n");
192-
return -EBUSY;
193-
}
194-
195-
ret = adf_dev_down(accel_dev);
196-
if (ret)
197-
return ret;
198-
}
199-
200-
if (adf_cfg_section_add(accel_dev, ADF_KERNEL_SEC))
201-
return -EFAULT;
202-
val = 0;
203-
if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
204-
ADF_NUM_CY, (void *)&val, ADF_DEC))
205-
return -EFAULT;
206-
ret = adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_DC,
207-
&val, ADF_DEC);
208-
if (ret)
209-
return ret;
210-
211-
set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
212-
213-
/* Allocate memory for VF info structs */
214-
accel_dev->pf.vf_info = kcalloc(totalvfs,
215-
sizeof(struct adf_accel_vf_info),
216-
GFP_KERNEL);
217-
if (!accel_dev->pf.vf_info)
218-
return -ENOMEM;
219-
220-
if (adf_dev_up(accel_dev, false)) {
221-
dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
222-
accel_dev->accel_id);
223-
return -EFAULT;
224-
}
225-
226-
ret = adf_enable_sriov(accel_dev);
227-
if (ret)
228-
return ret;
229-
230-
val = 1;
231-
adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC, ADF_SRIOV_ENABLED,
232-
&val, ADF_DEC);
233-
234-
return numvfs;
293+
if (numvfs)
294+
return adf_do_enable_sriov(accel_dev);
295+
else
296+
return adf_do_disable_sriov(accel_dev);
235297
}
236298
EXPORT_SYMBOL_GPL(adf_sriov_configure);
237299

0 commit comments

Comments
 (0)