Skip to content

Commit c9ebea0

Browse files
idoschdavem330
authored andcommitted
mlxsw: pci: Ring CQ's doorbell before RDQ's
When a packet should be trapped to the CPU the device consumes a WQE (work queue element) from an RDQ (receive descriptor queue) and copies the packet to the address specified in the WQE. The device then tries to post a CQE (completion queue element) that contains various metadata (e.g., ingress port) about the packet to a CQ (completion queue). In case the device managed to consume a WQE, but did not manage to post the corresponding CQE, it will get stuck. This unlikely situation can be triggered due to the scheme the driver is currently using to process CQEs. The driver will consume up to 512 CQEs at a time and after processing each corresponding WQE it will ring the RDQ's doorbell, letting the device know that a new WQE was posted for it to consume. Only after processing all the CQEs (up to 512), the driver will ring the CQ's doorbell, letting the device know that new ones can be posted. Fix this by having the driver ring the CQ's doorbell for every processed CQE, but before ringing the RDQ's doorbell. This guarantees that whenever we post a new WQE, there is a corresponding CQE available. Copy the currently processed CQE to prevent the device from overwriting it with a new CQE after ringing the doorbell. Note that the driver still arms the CQ only after processing all the pending CQEs, so that interrupts for this CQ will only be delivered after the driver finished its processing. Before commit 8404f6f ("mlxsw: pci: Allow to use CQEs of version 1 and version 2") the issue was virtually impossible to trigger since the number of CQEs was twice the number of WQEs and the number of CQEs processed at a time was equal to the number of available WQEs. Fixes: 8404f6f ("mlxsw: pci: Allow to use CQEs of version 1 and version 2") Signed-off-by: Ido Schimmel <idosch@mellanox.com> Reported-by: Semion Lisyansky <semionl@mellanox.com> Tested-by: Semion Lisyansky <semionl@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 20f5248 commit c9ebea0

File tree

2 files changed

+8
-5
lines changed

2 files changed

+8
-5
lines changed

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -604,29 +604,31 @@ static void mlxsw_pci_cq_tasklet(unsigned long data)
604604
u16 wqe_counter = mlxsw_pci_cqe_wqe_counter_get(cqe);
605605
u8 sendq = mlxsw_pci_cqe_sr_get(q->u.cq.v, cqe);
606606
u8 dqn = mlxsw_pci_cqe_dqn_get(q->u.cq.v, cqe);
607+
char ncqe[MLXSW_PCI_CQE_SIZE_MAX];
608+
609+
memcpy(ncqe, cqe, q->elem_size);
610+
mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
607611

608612
if (sendq) {
609613
struct mlxsw_pci_queue *sdq;
610614

611615
sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn);
612616
mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq,
613-
wqe_counter, cqe);
617+
wqe_counter, ncqe);
614618
q->u.cq.comp_sdq_count++;
615619
} else {
616620
struct mlxsw_pci_queue *rdq;
617621

618622
rdq = mlxsw_pci_rdq_get(mlxsw_pci, dqn);
619623
mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq,
620-
wqe_counter, q->u.cq.v, cqe);
624+
wqe_counter, q->u.cq.v, ncqe);
621625
q->u.cq.comp_rdq_count++;
622626
}
623627
if (++items == credits)
624628
break;
625629
}
626-
if (items) {
627-
mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
630+
if (items)
628631
mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
629-
}
630632
}
631633

632634
static u16 mlxsw_pci_cq_elem_count(const struct mlxsw_pci_queue *q)

drivers/net/ethernet/mellanox/mlxsw/pci_hw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#define MLXSW_PCI_WQE_SIZE 32 /* 32 bytes per element */
5454
#define MLXSW_PCI_CQE01_SIZE 16 /* 16 bytes per element */
5555
#define MLXSW_PCI_CQE2_SIZE 32 /* 32 bytes per element */
56+
#define MLXSW_PCI_CQE_SIZE_MAX MLXSW_PCI_CQE2_SIZE
5657
#define MLXSW_PCI_EQE_SIZE 16 /* 16 bytes per element */
5758
#define MLXSW_PCI_WQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
5859
#define MLXSW_PCI_CQE01_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE01_SIZE)

0 commit comments

Comments
 (0)