diff --git a/onic.h b/onic.h index 2b11c11..1368680 100644 --- a/onic.h +++ b/onic.h @@ -25,11 +25,14 @@ #define ONIC_MAX_QUEUES 64 /* state bits */ -#define ONIC_ERROR_INTR 0 +#define ONIC_MBOX_INTR 0 #define ONIC_USER_INTR 1 +#define ONIC_ERROR_INTR 2 /* flag bits */ #define ONIC_FLAG_MASTER_PF 0 +#define ONIC_FLAG_MBOX_INTR 1 +#define ONIC_FLAG_USER_INTR 2 struct onic_tx_buffer { struct sk_buff *skb; @@ -81,6 +84,7 @@ struct onic_rx_queue { }; struct onic_q_vector { + u16 qid; u16 vid; struct onic_private *priv; struct cpumask affinity_mask; diff --git a/onic_lib.c b/onic_lib.c index 331141d..769df65 100644 --- a/onic_lib.c +++ b/onic_lib.c @@ -29,7 +29,7 @@ static irqreturn_t onic_q_handler(int irq, void *dev_id) { struct onic_q_vector *vec = dev_id; struct onic_private *priv = vec->priv; - u16 qid = vec->vid; + u16 qid = vec->qid; struct onic_rx_queue *rxq = priv->rx_queue[qid]; bool debug = 0; if (debug) dev_info(&priv->pdev->dev, "queue irq"); @@ -39,6 +39,13 @@ static irqreturn_t onic_q_handler(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t onic_mailbox_handler(int irq, void *dev_id) +{ + struct onic_private *priv = dev_id; + dev_info(&priv->pdev->dev, "mailbox irq"); + return IRQ_HANDLED; +} + static irqreturn_t onic_user_handler(int irq, void *dev_id) { struct onic_private *priv = dev_id; @@ -76,28 +83,30 @@ static irqreturn_t onic_error_thread_fn(int irq, void *dev_id) /** * onic_init_q_vector - clear a queue vector * @priv: pointer to driver private data - * @vid: vector ID + * @idx: queue vector index **/ -static void onic_clear_q_vector(struct onic_private *priv, u16 vid) +static void onic_clear_q_vector(struct onic_private *priv, int idx) { - struct onic_q_vector *vec = priv->q_vector[vid]; + struct onic_q_vector *vec = priv->q_vector[idx]; if (!vec) return; - free_irq(pci_irq_vector(priv->pdev, vid), vec); + free_irq(pci_irq_vector(priv->pdev, vec->vid), vec); kfree(vec); + priv->q_vector[idx] = NULL; } /** * onic_init_q_vector - initialize a queue vector * @priv: pointer to driver private data + * @qid: queue ID * @vid: vector ID * * This function does the following: allocate coherent DMA region for interrupt * aggregation ring, register NAPI instances, and initialize relevant QDMA * interrupt registers. Return 0 on success, negative on failure **/ -static int onic_init_q_vector(struct onic_private *priv, u16 vid) +static int onic_init_q_vector(struct onic_private *priv, u16 qid, u16 vid) { struct pci_dev *pdev = priv->pdev; struct onic_q_vector *vec; @@ -109,8 +118,9 @@ static int onic_init_q_vector(struct onic_private *priv, u16 vid) return -ENOMEM; vec->priv = priv; vec->vid = vid; + vec->qid = qid; - snprintf(name, ONIC_MAX_IRQ_NAME, "%s-%d", priv->netdev->name, vid); + snprintf(name, ONIC_MAX_IRQ_NAME, "%s-%d", priv->netdev->name, qid); rv = request_irq(pci_irq_vector(pdev, vid), onic_q_handler, 0, name, vec); if (rv < 0) { @@ -119,13 +129,13 @@ static int onic_init_q_vector(struct onic_private *priv, u16 vid) } /* setup affinity mask and node */ - /* cpu = vid % num_online_cpus(); */ + /* cpu = qid % num_online_cpus(); */ /* cpumask_set_cpu(cpu, &vec->affinity_mask); */ /* vec->numa_node = node; */ dev_info(&pdev->dev, "Setup IRQ vector %d with name %s", pci_irq_vector(pdev, vid), name); - priv->q_vector[vid] = vec; + priv->q_vector[qid] = vec; return 0; } @@ -137,16 +147,20 @@ static int onic_init_q_vector(struct onic_private *priv, u16 vid) * Attempt to acquire a suitable range of MSI-X vector interrupts. Return 0 on * success, and negative on error. * - * For every PF, a minimum of 2 vectors are required for proper operation, one - * for queue interrupt and one for user interreupt. The master PF requires one - * additional vector for global error interrupt. + * For every PF, 1 optional mailbox interrupt, 1 optional user interrupt and at + * least 1 queue interupt is required. The master PF requires one additional + * vector for global error interrupt. **/ static int onic_acquire_msix_vectors(struct onic_private *priv) { int vectors, non_q_vectors; vectors = ONIC_MAX_QUEUES; - non_q_vectors = 1; + non_q_vectors = 0; + if (test_bit(ONIC_FLAG_MBOX_INTR, priv->flags)) + non_q_vectors++; + if (test_bit(ONIC_FLAG_USER_INTR, priv->flags)) + non_q_vectors++; if (test_bit(ONIC_FLAG_MASTER_PF, priv->flags)) non_q_vectors++; vectors += non_q_vectors; @@ -207,36 +221,56 @@ void onic_clear_capacity(struct onic_private *priv) int onic_init_interrupt(struct onic_private *priv) { struct pci_dev *pdev = priv->pdev; - int vid, rv; + u16 qid, vid; + int rv; - for (vid = 0; vid < priv->num_q_vectors; ++vid) { - rv = onic_init_q_vector(priv, vid); - if (rv < 0) + vid = 0; + if (test_bit(ONIC_FLAG_MBOX_INTR, priv->flags)) { + rv = request_irq(pci_irq_vector(pdev, vid), + onic_mailbox_handler, 0, "onic-mailbox", priv); + if (rv < 0) { + dev_err(&pdev->dev, + "Failed to setup mailbox interrupt"); goto clear_interrupt; + } + set_bit(ONIC_MBOX_INTR, priv->state); + vid++; } - rv = request_threaded_irq(pci_irq_vector(pdev, vid), - onic_user_handler, onic_user_thread_fn, - 0, "onic-user", priv); - if (rv < 0) { - dev_err(&pdev->dev, "Failed to setup user interrupt"); - goto clear_interrupt; + if (test_bit(ONIC_FLAG_USER_INTR, priv->flags)) { + rv = request_threaded_irq(pci_irq_vector(pdev, vid), + onic_user_handler, + onic_user_thread_fn, 0, "onic-user", + priv); + if (rv < 0) { + dev_err(&pdev->dev, "Failed to setup user interrupt"); + goto clear_interrupt; + } + set_bit(ONIC_USER_INTR, priv->state); + vid++; } - set_bit(ONIC_USER_INTR, priv->state); - if (!test_bit(ONIC_FLAG_MASTER_PF, priv->flags)) - return 0; + if (test_bit(ONIC_FLAG_MASTER_PF, priv->flags)) { + rv = request_threaded_irq(pci_irq_vector(pdev, vid), + onic_error_handler, + onic_error_thread_fn, 0, "onic-error", + priv); + if (rv < 0) { + dev_err(&pdev->dev, "Failed to setup error interrupt"); + goto clear_interrupt; + } + onic_qdma_init_error_interrupt(priv->hw.qdma, vid); + set_bit(ONIC_ERROR_INTR, priv->state); + vid++; + } - vid++; - rv = request_threaded_irq(pci_irq_vector(pdev, vid), - onic_error_handler, onic_error_thread_fn, - 0, "onic-error", priv); - if (rv < 0) { - dev_err(&pdev->dev, "Failed to setup error interrupt"); - goto clear_interrupt; + for (qid = 0; qid < priv->num_q_vectors; qid++) { + rv = onic_init_q_vector(priv, qid, vid); + if (rv < 0) { + goto clear_interrupt; + } + vid++; } - onic_qdma_init_error_interrupt(priv->hw.qdma, vid); - set_bit(ONIC_ERROR_INTR, priv->state); return 0; @@ -247,22 +281,27 @@ int onic_init_interrupt(struct onic_private *priv) void onic_clear_interrupt(struct onic_private *priv) { - u8 master_pf = test_bit(ONIC_FLAG_MASTER_PF, priv->flags); - int vid = (master_pf) ? - priv->num_q_vectors + 1 : - priv->num_q_vectors; - - if (master_pf) { - if (test_bit(ONIC_ERROR_INTR, priv->state)) { - free_irq(pci_irq_vector(priv->pdev, vid), priv); - onic_qdma_clear_error_interrupt(priv->hw.qdma); - } - vid--; + int vid, i; + + vid = 0; + if (test_bit(ONIC_FLAG_MBOX_INTR, priv->flags) && + test_bit(ONIC_MBOX_INTR, priv->state)) { + free_irq(pci_irq_vector(priv->pdev, vid), priv); + vid++; + } + + if (test_bit(ONIC_FLAG_USER_INTR, priv->flags) && + test_bit(ONIC_USER_INTR, priv->state)) { + free_irq(pci_irq_vector(priv->pdev, vid), priv); + vid++; } - if (test_bit(ONIC_USER_INTR, priv->state)) + if (test_bit(ONIC_FLAG_MASTER_PF, priv->flags) && + test_bit(ONIC_ERROR_INTR, priv->state)) { free_irq(pci_irq_vector(priv->pdev, vid), priv); + onic_qdma_clear_error_interrupt(priv->hw.qdma); + } - while (vid--) - onic_clear_q_vector(priv, vid); + for (i = 0; i < priv->num_q_vectors; i++) + onic_clear_q_vector(priv, i); } diff --git a/onic_netdev.c b/onic_netdev.c index a091af8..b314bab 100644 --- a/onic_netdev.c +++ b/onic_netdev.c @@ -346,7 +346,6 @@ static int onic_init_tx_queue(struct onic_private *priv, u16 qid) struct onic_tx_queue *q; struct onic_ring *ring; struct onic_qdma_h2c_param param; - u16 vid; u32 size, real_count; int rv; bool debug = 0; @@ -361,11 +360,8 @@ static int onic_init_tx_queue(struct onic_private *priv, u16 qid) if (!q) return -ENOMEM; - /* evenly assign to TX queues available vectors */ - vid = qid % priv->num_q_vectors; - q->netdev = dev; - q->vector = priv->q_vector[vid]; + q->vector = priv->q_vector[qid]; q->qid = qid; ring = &q->ring; @@ -398,7 +394,7 @@ static int onic_init_tx_queue(struct onic_private *priv, u16 qid) /* initialize QDMA H2C queue */ param.rngcnt_idx = rngcnt_idx; param.dma_addr = ring->dma_addr; - param.vid = vid; + param.vid = priv->q_vector[qid]->vid; rv = onic_qdma_init_tx_queue(priv->hw.qdma, qid, ¶m); if (rv < 0) goto clear_tx_queue; @@ -459,7 +455,6 @@ static int onic_init_rx_queue(struct onic_private *priv, u16 qid) struct onic_rx_queue *q; struct onic_ring *ring; struct onic_qdma_c2h_param param; - u16 vid; u32 size, real_count; int i, rv; bool debug = 0; @@ -474,11 +469,8 @@ static int onic_init_rx_queue(struct onic_private *priv, u16 qid) if (!q) return -ENOMEM; - /* evenly assign to RX queues available vectors */ - vid = qid % priv->num_q_vectors; - q->netdev = dev; - q->vector = priv->q_vector[vid]; + q->vector = priv->q_vector[qid]; q->qid = qid; /* allocate DMA memory for RX descriptor ring */ @@ -563,13 +555,14 @@ static int onic_init_rx_queue(struct onic_private *priv, u16 qid) param.cmpl_desc_sz = 0; param.desc_dma_addr = q->desc_ring.dma_addr; param.cmpl_dma_addr = q->cmpl_ring.dma_addr; - param.vid = vid; + param.vid = priv->q_vector[qid]->vid; if (debug) netdev_info( dev, "bufsz_idx %u, desc_rngcnt_idx %u, cmpl_rngcnt_idx %u, desc_dma_addr 0x%llx, cmpl_dma_addr 0x%llx, vid %d", bufsz_idx, desc_rngcnt_idx, cmpl_rngcnt_idx, - q->desc_ring.dma_addr, q->cmpl_ring.dma_addr, vid); + q->desc_ring.dma_addr, q->cmpl_ring.dma_addr, + priv->q_vector[qid]->vid); rv = onic_qdma_init_rx_queue(priv->hw.qdma, qid, ¶m); if (rv < 0)