cxgb4: Enable doorbell drop recovery only for T4 adapter
authorSantosh Rastapur <santosh@chelsio.com>
Thu, 14 Mar 2013 05:08:52 +0000 (05:08 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 14 Mar 2013 15:35:54 +0000 (11:35 -0400)
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>
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c

index ce1451cb5a26e8fb7987ef4ec28fc15e12b25670..177d0c199e015d0b7ebbd1786e2cfb3fadb18d4e 100644 (file)
@@ -3227,10 +3227,18 @@ EXPORT_SYMBOL(cxgb4_port_chan);
 unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
 {
        struct adapter *adap = netdev2adap(dev);
-       u32 v;
+       u32 v1, v2, lp_count, hp_count;
 
-       v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
-       return lpfifo ? G_LP_COUNT(v) : G_HP_COUNT(v);
+       v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+       v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
+       if (is_t4(adap->chip)) {
+               lp_count = G_LP_COUNT(v1);
+               hp_count = G_HP_COUNT(v1);
+       } else {
+               lp_count = G_LP_COUNT_T5(v1);
+               hp_count = G_HP_COUNT_T5(v2);
+       }
+       return lpfifo ? lp_count : hp_count;
 }
 EXPORT_SYMBOL(cxgb4_dbfifo_count);
 
@@ -3368,14 +3376,23 @@ static struct notifier_block cxgb4_netevent_nb = {
 
 static void drain_db_fifo(struct adapter *adap, int usecs)
 {
-       u32 v;
+       u32 v1, v2, lp_count, hp_count;
 
        do {
+               v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+               v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
+               if (is_t4(adap->chip)) {
+                       lp_count = G_LP_COUNT(v1);
+                       hp_count = G_HP_COUNT(v1);
+               } else {
+                       lp_count = G_LP_COUNT_T5(v1);
+                       hp_count = G_HP_COUNT_T5(v2);
+               }
+
+               if (lp_count == 0 && hp_count == 0)
+                       break;
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(usecs_to_jiffies(usecs));
-               v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
-               if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0)
-                       break;
        } while (1);
 }
 
@@ -3484,24 +3501,62 @@ static void process_db_drop(struct work_struct *work)
 
        adap = container_of(work, struct adapter, db_drop_task);
 
+       if (is_t4(adap->chip)) {
+               disable_dbs(adap);
+               notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
+               drain_db_fifo(adap, 1);
+               recover_all_queues(adap);
+               enable_dbs(adap);
+       } else {
+               u32 dropped_db = t4_read_reg(adap, 0x010ac);
+               u16 qid = (dropped_db >> 15) & 0x1ffff;
+               u16 pidx_inc = dropped_db & 0x1fff;
+               unsigned int s_qpp;
+               unsigned short udb_density;
+               unsigned long qpshift;
+               int page;
+               u32 udb;
+
+               dev_warn(adap->pdev_dev,
+                        "Dropped DB 0x%x qid %d bar2 %d coalesce %d pidx %d\n",
+                        dropped_db, qid,
+                        (dropped_db >> 14) & 1,
+                        (dropped_db >> 13) & 1,
+                        pidx_inc);
+
+               drain_db_fifo(adap, 1);
+
+               s_qpp = QUEUESPERPAGEPF1 * adap->fn;
+               udb_density = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adap,
+                               SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp);
+               qpshift = PAGE_SHIFT - ilog2(udb_density);
+               udb = qid << qpshift;
+               udb &= PAGE_MASK;
+               page = udb / PAGE_SIZE;
+               udb += (qid - (page * udb_density)) * 128;
+
+               writel(PIDX(pidx_inc),  adap->bar2 + udb + 8);
+
+               /* Re-enable BAR2 WC */
+               t4_set_reg_field(adap, 0x10b0, 1<<15, 1<<15);
+       }
+
        t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_DROPPED_DB, 0);
-       disable_dbs(adap);
-       notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
-       drain_db_fifo(adap, 1);
-       recover_all_queues(adap);
-       enable_dbs(adap);
 }
 
 void t4_db_full(struct adapter *adap)
 {
-       t4_set_reg_field(adap, SGE_INT_ENABLE3,
-                        DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
-       queue_work(workq, &adap->db_full_task);
+       if (is_t4(adap->chip)) {
+               t4_set_reg_field(adap, SGE_INT_ENABLE3,
+                                DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
+               queue_work(workq, &adap->db_full_task);
+       }
 }
 
 void t4_db_dropped(struct adapter *adap)
 {
-       queue_work(workq, &adap->db_drop_task);
+       if (is_t4(adap->chip))
+               queue_work(workq, &adap->db_drop_task);
 }
 
 static void uld_attach(struct adapter *adap, unsigned int uld)