Skip to content

Commit b69585b

Browse files
ahubbe-amdkuba-moo
authored andcommitted
ionic: missed doorbell workaround
In one version of the HW there is a remote possibility that it will miss the doorbell ring. This adds a bit of protection to be sure we don't stall a queue from a missed doorbell. Fixes: 0f3154e ("ionic: Add Tx and Rx handling") Signed-off-by: Allen Hubbe <[email protected]> Signed-off-by: Shannon Nelson <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 1fffb02 commit b69585b

File tree

6 files changed

+176
-4
lines changed

6 files changed

+176
-4
lines changed

drivers/net/ethernet/pensando/ionic/ionic_dev.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,9 +708,16 @@ void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb,
708708
q->lif->index, q->name, q->hw_type, q->hw_index,
709709
q->head_idx, ring_doorbell);
710710

711-
if (ring_doorbell)
711+
if (ring_doorbell) {
712712
ionic_dbell_ring(lif->kern_dbpage, q->hw_type,
713713
q->dbval | q->head_idx);
714+
715+
q->dbell_jiffies = jiffies;
716+
717+
if (q_to_qcq(q)->napi_qcq)
718+
mod_timer(&q_to_qcq(q)->napi_qcq->napi_deadline,
719+
jiffies + IONIC_NAPI_DEADLINE);
720+
}
714721
}
715722

716723
static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos)

drivers/net/ethernet/pensando/ionic/ionic_dev.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
#define IONIC_DEV_INFO_REG_COUNT 32
2626
#define IONIC_DEV_CMD_REG_COUNT 32
2727

28+
#define IONIC_NAPI_DEADLINE (HZ / 200) /* 5ms */
29+
#define IONIC_ADMIN_DOORBELL_DEADLINE (HZ / 2) /* 500ms */
30+
#define IONIC_TX_DOORBELL_DEADLINE (HZ / 100) /* 10ms */
31+
#define IONIC_RX_MIN_DOORBELL_DEADLINE (HZ / 100) /* 10ms */
32+
#define IONIC_RX_MAX_DOORBELL_DEADLINE (HZ * 5) /* 5s */
33+
2834
struct ionic_dev_bar {
2935
void __iomem *vaddr;
3036
phys_addr_t bus_addr;
@@ -216,6 +222,8 @@ struct ionic_queue {
216222
struct ionic_lif *lif;
217223
struct ionic_desc_info *info;
218224
u64 dbval;
225+
unsigned long dbell_deadline;
226+
unsigned long dbell_jiffies;
219227
u16 head_idx;
220228
u16 tail_idx;
221229
unsigned int index;
@@ -361,4 +369,8 @@ void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
361369
int ionic_heartbeat_check(struct ionic *ionic);
362370
bool ionic_is_fw_running(struct ionic_dev *idev);
363371

372+
bool ionic_adminq_poke_doorbell(struct ionic_queue *q);
373+
bool ionic_txq_poke_doorbell(struct ionic_queue *q);
374+
bool ionic_rxq_poke_doorbell(struct ionic_queue *q);
375+
364376
#endif /* _IONIC_DEV_H_ */

drivers/net/ethernet/pensando/ionic/ionic_lif.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "ionic.h"
1818
#include "ionic_bus.h"
19+
#include "ionic_dev.h"
1920
#include "ionic_lif.h"
2021
#include "ionic_txrx.h"
2122
#include "ionic_ethtool.h"
@@ -200,6 +201,13 @@ void ionic_link_status_check_request(struct ionic_lif *lif, bool can_sleep)
200201
}
201202
}
202203

204+
static void ionic_napi_deadline(struct timer_list *timer)
205+
{
206+
struct ionic_qcq *qcq = container_of(timer, struct ionic_qcq, napi_deadline);
207+
208+
napi_schedule(&qcq->napi);
209+
}
210+
203211
static irqreturn_t ionic_isr(int irq, void *data)
204212
{
205213
struct napi_struct *napi = data;
@@ -325,6 +333,7 @@ static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int f
325333
synchronize_irq(qcq->intr.vector);
326334
irq_set_affinity_hint(qcq->intr.vector, NULL);
327335
napi_disable(&qcq->napi);
336+
del_timer_sync(&qcq->napi_deadline);
328337
}
329338

