Skip to content

Commit c0a6c5c

Browse files
ahubbe-amdmstsirkin
authored andcommitted
pds_vdpa: alloc irq vectors on DRIVER_OK
We were allocating irq vectors at the time the aux dev was probed, but that is before the PCI VF is assigned to a separate iommu domain by vhost_vdpa. Because vhost_vdpa later changes the iommu domain the interrupts do not work. Instead, we can allocate the irq vectors later when we see DRIVER_OK and know that the reassignment of the PCI VF to an iommu domain has already happened. Fixes: 151cc83 ("pds_vdpa: add support for vdpa and vdpamgmt interfaces") Signed-off-by: Allen Hubbe <allen.hubbe@amd.com> Signed-off-by: Shannon Nelson <shannon.nelson@amd.com> Acked-by: Jason Wang <jasowang@redhat.com> Message-Id: <20230711042437.69381-5-shannon.nelson@amd.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
1 parent ed88863 commit c0a6c5c

File tree

1 file changed

+81
-29
lines changed

1 file changed

+81
-29
lines changed

drivers/vdpa/pds/vdpa_dev.c

Lines changed: 81 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,9 @@ static void pds_vdpa_release_irq(struct pds_vdpa_device *pdsv, int qid)
126126
static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool ready)
127127
{
128128
struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
129-
struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
130129
struct device *dev = &pdsv->vdpa_dev.dev;
131130
u64 driver_features;
132131
u16 invert_idx = 0;
133-
int irq;
134132
int err;
135133

136134
dev_dbg(dev, "%s: qid %d ready %d => %d\n",
@@ -143,19 +141,6 @@ static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool re
143141
invert_idx = PDS_VDPA_PACKED_INVERT_IDX;
144142

145143
if (ready) {
146-
irq = pci_irq_vector(pdev, qid);
147-
snprintf(pdsv->vqs[qid].irq_name, sizeof(pdsv->vqs[qid].irq_name),
148-
"vdpa-%s-%d", dev_name(dev), qid);
149-
150-
err = request_irq(irq, pds_vdpa_isr, 0,
151-
pdsv->vqs[qid].irq_name, &pdsv->vqs[qid]);
152-
if (err) {
153-
dev_err(dev, "%s: no irq for qid %d: %pe\n",
154-
__func__, qid, ERR_PTR(err));
155-
return;
156-
}
157-
pdsv->vqs[qid].irq = irq;
158-
159144
/* Pass vq setup info to DSC using adminq to gather up and
160145
* send all info at once so FW can do its full set up in
161146
* one easy operation
@@ -164,15 +149,13 @@ static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool re
164149
if (err) {
165150
dev_err(dev, "Failed to init vq %d: %pe\n",
166151
qid, ERR_PTR(err));
167-
pds_vdpa_release_irq(pdsv, qid);
168152
ready = false;
169153
}
170154
} else {
171155
err = pds_vdpa_cmd_reset_vq(pdsv, qid, invert_idx, &pdsv->vqs[qid]);
172156
if (err)
173157
dev_err(dev, "%s: reset_vq failed qid %d: %pe\n",
174158
__func__, qid, ERR_PTR(err));
175-
pds_vdpa_release_irq(pdsv, qid);
176159
}
177160

178161
pdsv->vqs[qid].ready = ready;
@@ -395,6 +378,72 @@ static u8 pds_vdpa_get_status(struct vdpa_device *vdpa_dev)
395378
return vp_modern_get_status(&pdsv->vdpa_aux->vd_mdev);
396379
}
397380

381+
static int pds_vdpa_request_irqs(struct pds_vdpa_device *pdsv)
382+
{
383+
struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
384+
struct pds_vdpa_aux *vdpa_aux = pdsv->vdpa_aux;
385+
struct device *dev = &pdsv->vdpa_dev.dev;
386+
int max_vq, nintrs, qid, err;
387+
388+
max_vq = vdpa_aux->vdpa_mdev.max_supported_vqs;
389+
390+
nintrs = pci_alloc_irq_vectors(pdev, max_vq, max_vq, PCI_IRQ_MSIX);
391+
if (nintrs < 0) {
392+
dev_err(dev, "Couldn't get %d msix vectors: %pe\n",
393+
max_vq, ERR_PTR(nintrs));
394+
return nintrs;
395+
}
396+
397+
for (qid = 0; qid < pdsv->num_vqs; ++qid) {
398+
int irq = pci_irq_vector(pdev, qid);
399+
400+
snprintf(pdsv->vqs[qid].irq_name, sizeof(pdsv->vqs[qid].irq_name),
401+
"vdpa-%s-%d", dev_name(dev), qid);
402+
403+
err = request_irq(irq, pds_vdpa_isr, 0,
404+
pdsv->vqs[qid].irq_name,
405+
&pdsv->vqs[qid]);
406+
if (err) {
407+
dev_err(dev, "%s: no irq for qid %d: %pe\n",
408+
__func__, qid, ERR_PTR(err));
409+
goto err_release;
410+
}
411+
412+
pdsv->vqs[qid].irq = irq;
413+
}
414+
415+
vdpa_aux->nintrs = nintrs;
416+
417+
return 0;
418+
419+
err_release:
420+
while (qid--)
421+
pds_vdpa_release_irq(pdsv, qid);
422+
423+
pci_free_irq_vectors(pdev);
424+
425+
vdpa_aux->nintrs = 0;
426+
427+
return err;
428+
}
429+
430+
static void pds_vdpa_release_irqs(struct pds_vdpa_device *pdsv)
431+
{
432+
struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
433+
struct pds_vdpa_aux *vdpa_aux = pdsv->vdpa_aux;
434+
int qid;
435+
436+
if (!vdpa_aux->nintrs)
437+
return;
438+
439+
for (qid = 0; qid < pdsv->num_vqs; qid++)
440+
pds_vdpa_release_irq(pdsv, qid);
441+
442+
pci_free_irq_vectors(pdev);
443+
444+
vdpa_aux->nintrs = 0;
445+
}
446+
398447
static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
399448
{
400449
struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
@@ -405,6 +454,11 @@ static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
405454
old_status = pds_vdpa_get_status(vdpa_dev);
406455
dev_dbg(dev, "%s: old %#x new %#x\n", __func__, old_status, status);
407456

457+
if (status & ~old_status & VIRTIO_CONFIG_S_DRIVER_OK) {
458+
if (pds_vdpa_request_irqs(pdsv))
459+
status = old_status | VIRTIO_CONFIG_S_FAILED;
460+
}
461+
408462
pds_vdpa_cmd_set_status(pdsv, status);
409463

410464
/* Note: still working with FW on the need for this reset cmd */
@@ -426,6 +480,9 @@ static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
426480
i, &pdsv->vqs[i].notify_pa);
427481
}
428482
}
483+
484+
if (old_status & ~status & VIRTIO_CONFIG_S_DRIVER_OK)
485+
pds_vdpa_release_irqs(pdsv);
429486
}
430487

