Skip to content

Commit 1df7d87

Browse files
Amit Cohenkuba-moo
authored andcommitted
mlxsw: pci: Break mlxsw_pci_cq_tasklet() into tasklets per queue type
Completion queues are used for completions of RDQ or SDQ. Each completion queue is used for one DQ. The first CQs are used for SDQs and the rest are used for RDQs. Currently, for each CQE (completion queue element), we check 'sr' value (send/receive) to know if it is completion of RDQ or SDQ. Actually, we do not really have to check it, as according to the queue number we know if it handles completions of Rx or Tx. Break the tasklet into two - one for Rx (RDQ) and one for Tx (SDQ). Then, setup the appropriate tasklet for each queue as part of queue initialization. Use 'sr' value for unlikely case that we get completion with type that we do not expect. Call WARN_ON_ONCE() only after checking the value, to avoid calling this method for each completion. A next patch set will use NAPI to handle events, then we will have a separate poll method for Rx and Tx. This change is a preparation for NAPI usage. Signed-off-by: Amit Cohen <amcohen@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://lore.kernel.org/r/50fbc366f8de54cb5dc72a7c4f394333ef71f1d0.1712062203.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent a063923 commit 1df7d87

File tree

1 file changed

+74
-12
lines changed
  • drivers/net/ethernet/mellanox/mlxsw

1 file changed

+74
-12
lines changed

drivers/net/ethernet/mellanox/mlxsw/pci.c

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ enum mlxsw_pci_queue_type {
3535

3636
#define MLXSW_PCI_QUEUE_TYPE_COUNT 4
3737

38+
enum mlxsw_pci_cq_type {
39+
MLXSW_PCI_CQ_SDQ,
40+
MLXSW_PCI_CQ_RDQ,
41+
};
42+
3843
static const u16 mlxsw_pci_doorbell_type_offset[] = {
3944
MLXSW_PCI_DOORBELL_SDQ_OFFSET, /* for type MLXSW_PCI_QUEUE_TYPE_SDQ */
4045
MLXSW_PCI_DOORBELL_RDQ_OFFSET, /* for type MLXSW_PCI_QUEUE_TYPE_RDQ */
@@ -658,7 +663,7 @@ static char *mlxsw_pci_cq_sw_cqe_get(struct mlxsw_pci_queue *q)
658663
return elem;
659664
}
660665

661-
static void mlxsw_pci_cq_tasklet(struct tasklet_struct *t)
666+
static void mlxsw_pci_cq_rx_tasklet(struct tasklet_struct *t)
662667
{
663668
struct mlxsw_pci_queue *q = from_tasklet(q, t, tasklet);
664669
struct mlxsw_pci *mlxsw_pci = q->pci;
@@ -671,30 +676,87 @@ static void mlxsw_pci_cq_tasklet(struct tasklet_struct *t)
671676
u8 sendq = mlxsw_pci_cqe_sr_get(q->cq.v, cqe);
672677
u8 dqn = mlxsw_pci_cqe_dqn_get(q->cq.v, cqe);
673678
char ncqe[MLXSW_PCI_CQE_SIZE_MAX];
679+
struct mlxsw_pci_queue *rdq;
680+
681+
if (unlikely(sendq)) {
682+
WARN_ON_ONCE(1);
683+
continue;
684+
}
674685

675686
memcpy(ncqe, cqe, q->elem_size);
676687
mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
677688

678-
if (sendq) {
679-
struct mlxsw_pci_queue *sdq;
689+
rdq = mlxsw_pci_rdq_get(mlxsw_pci, dqn);
690+
mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq,
691+
wqe_counter, q->cq.v, ncqe);
692+
693+
if (++items == credits)
694+
break;
695+
}
680696

681-
sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn);
682-
mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq,
683-
wqe_counter, q->cq.v, ncqe);
684-
} else {
685-
struct mlxsw_pci_queue *rdq;
697+
mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
698+
}
686699

687-
rdq = mlxsw_pci_rdq_get(mlxsw_pci, dqn);
688-
mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq,
689-
wqe_counter, q->cq.v, ncqe);
700+
static void mlxsw_pci_cq_tx_tasklet(struct tasklet_struct *t)
701+
{
702+
struct mlxsw_pci_queue *q = from_tasklet(q, t, tasklet);
703+
struct mlxsw_pci *mlxsw_pci = q->pci;
704+
int credits = q->count >> 1;
705+
int items = 0;
706+
char *cqe;
707+
708+
while ((cqe = mlxsw_pci_cq_sw_cqe_get(q))) {
709+
u16 wqe_counter = mlxsw_pci_cqe_wqe_counter_get(cqe);
710+
u8 sendq = mlxsw_pci_cqe_sr_get(q->cq.v, cqe);
711+
u8 dqn = mlxsw_pci_cqe_dqn_get(q->cq.v, cqe);
712+
char ncqe[MLXSW_PCI_CQE_SIZE_MAX];
713+
struct mlxsw_pci_queue *sdq;
714+
715+
if (unlikely(!sendq)) {
716+
WARN_ON_ONCE(1);
717+
continue;
690718
}
719+
720+
memcpy(ncqe, cqe, q->elem_size);
721+
mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
722+
723+
sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn);
724+
mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq,
725+
wqe_counter, q->cq.v, ncqe);
726+
691727
if (++items == credits)
692728
break;
693729
}
694730

695731
mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
696732
}
697733

734+
static enum mlxsw_pci_cq_type
735+
mlxsw_pci_cq_type(const struct mlxsw_pci *mlxsw_pci,
736+
const struct mlxsw_pci_queue *q)
737+
{
738+
/* Each CQ is mapped to one DQ. The first 'num_sdq_cqs' queues are used
739+
* for SDQs and the rest are used for RDQs.
740+
*/
741+
if (q->num < mlxsw_pci->num_sdq_cqs)
742+
return MLXSW_PCI_CQ_SDQ;
743+
744+
return MLXSW_PCI_CQ_RDQ;
745+
}
746+
747+
static void mlxsw_pci_cq_tasklet_setup(struct mlxsw_pci_queue *q,
748+
enum mlxsw_pci_cq_type cq_type)
749+
{
750+
switch (cq_type) {
751+
case MLXSW_PCI_CQ_SDQ:
752+
tasklet_setup(&q->tasklet, mlxsw_pci_cq_tx_tasklet);
753+
break;
754+
case MLXSW_PCI_CQ_RDQ:
755+
tasklet_setup(&q->tasklet, mlxsw_pci_cq_rx_tasklet);
756+
break;
757+
}
758+
}
759+
698760
static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
699761
struct mlxsw_pci_queue *q)
700762
{
@@ -727,7 +789,7 @@ static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
727789
err = mlxsw_cmd_sw2hw_cq(mlxsw_pci->core, mbox, q->num);
728790
if (err)
729791
return err;
730-
tasklet_setup(&q->tasklet, mlxsw_pci_cq_tasklet);
792+
mlxsw_pci_cq_tasklet_setup(q, mlxsw_pci_cq_type(mlxsw_pci, q));
731793
mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
732794
mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
733795
return 0;

0 commit comments

Comments
 (0)