330339
/* If there was a previous fw communcation error, don't bother with
@@ -460,6 +469,7 @@ static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
460469

461470
n_qcq->intr.vector = src_qcq->intr.vector;
462471
n_qcq->intr.index = src_qcq->intr.index;
472+
n_qcq->napi_qcq = src_qcq->napi_qcq;
463473
}
464474

465475
static int ionic_alloc_qcq_interrupt(struct ionic_lif *lif, struct ionic_qcq *qcq)
@@ -784,8 +794,14 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
784794
dev_dbg(dev, "txq->hw_type %d\n", q->hw_type);
785795
dev_dbg(dev, "txq->hw_index %d\n", q->hw_index);
786796

787-
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
797+
q->dbell_deadline = IONIC_TX_DOORBELL_DEADLINE;
798+
q->dbell_jiffies = jiffies;
799+
800+
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) {
788801
netif_napi_add(lif->netdev, &qcq->napi, ionic_tx_napi);
802+
qcq->napi_qcq = qcq;
803+
timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0);
804+
}
789805

790806
qcq->flags |= IONIC_QCQ_F_INITED;
791807

@@ -839,11 +855,17 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
839855
dev_dbg(dev, "rxq->hw_type %d\n", q->hw_type);
840856
dev_dbg(dev, "rxq->hw_index %d\n", q->hw_index);
841857

858+
q->dbell_deadline = IONIC_RX_MIN_DOORBELL_DEADLINE;
859+
q->dbell_jiffies = jiffies;
860+
842861
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
843862
netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi);
844863
else
845864
netif_napi_add(lif->netdev, &qcq->napi, ionic_txrx_napi);
846865

866+
qcq->napi_qcq = qcq;
867+
timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0);
868+
847869
qcq->flags |= IONIC_QCQ_F_INITED;
848870

849871
return 0;
@@ -1161,6 +1183,7 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
11611183
struct ionic_dev *idev = &lif->ionic->idev;
11621184
unsigned long irqflags;
11631185
unsigned int flags = 0;
1186+
bool resched = false;
11641187
int rx_work = 0;
11651188
int tx_work = 0;
11661189
int n_work = 0;
@@ -1198,6 +1221,16 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
11981221
ionic_intr_credits(idev->intr_ctrl, intr->index, credits, flags);
11991222
}
12001223

1224+
if (!a_work && ionic_adminq_poke_doorbell(&lif->adminqcq->q))
1225+
resched = true;
1226+
if (lif->hwstamp_rxq && !rx_work && ionic_rxq_poke_doorbell(&lif->hwstamp_rxq->q))
1227+
resched = true;
1228+
if (lif->hwstamp_txq && !tx_work && ionic_txq_poke_doorbell(&lif->hwstamp_txq->q))
1229+
resched = true;
1230+
if (resched)
1231+
mod_timer(&lif->adminqcq->napi_deadline,
1232+
jiffies + IONIC_NAPI_DEADLINE);
1233+
12011234
return work_done;
12021235
}
12031236

@@ -3256,8 +3289,14 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif)
32563289
dev_dbg(dev, "adminq->hw_type %d\n", q->hw_type);
32573290
dev_dbg(dev, "adminq->hw_index %d\n", q->hw_index);
32583291

3292+
q->dbell_deadline = IONIC_ADMIN_DOORBELL_DEADLINE;
3293+
q->dbell_jiffies = jiffies;
3294+
32593295
netif_napi_add(lif->netdev, &qcq->napi, ionic_adminq_napi);
32603296

3297+
qcq->napi_qcq = qcq;
3298+
timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0);
3299+
32613300
napi_enable(&qcq->napi);
32623301

32633302
if (qcq->flags & IONIC_QCQ_F_INTR)

drivers/net/ethernet/pensando/ionic/ionic_lif.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@ struct ionic_qcq {
7474
struct ionic_queue q;
7575
struct ionic_cq cq;
7676
struct ionic_intr_info intr;
77+
struct timer_list napi_deadline;
7778
struct napi_struct napi;
7879
unsigned int flags;
80+
struct ionic_qcq *napi_qcq;
7981
struct dentry *dentry;
8082
};
8183

drivers/net/ethernet/pensando/ionic/ionic_main.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,35 @@ static void ionic_adminq_cb(struct ionic_queue *q,
289289
complete_all(&ctx->work);
290290
}
291291

292+
bool ionic_adminq_poke_doorbell(struct ionic_queue *q)
293+
{
294+
struct ionic_lif *lif = q->lif;
295+
unsigned long now, then, dif;
296+
unsigned long irqflags;
297+
298+
spin_lock_irqsave(&lif->adminq_lock, irqflags);
299+
300+
if (q->tail_idx == q->head_idx) {
301+
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
302+
return false;
303+
}
304+
305+
now = READ_ONCE(jiffies);
306+
then = q->dbell_jiffies;
307+
dif = now - then;
308+
309+
if (dif > q->dbell_deadline) {
310+
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
311+
q->dbval | q->head_idx);
312+
313+
q->dbell_jiffies = now;
314+
}
315+
316+
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
317+
318+
return true;
319+
}
320+
292321
int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
293322
{
294323
struct ionic_desc_info *desc_info;

drivers/net/ethernet/pensando/ionic/ionic_txrx.c

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,67 @@ static inline void ionic_rxq_post(struct ionic_queue *q, bool ring_dbell,
2222
ionic_q_post(q, ring_dbell, cb_func, cb_arg);
2323
}
2424

25+
bool ionic_txq_poke_doorbell(struct ionic_queue *q)
26+
{
27+
unsigned long now, then, dif;
28+
struct netdev_queue *netdev_txq;
29+
struct net_device *netdev;
30+
31+
netdev = q->lif->netdev;
32+
netdev_txq = netdev_get_tx_queue(netdev, q->index);
33+
34+
HARD_TX_LOCK(netdev, netdev_txq, smp_processor_id());
35+
36+
if (q->tail_idx == q->head_idx) {
37+
HARD_TX_UNLOCK(netdev, netdev_txq);
38+
return false;
39+
}
40+
41+
now = READ_ONCE(jiffies);
42+
then = q->dbell_jiffies;
43+
dif = now - then;
44+
45+
if (dif > q->dbell_deadline) {
46+
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
47+
q->dbval | q->head_idx);
48+
49+
q->dbell_jiffies = now;
50+
}
51+
52+
HARD_TX_UNLOCK(netdev, netdev_txq);
53+
54+
return true;
55+
}
56+
57+
bool ionic_rxq_poke_doorbell(struct ionic_queue *q)
58+
{
59+
unsigned long now, then, dif;
60+
61+
/* no lock, called from rx napi or txrx napi, nothing else can fill */
62+
63+
if (q->tail_idx == q->head_idx)
64+
return false;
65+
66+
now = READ_ONCE(jiffies);
67+
then = q->dbell_jiffies;
68+
dif = now - then;
69+
70+
if (dif > q->dbell_deadline) {
71+
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
72+
q->dbval | q->head_idx);
73+
74+
q->dbell_jiffies = now;
75+
76+
dif = 2 * q->dbell_deadline;
77+
if (dif > IONIC_RX_MAX_DOORBELL_DEADLINE)
78+
dif = IONIC_RX_MAX_DOORBELL_DEADLINE;
79+
80+
q->dbell_deadline = dif;
81+
}
82+
83+
return true;
84+
}
85+
2586
static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q)
2687
{
2788
return netdev_get_tx_queue(q->lif->netdev, q->index);
@@ -424,6 +485,12 @@ void ionic_rx_fill(struct ionic_queue *q)
424485

425486
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
426487
q->dbval | q->head_idx);
488+
489+
q->dbell_deadline = IONIC_RX_MIN_DOORBELL_DEADLINE;
490+
q->dbell_jiffies = jiffies;
491+
492+
mod_timer(&q_to_qcq(q)->napi_qcq->napi_deadline,
493+
jiffies + IONIC_NAPI_DEADLINE);
427494
}
428495

