Skip to content

Commit 26f8ce0

Browse files
Shijith Thottonmstsirkin
authored andcommitted
vdpa/octeon_ep: enable support for multiple interrupts per device
Updated the driver to utilize all the MSI-X interrupt vectors supported by each OCTEON endpoint VF, instead of relying on a single vector. Enabling more interrupts allows packets from multiple rings to be distributed across multiple cores, improving parallelism and performance. Reviewed-by: Dan Carpenter <[email protected]> Acked-by: Jason Wang <[email protected]> Signed-off-by: Shijith Thotton <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 6f3955a commit 26f8ce0

File tree

3 files changed

+62
-39
lines changed

3 files changed

+62
-39
lines changed

drivers/vdpa/octeon_ep/octep_vdpa.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@
2929
#define OCTEP_EPF_RINFO(x) (0x000209f0 | ((x) << 25))
3030
#define OCTEP_VF_MBOX_DATA(x) (0x00010210 | ((x) << 17))
3131
#define OCTEP_PF_MBOX_DATA(x) (0x00022000 | ((x) << 4))
32-
33-
#define OCTEP_EPF_RINFO_RPVF(val) (((val) >> 32) & 0xF)
34-
#define OCTEP_EPF_RINFO_NVFS(val) (((val) >> 48) & 0x7F)
32+
#define OCTEP_VF_IN_CTRL(x) (0x00010000 | ((x) << 17))
33+
#define OCTEP_VF_IN_CTRL_RPVF(val) (((val) >> 48) & 0xF)
3534

3635
#define OCTEP_FW_READY_SIGNATURE0 0xFEEDFEED
3736
#define OCTEP_FW_READY_SIGNATURE1 0x3355ffaa
37+
#define OCTEP_MAX_CB_INTR 8
3838

