diff options
author | Santosh Rastapur <santosh@chelsio.com> | 2013-03-14 01:08:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-14 11:35:54 -0400 |
commit | 2cc301d20f80ecf532754aad39e150f488acdcb7 (patch) | |
tree | 79b3644cf36764230bdb0de858058411fb5918da | |
parent | 22adfe0a85ca3808e09e7b4787cb08299d89aeaa (diff) |
cxgb4: Enable doorbell drop recovery only for T4 adapter
Signed-off-by: Santosh Rastapur <santosh@chelsio.com>
Signed-off-by: Vipul Pandya <vipul@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 87 |
1 files changed, 71 insertions, 16 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index ce1451cb5a26..177d0c199e01 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | |||
@@ -3227,10 +3227,18 @@ EXPORT_SYMBOL(cxgb4_port_chan); | |||
3227 | unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo) | 3227 | unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo) |
3228 | { | 3228 | { |
3229 | struct adapter *adap = netdev2adap(dev); | 3229 | struct adapter *adap = netdev2adap(dev); |
3230 | u32 v; | 3230 | u32 v1, v2, lp_count, hp_count; |
3231 | 3231 | ||
3232 | v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); | 3232 | v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); |
3233 | return lpfifo ? G_LP_COUNT(v) : G_HP_COUNT(v); | 3233 | v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2); |
3234 | if (is_t4(adap->chip)) { | ||
3235 | lp_count = G_LP_COUNT(v1); | ||
3236 | hp_count = G_HP_COUNT(v1); | ||
3237 | } else { | ||
3238 | lp_count = G_LP_COUNT_T5(v1); | ||
3239 | hp_count = G_HP_COUNT_T5(v2); | ||
3240 | } | ||
3241 | return lpfifo ? lp_count : hp_count; | ||
3234 | } | 3242 | } |
3235 | EXPORT_SYMBOL(cxgb4_dbfifo_count); | 3243 | EXPORT_SYMBOL(cxgb4_dbfifo_count); |
3236 | 3244 | ||
@@ -3368,14 +3376,23 @@ static struct notifier_block cxgb4_netevent_nb = { | |||
3368 | 3376 | ||
3369 | static void drain_db_fifo(struct adapter *adap, int usecs) | 3377 | static void drain_db_fifo(struct adapter *adap, int usecs) |
3370 | { | 3378 | { |
3371 | u32 v; | 3379 | u32 v1, v2, lp_count, hp_count; |
3372 | 3380 | ||
3373 | do { | 3381 | do { |
3382 | v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); | ||
3383 | v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2); | ||
3384 | if (is_t4(adap->chip)) { | ||
3385 | lp_count = G_LP_COUNT(v1); | ||
3386 | hp_count = G_HP_COUNT(v1); | ||
3387 | } else { | ||
3388 | lp_count = G_LP_COUNT_T5(v1); | ||
3389 | hp_count = G_HP_COUNT_T5(v2); | ||
3390 | } | ||
3391 | |||
3392 | if (lp_count == 0 && hp_count == 0) | ||
3393 | break; | ||
3374 | set_current_state(TASK_UNINTERRUPTIBLE); | 3394 | set_current_state(TASK_UNINTERRUPTIBLE); |
3375 | schedule_timeout(usecs_to_jiffies(usecs)); | 3395 | schedule_timeout(usecs_to_jiffies(usecs)); |
3376 | v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); | ||
3377 | if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0) | ||
3378 | break; | ||
3379 | } while (1); | 3396 | } while (1); |
3380 | } | 3397 | } |
3381 | 3398 | ||
@@ -3484,24 +3501,62 @@ static void process_db_drop(struct work_struct *work) | |||
3484 | 3501 | ||
3485 | adap = container_of(work, struct adapter, db_drop_task); | 3502 | adap = container_of(work, struct adapter, db_drop_task); |
3486 | 3503 | ||
3504 | if (is_t4(adap->chip)) { | ||
3505 | disable_dbs(adap); | ||
3506 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP); | ||
3507 | drain_db_fifo(adap, 1); | ||
3508 | recover_all_queues(adap); | ||
3509 | enable_dbs(adap); | ||
3510 | } else { | ||
3511 | u32 dropped_db = t4_read_reg(adap, 0x010ac); | ||
3512 | u16 qid = (dropped_db >> 15) & 0x1ffff; | ||
3513 | u16 pidx_inc = dropped_db & 0x1fff; | ||
3514 | unsigned int s_qpp; | ||
3515 | unsigned short udb_density; | ||
3516 | unsigned long qpshift; | ||
3517 | int page; | ||
3518 | u32 udb; | ||
3519 | |||
3520 | dev_warn(adap->pdev_dev, | ||
3521 | "Dropped DB 0x%x qid %d bar2 %d coalesce %d pidx %d\n", | ||
3522 | dropped_db, qid, | ||
3523 | (dropped_db >> 14) & 1, | ||
3524 | (dropped_db >> 13) & 1, | ||
3525 | pidx_inc); | ||
3526 | |||
3527 | drain_db_fifo(adap, 1); | ||
3528 | |||
3529 | s_qpp = QUEUESPERPAGEPF1 * adap->fn; | ||
3530 | udb_density = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adap, | ||
3531 | SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp); | ||
3532 | qpshift = PAGE_SHIFT - ilog2(udb_density); | ||
3533 | udb = qid << qpshift; | ||
3534 | udb &= PAGE_MASK; | ||
3535 | page = udb / PAGE_SIZE; | ||
3536 | udb += (qid - (page * udb_density)) * 128; | ||
3537 | |||
3538 | writel(PIDX(pidx_inc), adap->bar2 + udb + 8); | ||
3539 | |||
3540 | /* Re-enable BAR2 WC */ | ||
3541 | t4_set_reg_field(adap, 0x10b0, 1<<15, 1<<15); | ||
3542 | } | ||
3543 | |||
3487 | t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_DROPPED_DB, 0); | 3544 | t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_DROPPED_DB, 0); |
3488 | disable_dbs(adap); | ||
3489 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP); | ||
3490 | drain_db_fifo(adap, 1); | ||
3491 | recover_all_queues(adap); | ||
3492 | enable_dbs(adap); | ||
3493 | } | 3545 | } |
3494 | 3546 | ||
3495 | void t4_db_full(struct adapter *adap) | 3547 | void t4_db_full(struct adapter *adap) |
3496 | { | 3548 | { |
3497 | t4_set_reg_field(adap, SGE_INT_ENABLE3, | 3549 | if (is_t4(adap->chip)) { |
3498 | DBFIFO_HP_INT | DBFIFO_LP_INT, 0); | 3550 | t4_set_reg_field(adap, SGE_INT_ENABLE3, |
3499 | queue_work(workq, &adap->db_full_task); | 3551 | DBFIFO_HP_INT | DBFIFO_LP_INT, 0); |
3552 | queue_work(workq, &adap->db_full_task); | ||
3553 | } | ||
3500 | } | 3554 | } |
3501 | 3555 | ||
3502 | void t4_db_dropped(struct adapter *adap) | 3556 | void t4_db_dropped(struct adapter *adap) |
3503 | { | 3557 | { |
3504 | queue_work(workq, &adap->db_drop_task); | 3558 | if (is_t4(adap->chip)) |
3559 | queue_work(workq, &adap->db_drop_task); | ||
3505 | } | 3560 | } |
3506 | 3561 | ||
3507 | static void uld_attach(struct adapter *adap, unsigned int uld) | 3562 | static void uld_attach(struct adapter *adap, unsigned int uld) |