|
@@ -66,8 +66,9 @@ struct nicpf {
|
|
/* MSI-X */
|
|
/* MSI-X */
|
|
bool msix_enabled;
|
|
bool msix_enabled;
|
|
u8 num_vec;
|
|
u8 num_vec;
|
|
- struct msix_entry msix_entries[NIC_PF_MSIX_VECTORS];
|
|
|
|
|
|
+ struct msix_entry *msix_entries;
|
|
bool irq_allocated[NIC_PF_MSIX_VECTORS];
|
|
bool irq_allocated[NIC_PF_MSIX_VECTORS];
|
|
|
|
+ char irq_name[NIC_PF_MSIX_VECTORS][20];
|
|
};
|
|
};
|
|
|
|
|
|
/* Supported devices */
|
|
/* Supported devices */
|
|
@@ -105,9 +106,22 @@ static u64 nic_reg_read(struct nicpf *nic, u64 offset)
|
|
/* PF -> VF mailbox communication APIs */
|
|
/* PF -> VF mailbox communication APIs */
|
|
static void nic_enable_mbx_intr(struct nicpf *nic)
|
|
static void nic_enable_mbx_intr(struct nicpf *nic)
|
|
{
|
|
{
|
|
- /* Enable mailbox interrupt for all 128 VFs */
|
|
|
|
- nic_reg_write(nic, NIC_PF_MAILBOX_ENA_W1S, ~0ull);
|
|
|
|
- nic_reg_write(nic, NIC_PF_MAILBOX_ENA_W1S + sizeof(u64), ~0ull);
|
|
|
|
|
|
+ int vf_cnt = pci_sriov_get_totalvfs(nic->pdev);
|
|
|
|
+
|
|
|
|
+#define INTR_MASK(vfs) ((vfs < 64) ? (BIT_ULL(vfs) - 1) : (~0ull))
|
|
|
|
+
|
|
|
|
+ /* Clear it, to avoid spurious interrupts (if any) */
|
|
|
|
+ nic_reg_write(nic, NIC_PF_MAILBOX_INT, INTR_MASK(vf_cnt));
|
|
|
|
+
|
|
|
|
+ /* Enable mailbox interrupt for all VFs */
|
|
|
|
+ nic_reg_write(nic, NIC_PF_MAILBOX_ENA_W1S, INTR_MASK(vf_cnt));
|
|
|
|
+ /* One mailbox intr enable reg per 64 VFs */
|
|
|
|
+ if (vf_cnt > 64) {
|
|
|
|
+ nic_reg_write(nic, NIC_PF_MAILBOX_INT + sizeof(u64),
|
|
|
|
+ INTR_MASK(vf_cnt - 64));
|
|
|
|
+ nic_reg_write(nic, NIC_PF_MAILBOX_ENA_W1S + sizeof(u64),
|
|
|
|
+ INTR_MASK(vf_cnt - 64));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
static void nic_clear_mbx_intr(struct nicpf *nic, int vf, int mbx_reg)
|
|
static void nic_clear_mbx_intr(struct nicpf *nic, int vf, int mbx_reg)
|
|
@@ -894,11 +908,18 @@ unlock:
|
|
nic->mbx_lock[vf] = false;
|
|
nic->mbx_lock[vf] = false;
|
|
}
|
|
}
|
|
|
|
|
|
-static void nic_mbx_intr_handler (struct nicpf *nic, int mbx)
|
|
|
|
|
|
+static irqreturn_t nic_mbx_intr_handler(int irq, void *nic_irq)
|
|
{
|
|
{
|
|
|
|
+ struct nicpf *nic = (struct nicpf *)nic_irq;
|
|
|
|
+ int mbx;
|
|
u64 intr;
|
|
u64 intr;
|
|
u8 vf, vf_per_mbx_reg = 64;
|
|
u8 vf, vf_per_mbx_reg = 64;
|
|
|
|
|
|
|
|
+ if (irq == nic->msix_entries[NIC_PF_INTR_ID_MBOX0].vector)
|
|
|
|
+ mbx = 0;
|
|
|
|
+ else
|
|
|
|
+ mbx = 1;
|
|
|
|
+
|
|
intr = nic_reg_read(nic, NIC_PF_MAILBOX_INT + (mbx << 3));
|
|
intr = nic_reg_read(nic, NIC_PF_MAILBOX_INT + (mbx << 3));
|
|
dev_dbg(&nic->pdev->dev, "PF interrupt Mbox%d 0x%llx\n", mbx, intr);
|
|
dev_dbg(&nic->pdev->dev, "PF interrupt Mbox%d 0x%llx\n", mbx, intr);
|
|
for (vf = 0; vf < vf_per_mbx_reg; vf++) {
|
|
for (vf = 0; vf < vf_per_mbx_reg; vf++) {
|
|
@@ -910,23 +931,6 @@ static void nic_mbx_intr_handler (struct nicpf *nic, int mbx)
|
|
nic_clear_mbx_intr(nic, vf, mbx);
|
|
nic_clear_mbx_intr(nic, vf, mbx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-}
|
|
|
|
-
|
|
|
|
-static irqreturn_t nic_mbx0_intr_handler (int irq, void *nic_irq)
|
|
|
|
-{
|
|
|
|
- struct nicpf *nic = (struct nicpf *)nic_irq;
|
|
|
|
-
|
|
|
|
- nic_mbx_intr_handler(nic, 0);
|
|
|
|
-
|
|
|
|
- return IRQ_HANDLED;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static irqreturn_t nic_mbx1_intr_handler (int irq, void *nic_irq)
|
|
|
|
-{
|
|
|
|
- struct nicpf *nic = (struct nicpf *)nic_irq;
|
|
|
|
-
|
|
|
|
- nic_mbx_intr_handler(nic, 1);
|
|
|
|
-
|
|
|
|
return IRQ_HANDLED;
|
|
return IRQ_HANDLED;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -934,7 +938,13 @@ static int nic_enable_msix(struct nicpf *nic)
|
|
{
|
|
{
|
|
int i, ret;
|
|
int i, ret;
|
|
|
|
|
|
- nic->num_vec = NIC_PF_MSIX_VECTORS;
|
|
|
|
|
|
+ nic->num_vec = pci_msix_vec_count(nic->pdev);
|
|
|
|
+
|
|
|
|
+ nic->msix_entries = kmalloc_array(nic->num_vec,
|
|
|
|
+ sizeof(struct msix_entry),
|
|
|
|
+ GFP_KERNEL);
|
|
|
|
+ if (!nic->msix_entries)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
for (i = 0; i < nic->num_vec; i++)
|
|
for (i = 0; i < nic->num_vec; i++)
|
|
nic->msix_entries[i].entry = i;
|
|
nic->msix_entries[i].entry = i;
|
|
@@ -942,8 +952,9 @@ static int nic_enable_msix(struct nicpf *nic)
|
|
ret = pci_enable_msix(nic->pdev, nic->msix_entries, nic->num_vec);
|
|
ret = pci_enable_msix(nic->pdev, nic->msix_entries, nic->num_vec);
|
|
if (ret) {
|
|
if (ret) {
|
|
dev_err(&nic->pdev->dev,
|
|
dev_err(&nic->pdev->dev,
|
|
- "Request for #%d msix vectors failed\n",
|
|
|
|
- nic->num_vec);
|
|
|
|
|
|
+ "Request for #%d msix vectors failed, returned %d\n",
|
|
|
|
+ nic->num_vec, ret);
|
|
|
|
+ kfree(nic->msix_entries);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -955,6 +966,7 @@ static void nic_disable_msix(struct nicpf *nic)
|
|
{
|
|
{
|
|
if (nic->msix_enabled) {
|
|
if (nic->msix_enabled) {
|
|
pci_disable_msix(nic->pdev);
|
|
pci_disable_msix(nic->pdev);
|
|
|
|
+ kfree(nic->msix_entries);
|
|
nic->msix_enabled = 0;
|
|
nic->msix_enabled = 0;
|
|
nic->num_vec = 0;
|
|
nic->num_vec = 0;
|
|
}
|
|
}
|
|
@@ -973,27 +985,26 @@ static void nic_free_all_interrupts(struct nicpf *nic)
|
|
|
|
|
|
static int nic_register_interrupts(struct nicpf *nic)
|
|
static int nic_register_interrupts(struct nicpf *nic)
|
|
{
|
|
{
|
|
- int ret;
|
|
|
|
|
|
+ int i, ret;
|
|
|
|
|
|
/* Enable MSI-X */
|
|
/* Enable MSI-X */
|
|
ret = nic_enable_msix(nic);
|
|
ret = nic_enable_msix(nic);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- /* Register mailbox interrupt handlers */
|
|
|
|
- ret = request_irq(nic->msix_entries[NIC_PF_INTR_ID_MBOX0].vector,
|
|
|
|
- nic_mbx0_intr_handler, 0, "NIC Mbox0", nic);
|
|
|
|
- if (ret)
|
|
|
|
- goto fail;
|
|
|
|
|
|
+ /* Register mailbox interrupt handler */
|
|
|
|
+ for (i = NIC_PF_INTR_ID_MBOX0; i < nic->num_vec; i++) {
|
|
|
|
+ sprintf(nic->irq_name[i],
|
|
|
|
+ "NICPF Mbox%d", (i - NIC_PF_INTR_ID_MBOX0));
|
|
|
|
|
|
- nic->irq_allocated[NIC_PF_INTR_ID_MBOX0] = true;
|
|
|
|
|
|
+ ret = request_irq(nic->msix_entries[i].vector,
|
|
|
|
+ nic_mbx_intr_handler, 0,
|
|
|
|
+ nic->irq_name[i], nic);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto fail;
|
|
|
|
|
|
- ret = request_irq(nic->msix_entries[NIC_PF_INTR_ID_MBOX1].vector,
|
|
|
|
- nic_mbx1_intr_handler, 0, "NIC Mbox1", nic);
|
|
|
|
- if (ret)
|
|
|
|
- goto fail;
|
|
|
|
-
|
|
|
|
- nic->irq_allocated[NIC_PF_INTR_ID_MBOX1] = true;
|
|
|
|
|
|
+ nic->irq_allocated[i] = true;
|
|
|
|
+ }
|
|
|
|
|
|
/* Enable mailbox interrupt */
|
|
/* Enable mailbox interrupt */
|
|
nic_enable_mbx_intr(nic);
|
|
nic_enable_mbx_intr(nic);
|
|
@@ -1002,6 +1013,7 @@ static int nic_register_interrupts(struct nicpf *nic)
|
|
fail:
|
|
fail:
|
|
dev_err(&nic->pdev->dev, "Request irq failed\n");
|
|
dev_err(&nic->pdev->dev, "Request irq failed\n");
|
|
nic_free_all_interrupts(nic);
|
|
nic_free_all_interrupts(nic);
|
|
|
|
+ nic_disable_msix(nic);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|