Skip to content

Commit 5e0b892

Browse files
ihuguetdavem330
authored andcommitted
net:cxgb3: replace tasklets with works
OFLD and CTRL TX queues can be stopped if there is no room in their DMA rings. If this happens, they're tried to be restarted later after having made some room in the corresponding ring. The tasks of restarting these queues were triggered using tasklets, but they can be replaced for workqueue works, getting them out of softirq context. This queues stop/restart probably doesn't happen often and they can be quite lengthy because they try to send all pending skbs. Moreover, given that probably the ring is not empty yet, so the DMA still has work to do, we don't need to be so fast to justify using tasklets/softirq instead of running in a thread. Signed-off-by: Íñigo Huguet <ihuguet@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent a29cb69 commit 5e0b892

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

drivers/net/ethernet/chelsio/cxgb3/adapter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ struct sge_txq { /* state for an SGE Tx queue */
178178
unsigned int token; /* WR token */
179179
dma_addr_t phys_addr; /* physical address of the ring */
180180
struct sk_buff_head sendq; /* List of backpressured offload packets */
181-
struct tasklet_struct qresume_tsk; /* restarts the queue */
181+
struct work_struct qresume_task; /* restarts the queue */
182182
unsigned int cntxt_id; /* SGE context id for the Tx q */
183183
unsigned long stops; /* # of times q has been stopped */
184184
unsigned long restarts; /* # of queue restarts */

drivers/net/ethernet/chelsio/cxgb3/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,4 +770,6 @@ int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
770770
int phy_addr, const struct mdio_ops *mdio_ops);
771771
int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter,
772772
int phy_addr, const struct mdio_ops *mdio_ops);
773+
774+
extern struct workqueue_struct *cxgb3_wq;
773775
#endif /* __CHELSIO_COMMON_H */

drivers/net/ethernet/chelsio/cxgb3/sge.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,14 +1518,15 @@ static int ctrl_xmit(struct adapter *adap, struct sge_txq *q,
15181518

15191519
/**
15201520
* restart_ctrlq - restart a suspended control queue
1521-
* @t: pointer to the tasklet associated with this handler
1521+
* @w: pointer to the work associated with this handler
15221522
*
15231523
* Resumes transmission on a suspended Tx control queue.
15241524
*/
1525-
static void restart_ctrlq(struct tasklet_struct *t)
1525+
static void restart_ctrlq(struct work_struct *w)
15261526
{
15271527
struct sk_buff *skb;
1528-
struct sge_qset *qs = from_tasklet(qs, t, txq[TXQ_CTRL].qresume_tsk);
1528+
struct sge_qset *qs = container_of(w, struct sge_qset,
1529+
txq[TXQ_CTRL].qresume_task);
15291530
struct sge_txq *q = &qs->txq[TXQ_CTRL];
15301531

15311532
spin_lock(&q->lock);
@@ -1736,14 +1737,15 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
17361737

17371738
/**
17381739
* restart_offloadq - restart a suspended offload queue
1739-
* @t: pointer to the tasklet associated with this handler
1740+
* @w: pointer to the work associated with this handler
17401741
*
17411742
* Resumes transmission on a suspended Tx offload queue.
17421743
*/
1743-
static void restart_offloadq(struct tasklet_struct *t)
1744+
static void restart_offloadq(struct work_struct *w)
17441745
{
17451746
struct sk_buff *skb;
1746-
struct sge_qset *qs = from_tasklet(qs, t, txq[TXQ_OFLD].qresume_tsk);
1747+
struct sge_qset *qs = container_of(w, struct sge_qset,
1748+
txq[TXQ_OFLD].qresume_task);
17471749
struct sge_txq *q = &qs->txq[TXQ_OFLD];
17481750
const struct port_info *pi = netdev_priv(qs->netdev);
17491751
struct adapter *adap = pi->adapter;
@@ -1998,13 +2000,17 @@ static void restart_tx(struct sge_qset *qs)
19982000
should_restart_tx(&qs->txq[TXQ_OFLD]) &&
19992001
test_and_clear_bit(TXQ_OFLD, &qs->txq_stopped)) {
20002002
qs->txq[TXQ_OFLD].restarts++;
2001-
tasklet_schedule(&qs->txq[TXQ_OFLD].qresume_tsk);
2003+
2004+
/* The work can be quite lengthy so we use driver's own queue */
2005+
queue_work(cxgb3_wq, &qs->txq[TXQ_OFLD].qresume_task);
20022006
}
20032007
if (test_bit(TXQ_CTRL, &qs->txq_stopped) &&
20042008
should_restart_tx(&qs->txq[TXQ_CTRL]) &&
20052009
test_and_clear_bit(TXQ_CTRL, &qs->txq_stopped)) {
20062010
qs->txq[TXQ_CTRL].restarts++;
2007-
tasklet_schedule(&qs->txq[TXQ_CTRL].qresume_tsk);
2011+
2012+
/* The work can be quite lengthy so we use driver's own queue */
2013+
queue_work(cxgb3_wq, &qs->txq[TXQ_CTRL].qresume_task);
20082014
}
20092015
}
20102016

@@ -3085,8 +3091,8 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
30853091
skb_queue_head_init(&q->txq[i].sendq);
30863092
}
30873093

3088-
tasklet_setup(&q->txq[TXQ_OFLD].qresume_tsk, restart_offloadq);
3089-
tasklet_setup(&q->txq[TXQ_CTRL].qresume_tsk, restart_ctrlq);
3094+
INIT_WORK(&q->txq[TXQ_OFLD].qresume_task, restart_offloadq);
3095+
INIT_WORK(&q->txq[TXQ_CTRL].qresume_task, restart_ctrlq);
30903096

30913097
q->fl[0].gen = q->fl[1].gen = 1;
30923098
q->fl[0].size = p->fl_size;
@@ -3276,11 +3282,11 @@ void t3_sge_start(struct adapter *adap)
32763282
*
32773283
* Can be invoked from interrupt context e.g. error handler.
32783284
*
3279-
* Note that this function cannot disable the restart of tasklets as
3285+
* Note that this function cannot disable the restart of works as
32803286
* it cannot wait if called from interrupt context, however the
3281-
* tasklets will have no effect since the doorbells are disabled. The
3287+
* works will have no effect since the doorbells are disabled. The
32823288
* driver will call tg3_sge_stop() later from process context, at
3283-
* which time the tasklets will be stopped if they are still running.
3289+
* which time the works will be stopped if they are still running.
32843290
*/
32853291
void t3_sge_stop_dma(struct adapter *adap)
32863292
{
@@ -3292,7 +3298,7 @@ void t3_sge_stop_dma(struct adapter *adap)
32923298
* @adap: the adapter
32933299
*
32943300
* Called from process context. Disables the DMA engine and any
3295-
* pending queue restart tasklets.
3301+
* pending queue restart works.
32963302
*/
32973303
void t3_sge_stop(struct adapter *adap)
32983304
{
@@ -3303,8 +3309,8 @@ void t3_sge_stop(struct adapter *adap)
33033309
for (i = 0; i < SGE_QSETS; ++i) {
33043310
struct sge_qset *qs = &adap->sge.qs[i];
33053311

3306-
tasklet_kill(&qs->txq[TXQ_OFLD].qresume_tsk);
3307-
tasklet_kill(&qs->txq[TXQ_CTRL].qresume_tsk);
3312+
cancel_work_sync(&qs->txq[TXQ_OFLD].qresume_task);
3313+
cancel_work_sync(&qs->txq[TXQ_OFLD].qresume_task);
33083314
}
33093315
}
33103316

0 commit comments

Comments
 (0)