429496
void ionic_rx_empty(struct ionic_queue *q)
@@ -511,6 +578,9 @@ int ionic_tx_napi(struct napi_struct *napi, int budget)
511578
work_done, flags);
512579
}
513580

581+
if (!work_done && ionic_txq_poke_doorbell(&qcq->q))
582+
mod_timer(&qcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE);
583+
514584
return work_done;
515585
}
516586

@@ -544,23 +614,29 @@ int ionic_rx_napi(struct napi_struct *napi, int budget)
544614
work_done, flags);
545615
}
546616

617+
if (!work_done && ionic_rxq_poke_doorbell(&qcq->q))
618+
mod_timer(&qcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE);
619+
547620
return work_done;
548621
}
549622

550623
int ionic_txrx_napi(struct napi_struct *napi, int budget)
551624
{
552-
struct ionic_qcq *qcq = napi_to_qcq(napi);
625+
struct ionic_qcq *rxqcq = napi_to_qcq(napi);
553626
struct ionic_cq *rxcq = napi_to_cq(napi);
554627
unsigned int qi = rxcq->bound_q->index;
628+
struct ionic_qcq *txqcq;
555629
struct ionic_dev *idev;
556630
struct ionic_lif *lif;
557631
struct ionic_cq *txcq;
632+
bool resched = false;
558633
u32 rx_work_done = 0;
559634
u32 tx_work_done = 0;
560635
u32 flags = 0;
561636

562637
lif = rxcq->bound_q->lif;
563638
idev = &lif->ionic->idev;
639+
txqcq = lif->txqcqs[qi];
564640
txcq = &lif->txqcqs[qi]->cq;
565641

566642
tx_work_done = ionic_cq_service(txcq, IONIC_TX_BUDGET_DEFAULT,
@@ -572,7 +648,7 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget)
572648
ionic_rx_fill(rxcq->bound_q);
573649

574650
if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) {
575-
ionic_dim_update(qcq, 0);
651+
ionic_dim_update(rxqcq, 0);
576652
flags |= IONIC_INTR_CRED_UNMASK;
577653
rxcq->bound_intr->rearm_count++;
578654
}
@@ -583,6 +659,13 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget)
583659
tx_work_done + rx_work_done, flags);
584660
}
585661

662+
if (!rx_work_done && ionic_rxq_poke_doorbell(&rxqcq->q))
663+
resched = true;
664+
if (!tx_work_done && ionic_txq_poke_doorbell(&txqcq->q))
665+
resched = true;
666+
if (resched)
667+
mod_timer(&rxqcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE);
668+
586669
return rx_work_done;
587670
}
588671

0 commit comments

Comments
 (0)