431488
static void pds_vdpa_init_vqs_entry(struct pds_vdpa_device *pdsv, int qid,
@@ -460,13 +517,17 @@ static int pds_vdpa_reset(struct vdpa_device *vdpa_dev)
460517
if (err)
461518
dev_err(dev, "%s: reset_vq failed qid %d: %pe\n",
462519
__func__, i, ERR_PTR(err));
463-
pds_vdpa_release_irq(pdsv, i);
464-
pds_vdpa_init_vqs_entry(pdsv, i, pdsv->vqs[i].notify);
465520
}
466521
}
467522

468523
pds_vdpa_set_status(vdpa_dev, 0);
469524

525+
if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
526+
/* Reset the vq info */
527+
for (i = 0; i < pdsv->num_vqs && !err; i++)
528+
pds_vdpa_init_vqs_entry(pdsv, i, pdsv->vqs[i].notify);
529+
}
530+
470531
return 0;
471532
}
472533

@@ -764,7 +825,7 @@ int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux)
764825

765826
max_vqs = min_t(u16, dev_intrs, max_vqs);
766827
mgmt->max_supported_vqs = min_t(u16, PDS_VDPA_MAX_QUEUES, max_vqs);
767-
vdpa_aux->nintrs = mgmt->max_supported_vqs;
828+
vdpa_aux->nintrs = 0;
768829

769830
mgmt->ops = &pds_vdpa_mgmt_dev_ops;
770831
mgmt->id_table = pds_vdpa_id_table;
@@ -778,14 +839,5 @@ int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux)
778839
mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP);
779840
mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_FEATURES);
780841

781-
err = pci_alloc_irq_vectors(pdev, vdpa_aux->nintrs, vdpa_aux->nintrs,
782-
PCI_IRQ_MSIX);
783-
if (err < 0) {
784-
dev_err(dev, "Couldn't get %d msix vectors: %pe\n",
785-
vdpa_aux->nintrs, ERR_PTR(err));
786-
return err;
787-
}
788-
vdpa_aux->nintrs = err;
789-
790842
return 0;
791843
}

0 commit comments

Comments
 (0)