Skip to content

Commit 0d72c2a

Browse files
Denis Bolotindavem330
authored andcommitted
qed: Fix the DORQ's attentions handling
Separate the overflow handling from the hardware interrupt status analysis. The interrupt status is a single register and is common for all PFs. The first PF reading the register is not necessarily the one who overflowed. All PFs must check their overflow status on every attention. In this change we clear the sticky indication in the attention handler to allow doorbells to be processed again as soon as possible, but running the doorbell recovery is scheduled for the periodic handler to reduce the time spent in the attention handler. Checking the need for DORQ flush was changed to "db_bar_no_edpm" because qed_edpm_enabled()'s result could change dynamically and might have prevented a needed flush. Signed-off-by: Denis Bolotin <[email protected]> Signed-off-by: Michal Kalderon <[email protected]> Signed-off-by: Ariel Elior <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d4476b8 commit 0d72c2a

File tree

2 files changed

+48
-16
lines changed

2 files changed

+48
-16
lines changed

drivers/net/ethernet/qlogic/qed/qed.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,13 +431,16 @@ struct qed_qm_info {
431431
u8 num_pf_rls;
432432
};
433433

434+
#define QED_OVERFLOW_BIT 1
435+
434436
struct qed_db_recovery_info {
435437
struct list_head list;
436438

437439
/* Lock to protect the doorbell recovery mechanism list */
438440
spinlock_t lock;
439441
bool dorq_attn;
440442
u32 db_recovery_counter;
443+
unsigned long overflow;
441444
};
442445

443446
struct storm_stats {

drivers/net/ethernet/qlogic/qed/qed_int.c

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,9 @@ static int qed_db_rec_flush_queue(struct qed_hwfn *p_hwfn,
378378
u32 count = QED_DB_REC_COUNT;
379379
u32 usage = 1;
380380

381+
/* Flush any pending (e)dpms as they may never arrive */
382+
qed_wr(p_hwfn, p_ptt, DORQ_REG_DPM_FORCE_ABORT, 0x1);
383+
381384
/* wait for usage to zero or count to run out. This is necessary since
382385
* EDPM doorbell transactions can take multiple 64b cycles, and as such
383386
* can "split" over the pci. Possibly, the doorbell drop can happen with
@@ -406,23 +409,24 @@ static int qed_db_rec_flush_queue(struct qed_hwfn *p_hwfn,
406409

407410
int qed_db_rec_handler(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
408411
{
409-
u32 overflow;
412+
u32 attn_ovfl, cur_ovfl;
410413
int rc;
411414

412-
overflow = qed_rd(p_hwfn, p_ptt, DORQ_REG_PF_OVFL_STICKY);
413-
DP_NOTICE(p_hwfn, "PF Overflow sticky 0x%x\n", overflow);
414-
if (!overflow)
415+
attn_ovfl = test_and_clear_bit(QED_OVERFLOW_BIT,
416+
&p_hwfn->db_recovery_info.overflow);
417+
cur_ovfl = qed_rd(p_hwfn, p_ptt, DORQ_REG_PF_OVFL_STICKY);
418+
if (!cur_ovfl && !attn_ovfl)
415419
return 0;
416420

417-
if (qed_edpm_enabled(p_hwfn)) {
421+
DP_NOTICE(p_hwfn, "PF Overflow sticky: attn %u current %u\n",
422+
attn_ovfl, cur_ovfl);
423+
424+
if (cur_ovfl && !p_hwfn->db_bar_no_edpm) {
418425
rc = qed_db_rec_flush_queue(p_hwfn, p_ptt);
419426
if (rc)
420427
return rc;
421428
}
422429

423-
/* Flush any pending (e)dpm as they may never arrive */
424-
qed_wr(p_hwfn, p_ptt, DORQ_REG_DPM_FORCE_ABORT, 0x1);
425-
426430
/* Release overflow sticky indication (stop silently dropping everything) */
427431
qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_OVFL_STICKY, 0x0);
428432

@@ -432,13 +436,35 @@ int qed_db_rec_handler(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
432436
return 0;
433437
}
434438

435-
static int qed_dorq_attn_cb(struct qed_hwfn *p_hwfn)
439+
static void qed_dorq_attn_overflow(struct qed_hwfn *p_hwfn)
436440
{
437-
u32 int_sts, first_drop_reason, details, address, all_drops_reason;
438441
struct qed_ptt *p_ptt = p_hwfn->p_dpc_ptt;
442+
u32 overflow;
439443
int rc;
440444

441-
p_hwfn->db_recovery_info.dorq_attn = true;
445+
overflow = qed_rd(p_hwfn, p_ptt, DORQ_REG_PF_OVFL_STICKY);
446+
if (!overflow)
447+
goto out;
448+
449+
/* Run PF doorbell recovery in next periodic handler */
450+
set_bit(QED_OVERFLOW_BIT, &p_hwfn->db_recovery_info.overflow);
451+
452+
if (!p_hwfn->db_bar_no_edpm) {
453+
rc = qed_db_rec_flush_queue(p_hwfn, p_ptt);
454+
if (rc)
455+
goto out;
456+
}
457+
458+
qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_OVFL_STICKY, 0x0);
459+
out:
460+
/* Schedule the handler even if overflow was not detected */
461+
qed_periodic_db_rec_start(p_hwfn);
462+
}
463+
464+
static int qed_dorq_attn_int_sts(struct qed_hwfn *p_hwfn)
465+
{
466+
u32 int_sts, first_drop_reason, details, address, all_drops_reason;
467+
struct qed_ptt *p_ptt = p_hwfn->p_dpc_ptt;
442468

443469
/* int_sts may be zero since all PFs were interrupted for doorbell
444470
* overflow but another one already handled it. Can abort here. If
@@ -477,11 +503,6 @@ static int qed_dorq_attn_cb(struct qed_hwfn *p_hwfn)
477503
GET_FIELD(details, QED_DORQ_ATTENTION_SIZE) * 4,
478504
first_drop_reason, all_drops_reason);
479505

480-
rc = qed_db_rec_handler(p_hwfn, p_ptt);
481-
qed_periodic_db_rec_start(p_hwfn);
482-
if (rc)
483-
return rc;
484-
485506
/* Clear the doorbell drop details and prepare for next drop */
486507
qed_wr(p_hwfn, p_ptt, DORQ_REG_DB_DROP_DETAILS_REL, 0);
487508

@@ -507,6 +528,14 @@ static int qed_dorq_attn_cb(struct qed_hwfn *p_hwfn)
507528
return -EINVAL;
508529
}
509530

531+
static int qed_dorq_attn_cb(struct qed_hwfn *p_hwfn)
532+
{
533+
p_hwfn->db_recovery_info.dorq_attn = true;
534+
qed_dorq_attn_overflow(p_hwfn);
535+
536+
return qed_dorq_attn_int_sts(p_hwfn);
537+
}
538+
510539
static void qed_dorq_attn_handler(struct qed_hwfn *p_hwfn)
511540
{
512541
if (p_hwfn->db_recovery_info.dorq_attn)

0 commit comments

Comments
 (0)