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>
This commit is contained in:
Santosh Rastapur 2013-03-14 05:08:52 +00:00 committed by David S. Miller
parent 22adfe0a85
commit 2cc301d20f

View 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)