aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVipul Pandya <vipul@chelsio.com>2012-05-18 05:59:24 -0400
committerRoland Dreier <roland@purestorage.com>2012-05-18 16:22:25 -0400
commit881806bc155c0d5d78196c8bfae0ea2e76ae7386 (patch)
tree20ac25b6859424a3bed1c4d64664d9264a013056
parent14b9222808bb8bfefc71f72bc0dbdcf3b2f0140f (diff)
cxgb4: Detect DB FULL events and notify RDMA ULD
Signed-off-by: Vipul Pandya <vipul@chelsio.com> Signed-off-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c77
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h7
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c6
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c9
5 files changed, 103 insertions, 0 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 0fe18850c838..f91b259f19be 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -504,6 +504,8 @@ struct adapter {
504 void **tid_release_head; 504 void **tid_release_head;
505 spinlock_t tid_release_lock; 505 spinlock_t tid_release_lock;
506 struct work_struct tid_release_task; 506 struct work_struct tid_release_task;
507 struct work_struct db_full_task;
508 struct work_struct db_drop_task;
507 bool tid_release_task_busy; 509 bool tid_release_task_busy;
508 510
509 struct dentry *debugfs_root; 511 struct dentry *debugfs_root;
@@ -719,4 +721,6 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
719int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, 721int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
720 unsigned int vf, unsigned int eqid); 722 unsigned int vf, unsigned int eqid);
721int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); 723int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
724void t4_db_full(struct adapter *adapter);
725void t4_db_dropped(struct adapter *adapter);
722#endif /* __CXGB4_H__ */ 726#endif /* __CXGB4_H__ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index b126b98065a9..c243f932099e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2366,6 +2366,16 @@ unsigned int cxgb4_port_chan(const struct net_device *dev)
2366} 2366}
2367EXPORT_SYMBOL(cxgb4_port_chan); 2367EXPORT_SYMBOL(cxgb4_port_chan);
2368 2368
2369unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
2370{
2371 struct adapter *adap = netdev2adap(dev);
2372 u32 v;
2373
2374 v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
2375 return lpfifo ? G_LP_COUNT(v) : G_HP_COUNT(v);
2376}
2377EXPORT_SYMBOL(cxgb4_dbfifo_count);
2378
2369/** 2379/**
2370 * cxgb4_port_viid - get the VI id of a port 2380 * cxgb4_port_viid - get the VI id of a port
2371 * @dev: the net device for the port 2381 * @dev: the net device for the port
@@ -2446,6 +2456,69 @@ static struct notifier_block cxgb4_netevent_nb = {
2446 .notifier_call = netevent_cb 2456 .notifier_call = netevent_cb
2447}; 2457};
2448 2458
2459static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd)
2460{
2461 mutex_lock(&uld_mutex);
2462 if (adap->uld_handle[CXGB4_ULD_RDMA])
2463 ulds[CXGB4_ULD_RDMA].control(adap->uld_handle[CXGB4_ULD_RDMA],
2464 cmd);
2465 mutex_unlock(&uld_mutex);
2466}
2467
2468static void process_db_full(struct work_struct *work)
2469{
2470 struct adapter *adap;
2471 static int delay = 1000;
2472 u32 v;
2473
2474 adap = container_of(work, struct adapter, db_full_task);
2475
2476
2477 /* stop LLD queues */
2478
2479 notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL);
2480 do {
2481 set_current_state(TASK_UNINTERRUPTIBLE);
2482 schedule_timeout(usecs_to_jiffies(delay));
2483 v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
2484 if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0)
2485 break;
2486 } while (1);
2487 notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY);
2488
2489
2490 /*
2491 * The more we get db full interrupts, the more we'll delay
2492 * in re-enabling db rings on queues, capped off at 200ms.
2493 */
2494 delay = min(delay << 1, 200000);
2495
2496 /* resume LLD queues */
2497}
2498
2499static void process_db_drop(struct work_struct *work)
2500{
2501 struct adapter *adap;
2502 adap = container_of(work, struct adapter, db_drop_task);
2503
2504
2505 /*
2506 * sync the PIDX values in HW and SW for LLD queues.
2507 */
2508
2509 notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
2510}
2511
2512void t4_db_full(struct adapter *adap)
2513{
2514 schedule_work(&adap->db_full_task);
2515}
2516
2517void t4_db_dropped(struct adapter *adap)
2518{
2519 schedule_work(&adap->db_drop_task);
2520}
2521
2449static void uld_attach(struct adapter *adap, unsigned int uld) 2522static void uld_attach(struct adapter *adap, unsigned int uld)
2450{ 2523{
2451 void *handle; 2524 void *handle;
@@ -2649,6 +2722,8 @@ static void cxgb_down(struct adapter *adapter)
2649{ 2722{
2650 t4_intr_disable(adapter); 2723 t4_intr_disable(adapter);
2651 cancel_work_sync(&adapter->tid_release_task); 2724 cancel_work_sync(&adapter->tid_release_task);
2725 cancel_work_sync(&adapter->db_full_task);
2726 cancel_work_sync(&adapter->db_drop_task);
2652 adapter->tid_release_task_busy = false; 2727 adapter->tid_release_task_busy = false;
2653 adapter->tid_release_head = NULL; 2728 adapter->tid_release_head = NULL;
2654 2729
@@ -3601,6 +3676,8 @@ static int __devinit init_one(struct pci_dev *pdev,
3601 spin_lock_init(&adapter->tid_release_lock); 3676 spin_lock_init(&adapter->tid_release_lock);
3602 3677
3603 INIT_WORK(&adapter->tid_release_task, process_tid_release_list); 3678 INIT_WORK(&adapter->tid_release_task, process_tid_release_list);
3679 INIT_WORK(&adapter->db_full_task, process_db_full);
3680 INIT_WORK(&adapter->db_drop_task, process_db_drop);
3604 3681
3605 err = t4_prep_adapter(adapter); 3682 err = t4_prep_adapter(adapter);
3606 if (err) 3683 if (err)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index b1d39b8d141a..5cc2f27d60c7 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -163,6 +163,12 @@ enum cxgb4_state {
163 CXGB4_STATE_DETACH 163 CXGB4_STATE_DETACH
164}; 164};
165 165
166enum cxgb4_control {
167 CXGB4_CONTROL_DB_FULL,
168 CXGB4_CONTROL_DB_EMPTY,
169 CXGB4_CONTROL_DB_DROP,
170};
171
166struct pci_dev; 172struct pci_dev;
167struct l2t_data; 173struct l2t_data;
168struct net_device; 174struct net_device;
@@ -225,6 +231,7 @@ struct cxgb4_uld_info {
225int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p); 231int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
226int cxgb4_unregister_uld(enum cxgb4_uld type); 232int cxgb4_unregister_uld(enum cxgb4_uld type);
227int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb); 233int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb);
234unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo);
228unsigned int cxgb4_port_chan(const struct net_device *dev); 235unsigned int cxgb4_port_chan(const struct net_device *dev);
229unsigned int cxgb4_port_viid(const struct net_device *dev); 236unsigned int cxgb4_port_viid(const struct net_device *dev);
230unsigned int cxgb4_port_idx(const struct net_device *dev); 237unsigned int cxgb4_port_idx(const struct net_device *dev);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 2dae7959f000..234c157a4879 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -2415,6 +2415,12 @@ void t4_sge_init(struct adapter *adap)
2415 RXPKTCPLMODE | 2415 RXPKTCPLMODE |
2416 (STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0)); 2416 (STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0));
2417 2417
2418 t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
2419 V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5),
2420 V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5));
2421 t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_ENABLE_DROP,
2422 F_ENABLE_DROP);
2423
2418 for (i = v = 0; i < 32; i += 4) 2424 for (i = v = 0; i < 32; i += 4)
2419 v |= (PAGE_SHIFT - 10) << i; 2425 v |= (PAGE_SHIFT - 10) << i;
2420 t4_write_reg(adap, SGE_HOST_PAGE_SIZE, v); 2426 t4_write_reg(adap, SGE_HOST_PAGE_SIZE, v);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index d1ec111aebd8..13609bf056b0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -1013,6 +1013,8 @@ static void sge_intr_handler(struct adapter *adapter)
1013 { ERR_INVALID_CIDX_INC, 1013 { ERR_INVALID_CIDX_INC,
1014 "SGE GTS CIDX increment too large", -1, 0 }, 1014 "SGE GTS CIDX increment too large", -1, 0 },
1015 { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 }, 1015 { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
1016 { F_DBFIFO_LP_INT, NULL, -1, 0 },
1017 { F_DBFIFO_HP_INT, NULL, -1, 0 },
1016 { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 }, 1018 { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
1017 { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0, 1019 { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
1018 "SGE IQID > 1023 received CPL for FL", -1, 0 }, 1020 "SGE IQID > 1023 received CPL for FL", -1, 0 },
@@ -1042,6 +1044,12 @@ static void sge_intr_handler(struct adapter *adapter)
1042 t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32); 1044 t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32);
1043 } 1045 }
1044 1046
1047 err = t4_read_reg(adapter, A_SGE_INT_CAUSE3);
1048 if (err & (F_DBFIFO_HP_INT|F_DBFIFO_LP_INT))
1049 t4_db_full(adapter);
1050 if (err & F_ERR_DROPPED_DB)
1051 t4_db_dropped(adapter);
1052
1045 if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) || 1053 if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) ||
1046 v != 0) 1054 v != 0)
1047 t4_fatal_err(adapter); 1055 t4_fatal_err(adapter);
@@ -1513,6 +1521,7 @@ void t4_intr_enable(struct adapter *adapter)
1513 ERR_BAD_DB_PIDX2 | ERR_BAD_DB_PIDX1 | 1521 ERR_BAD_DB_PIDX2 | ERR_BAD_DB_PIDX1 |
1514 ERR_BAD_DB_PIDX0 | ERR_ING_CTXT_PRIO | 1522 ERR_BAD_DB_PIDX0 | ERR_ING_CTXT_PRIO |
1515 ERR_EGR_CTXT_PRIO | INGRESS_SIZE_ERR | 1523 ERR_EGR_CTXT_PRIO | INGRESS_SIZE_ERR |
1524 F_DBFIFO_HP_INT | F_DBFIFO_LP_INT |
1516 EGRESS_SIZE_ERR); 1525 EGRESS_SIZE_ERR);
1517 t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE), PF_INTR_MASK); 1526 t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE), PF_INTR_MASK);
1518 t4_set_reg_field(adapter, PL_INT_MAP0, 0, 1 << pf); 1527 t4_set_reg_field(adapter, PL_INT_MAP0, 0, 1 << pf);