Skip to content

Commit 7dd793f

Browse files
Zhu Lingshanmstsirkin
authored andcommitted
ifcvf: move IRQ request/free to status change handlers
This commit move IRQ request and free operations from probe() to VIRTIO status change handler to comply with VIRTIO spec. VIRTIO spec 1.1, section 2.1.2 Device Requirements: Device Status Field The device MUST NOT consume buffers or send any used buffer notifications to the driver before DRIVER_OK. Signed-off-by: Zhu Lingshan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael S. Tsirkin <[email protected]> Acked-by: Jason Wang <[email protected]>
1 parent 002ef18 commit 7dd793f

File tree

1 file changed

+73
-47
lines changed

1 file changed

+73
-47
lines changed

drivers/vdpa/ifcvf/ifcvf_main.c

Lines changed: 73 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,60 @@ static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
2828
return IRQ_HANDLED;
2929
}
3030

31+
static void ifcvf_free_irq_vectors(void *data)
32+
{
33+
pci_free_irq_vectors(data);
34+
}
35+
36+
static void ifcvf_free_irq(struct ifcvf_adapter *adapter, int queues)
37+
{
38+
struct pci_dev *pdev = adapter->pdev;
39+
struct ifcvf_hw *vf = &adapter->vf;
40+
int i;
41+
42+
43+
for (i = 0; i < queues; i++)
44+
devm_free_irq(&pdev->dev, vf->vring[i].irq, &vf->vring[i]);
45+
46+
ifcvf_free_irq_vectors(pdev);
47+
}
48+
49+
static int ifcvf_request_irq(struct ifcvf_adapter *adapter)
50+
{
51+
struct pci_dev *pdev = adapter->pdev;
52+
struct ifcvf_hw *vf = &adapter->vf;
53+
int vector, i, ret, irq;
54+
55+
ret = pci_alloc_irq_vectors(pdev, IFCVF_MAX_INTR,
56+
IFCVF_MAX_INTR, PCI_IRQ_MSIX);
57+
if (ret < 0) {
58+
IFCVF_ERR(pdev, "Failed to alloc IRQ vectors\n");
59+
return ret;
60+
}
61+
62+
for (i = 0; i < IFCVF_MAX_QUEUE_PAIRS * 2; i++) {
63+
snprintf(vf->vring[i].msix_name, 256, "ifcvf[%s]-%d\n",
64+
pci_name(pdev), i);
65+
vector = i + IFCVF_MSI_QUEUE_OFF;
66+
irq = pci_irq_vector(pdev, vector);
67+
ret = devm_request_irq(&pdev->dev, irq,
68+
ifcvf_intr_handler, 0,
69+
vf->vring[i].msix_name,
70+
&vf->vring[i]);
71+
if (ret) {
72+
IFCVF_ERR(pdev,
73+
"Failed to request irq for vq %d\n", i);
74+
ifcvf_free_irq(adapter, i);
75+
76+
return ret;
77+
}
78+
79+
vf->vring[i].irq = irq;
80+
}
81+
82+
return 0;
83+
}
84+
3185
static int ifcvf_start_datapath(void *private)
3286
{
3387
struct ifcvf_hw *vf = ifcvf_private_to_vf(private);
@@ -118,17 +172,34 @@ static void ifcvf_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
118172
{
119173
struct ifcvf_adapter *adapter;
120174
struct ifcvf_hw *vf;
175+
u8 status_old;
176+
int ret;
121177

122178
vf = vdpa_to_vf(vdpa_dev);
123179
adapter = dev_get_drvdata(vdpa_dev->dev.parent);
180+
status_old = ifcvf_get_status(vf);
124181

125-
if (status == 0) {
182+
if ((status_old & VIRTIO_CONFIG_S_DRIVER_OK) &&
183+
!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
126184
ifcvf_stop_datapath(adapter);
185+
ifcvf_free_irq(adapter, IFCVF_MAX_QUEUE_PAIRS * 2);
186+
}
187+
188+
if (status == 0) {
127189
ifcvf_reset_vring(adapter);
128190
return;
129191
}
130192

131-
if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
193+
if ((status & VIRTIO_CONFIG_S_DRIVER_OK) &&
194+
!(status_old & VIRTIO_CONFIG_S_DRIVER_OK)) {
195+
ret = ifcvf_request_irq(adapter);
196+
if (ret) {
197+
status = ifcvf_get_status(vf);
198+
status |= VIRTIO_CONFIG_S_FAILED;
199+
ifcvf_set_status(vf, status);
200+
return;
201+
}
202+
132203
if (ifcvf_start_datapath(adapter) < 0)
133204
IFCVF_ERR(adapter->pdev,
134205
"Failed to set ifcvf vdpa status %u\n",
@@ -284,38 +355,6 @@ static const struct vdpa_config_ops ifc_vdpa_ops = {
284355
.set_config_cb = ifcvf_vdpa_set_config_cb,
285356
};
286357

287-
static int ifcvf_request_irq(struct ifcvf_adapter *adapter)
288-
{
289-
struct pci_dev *pdev = adapter->pdev;
290-
struct ifcvf_hw *vf = &adapter->vf;
291-
int vector, i, ret, irq;
292-
293-
294-
for (i = 0; i < IFCVF_MAX_QUEUE_PAIRS * 2; i++) {
295-
snprintf(vf->vring[i].msix_name, 256, "ifcvf[%s]-%d\n",
296-
pci_name(pdev), i);
297-
vector = i + IFCVF_MSI_QUEUE_OFF;
298-
irq = pci_irq_vector(pdev, vector);
299-
ret = devm_request_irq(&pdev->dev, irq,
300-
ifcvf_intr_handler, 0,
301-
vf->vring[i].msix_name,
302-
&vf->vring[i]);
303-
if (ret) {
304-
IFCVF_ERR(pdev,
305-
"Failed to request irq for vq %d\n", i);
306-
return ret;
307-
}
308-
vf->vring[i].irq = irq;
309-
}
310-
311-
return 0;
312-
}
313-
314-
static void ifcvf_free_irq_vectors(void *data)
315-
{
316-
pci_free_irq_vectors(data);
317-
}
318-
319358
static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
320359
{
321360
struct device *dev = &pdev->dev;
@@ -349,13 +388,6 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
349388
return ret;
350389
}
351390

352-
ret = pci_alloc_irq_vectors(pdev, IFCVF_MAX_INTR,
353-
IFCVF_MAX_INTR, PCI_IRQ_MSIX);
354-
if (ret < 0) {
355-
IFCVF_ERR(pdev, "Failed to alloc irq vectors\n");
356-
return ret;
357-
}
358-
359391
ret = devm_add_action_or_reset(dev, ifcvf_free_irq_vectors, pdev);
360392
if (ret) {
361393
IFCVF_ERR(pdev,
@@ -379,12 +411,6 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
379411
adapter->pdev = pdev;
380412
adapter->vdpa.dma_dev = &pdev->dev;
381413

382-
ret = ifcvf_request_irq(adapter);
383-
if (ret) {
384-
IFCVF_ERR(pdev, "Failed to request MSI-X irq\n");
385-
goto err;
386-
}
387-
388414
ret = ifcvf_init_hw(vf, pdev);
389415
if (ret) {
390416
IFCVF_ERR(pdev, "Failed to init IFCVF hw\n");

0 commit comments

Comments
 (0)