3939
enum octep_vdpa_dev_status {
4040
OCTEP_VDPA_DEV_STATUS_INVALID,
@@ -48,9 +48,8 @@ enum octep_vdpa_dev_status {
4848
struct octep_vring_info {
4949
struct vdpa_callback cb;
5050
void __iomem *notify_addr;
51-
u32 __iomem *cb_notify_addr;
51+
void __iomem *cb_notify_addr;
5252
phys_addr_t notify_pa;
53-
char msix_name[256];
5453
};
5554

5655
struct octep_hw {
@@ -68,7 +67,8 @@ struct octep_hw {
6867
u64 features;
6968
u16 nr_vring;
7069
u32 config_size;
71-
int irq;
70+
int nb_irqs;
71+
int *irqs;
7272
};
7373

7474
u8 octep_hw_get_status(struct octep_hw *oct_hw);

drivers/vdpa/octeon_ep/octep_vdpa_hw.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,8 +495,6 @@ int octep_hw_caps_read(struct octep_hw *oct_hw, struct pci_dev *pdev)
495495
if (!oct_hw->vqs)
496496
return -ENOMEM;
497497

498-
oct_hw->irq = -1;
499-
500498
dev_info(&pdev->dev, "Device features : %llx\n", oct_hw->features);
501499
dev_info(&pdev->dev, "Maximum queues : %u\n", oct_hw->nr_vring);
502500

drivers/vdpa/octeon_ep/octep_vdpa_main.c

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,25 @@ static irqreturn_t octep_vdpa_intr_handler(int irq, void *data)
4949
struct octep_hw *oct_hw = data;
5050
int i;
5151

52-
for (i = 0; i < oct_hw->nr_vring; i++) {
53-
if (oct_hw->vqs[i].cb.callback && ioread32(oct_hw->vqs[i].cb_notify_addr)) {
54-
/* Acknowledge the per queue notification to the device */
55-
iowrite32(0, oct_hw->vqs[i].cb_notify_addr);
56-
oct_hw->vqs[i].cb.callback(oct_hw->vqs[i].cb.private);
52+
/* Each device has multiple interrupts (nb_irqs) shared among rings
53+
* (nr_vring). Device interrupts are mapped to the rings in a
54+
* round-robin fashion.
55+
*
56+
* For example, if nb_irqs = 8 and nr_vring = 64:
57+
* 0 -> 0, 8, 16, 24, 32, 40, 48, 56;
58+
* 1 -> 1, 9, 17, 25, 33, 41, 49, 57;
59+
* ...
60+
* 7 -> 7, 15, 23, 31, 39, 47, 55, 63;
61+
*/
62+
63+
for (i = irq - oct_hw->irqs[0]; i < oct_hw->nr_vring; i += oct_hw->nb_irqs) {
64+
if (ioread8(oct_hw->vqs[i].cb_notify_addr)) {
65+
/* Acknowledge the per ring notification to the device */
66+
iowrite8(0, oct_hw->vqs[i].cb_notify_addr);
67+
68+
if (likely(oct_hw->vqs[i].cb.callback))
69+
oct_hw->vqs[i].cb.callback(oct_hw->vqs[i].cb.private);
70+
break;
5771
}
5872
}
5973

@@ -63,44 +77,53 @@ static irqreturn_t octep_vdpa_intr_handler(int irq, void *data)
6377
static void octep_free_irqs(struct octep_hw *oct_hw)
6478
{
6579
struct pci_dev *pdev = oct_hw->pdev;
80+
int irq;
81+
82+
if (!oct_hw->irqs)
83+
return;
6684

67-
if (oct_hw->irq != -1) {
68-
devm_free_irq(&pdev->dev, oct_hw->irq, oct_hw);
69-
oct_hw->irq = -1;
85+
for (irq = 0; irq < oct_hw->nb_irqs; irq++) {
86+
if (!oct_hw->irqs[irq])
87+
break;
88+
89+
devm_free_irq(&pdev->dev, oct_hw->irqs[irq], oct_hw);
7090
}
91+
7192
pci_free_irq_vectors(pdev);
93+
devm_kfree(&pdev->dev, oct_hw->irqs);
94+
oct_hw->irqs = NULL;
7295
}
7396

7497
static int octep_request_irqs(struct octep_hw *oct_hw)
7598
{
7699
struct pci_dev *pdev = oct_hw->pdev;
77-
int ret, irq;
100+
int ret, irq, idx;
78101

79-
/* Currently HW device provisions one IRQ per VF, hence
80-
* allocate one IRQ for all virtqueues call interface.
81-
*/
82-
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
102+
oct_hw->irqs = devm_kcalloc(&pdev->dev, oct_hw->nb_irqs, sizeof(int), GFP_KERNEL);
103+
if (!oct_hw->irqs)
104+
return -ENOMEM;
105+
106+
ret = pci_alloc_irq_vectors(pdev, 1, oct_hw->nb_irqs, PCI_IRQ_MSIX);
83107
if (ret < 0) {
84108
dev_err(&pdev->dev, "Failed to alloc msix vector");
85109
return ret;
86110
}
87111

88-
snprintf(oct_hw->vqs->msix_name, sizeof(oct_hw->vqs->msix_name),
89-
OCTEP_VDPA_DRIVER_NAME "-vf-%d", pci_iov_vf_id(pdev));
90-
91-
irq = pci_irq_vector(pdev, 0);
92-
ret = devm_request_irq(&pdev->dev, irq, octep_vdpa_intr_handler, 0,
93-
oct_hw->vqs->msix_name, oct_hw);
94-
if (ret) {
95-
dev_err(&pdev->dev, "Failed to register interrupt handler\n");
96-
goto free_irq_vec;
112+
for (idx = 0; idx < oct_hw->nb_irqs; idx++) {
113+
irq = pci_irq_vector(pdev, idx);
114+
ret = devm_request_irq(&pdev->dev, irq, octep_vdpa_intr_handler, 0,
115+
dev_name(&pdev->dev), oct_hw);
116+
if (ret) {
117+
dev_err(&pdev->dev, "Failed to register interrupt handler\n");
118+
goto free_irqs;
119+
}
120+
oct_hw->irqs[idx] = irq;
97121
}
98-
oct_hw->irq = irq;
99122

100123
return 0;
101124

102-
free_irq_vec:
103-
pci_free_irq_vectors(pdev);
125+
free_irqs:
126+
octep_free_irqs(oct_hw);
104127
return ret;
105128
}
106129

@@ -559,6 +582,7 @@ static void octep_vdpa_setup_task(struct work_struct *work)
559582
struct device *dev = &pdev->dev;
560583
struct octep_hw *oct_hw;
561584
unsigned long timeout;
585+
u64 val;
562586
int ret;
563587

564588
oct_hw = &mgmt_dev->oct_hw;
@@ -590,6 +614,13 @@ static void octep_vdpa_setup_task(struct work_struct *work)
590614
if (ret)
591615
return;
592616

617+
val = readq(oct_hw->base[OCTEP_HW_MBOX_BAR] + OCTEP_VF_IN_CTRL(0));
618+
oct_hw->nb_irqs = OCTEP_VF_IN_CTRL_RPVF(val);
619+
if (!oct_hw->nb_irqs || oct_hw->nb_irqs > OCTEP_MAX_CB_INTR) {
620+
dev_err(dev, "Invalid number of interrupts %d\n", oct_hw->nb_irqs);
621+
goto unmap_region;
622+
}
623+
593624
ret = octep_hw_caps_read(oct_hw, pdev);
594625
if (ret < 0)
595626
goto unmap_region;
@@ -768,12 +799,6 @@ static int octep_vdpa_pf_setup(struct octep_pf *octpf)
768799
return -EINVAL;
769800
}
770801

771-
if (OCTEP_EPF_RINFO_RPVF(val) != BIT_ULL(0)) {
772-
val &= ~GENMASK_ULL(35, 32);
773-
val |= BIT_ULL(32);
774-
writeq(val, addr + OCTEP_EPF_RINFO(0));
775-
}
776-
777802
len = pci_resource_len(pdev, OCTEP_HW_CAPS_BAR);
778803

779804
octpf->vf_stride = len / totalvfs;

0 commit comments

Comments
 (0)