Skip to content

Commit 3802dce

Browse files
ikhorndavem330
authored andcommitted
net: ethernet: ti: davinci_cpdma: split descs num between all channels
Tx channels share same pool of descriptors. Thus one channel can block another if pool is emptied by one. But, the shaper should decide which channel is allowed to send packets. To avoid such impact of one channel on another, let every channel to have its own piece of pool. Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org> Reviewed-by: Mugunthan V N <mugunthanvnm@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent a01512d commit 3802dce

File tree

3 files changed

+83
-27
lines changed

3 files changed

+83
-27
lines changed

drivers/net/ethernet/ti/cpsw.c

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,40 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
12131213
}
12141214
}
12151215

1216+
static int cpsw_fill_rx_channels(struct cpsw_priv *priv)
1217+
{
1218+
struct cpsw_common *cpsw = priv->cpsw;
1219+
struct sk_buff *skb;
1220+
int ch_buf_num;
1221+
int i, ret;
1222+
1223+
ch_buf_num = cpdma_chan_get_rx_buf_num(cpsw->rxch);
1224+
for (i = 0; i < ch_buf_num; i++) {
1225+
skb = __netdev_alloc_skb_ip_align(priv->ndev,
1226+
cpsw->rx_packet_max,
1227+
GFP_KERNEL);
1228+
if (!skb) {
1229+
cpsw_err(priv, ifup, "cannot allocate skb\n");
1230+
return -ENOMEM;
1231+
}
1232+
1233+
ret = cpdma_chan_submit(cpsw->rxch, skb, skb->data,
1234+
skb_tailroom(skb), 0);
1235+
if (ret < 0) {
1236+
cpsw_err(priv, ifup,
1237+
"cannot submit skb to rx channel, error %d\n",
1238+
ret);
1239+
kfree_skb(skb);
1240+
return ret;
1241+
}
1242+
kmemleak_not_leak(skb);
1243+
}
1244+
1245+
cpsw_info(priv, ifup, "submitted %d rx descriptors\n", ch_buf_num);
1246+
1247+
return ch_buf_num;
1248+
}
1249+
12161250
static void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_common *cpsw)
12171251
{
12181252
u32 slave_port;
@@ -1233,7 +1267,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
12331267
{
12341268
struct cpsw_priv *priv = netdev_priv(ndev);
12351269
struct cpsw_common *cpsw = priv->cpsw;
1236-
int i, ret;
1270+
int ret;
12371271
u32 reg;
12381272

12391273
ret = pm_runtime_get_sync(cpsw->dev);
@@ -1265,8 +1299,6 @@ static int cpsw_ndo_open(struct net_device *ndev)
12651299
ALE_ALL_PORTS, ALE_ALL_PORTS, 0, 0);
12661300

12671301
if (!cpsw_common_res_usage_state(cpsw)) {
1268-
int buf_num;
1269-
12701302
/* setup tx dma to fixed prio and zero offset */
12711303
cpdma_control_set(cpsw->dma, CPDMA_TX_PRIO_FIXED, 1);
12721304
cpdma_control_set(cpsw->dma, CPDMA_RX_BUFFER_OFFSET, 0);
@@ -1293,27 +1325,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
12931325
enable_irq(cpsw->irqs_table[0]);
12941326
}
12951327

1296-
buf_num = cpdma_chan_get_rx_buf_num(cpsw->dma);
1297-
for (i = 0; i < buf_num; i++) {
1298-
struct sk_buff *skb;
1299-
1300-
ret = -ENOMEM;
1301-
skb = __netdev_alloc_skb_ip_align(priv->ndev,
1302-
cpsw->rx_packet_max, GFP_KERNEL);
1303-
if (!skb)
1304-
goto err_cleanup;
1305-
ret = cpdma_chan_submit(cpsw->rxch, skb, skb->data,
1306-
skb_tailroom(skb), 0);
1307-
if (ret < 0) {
1308-
kfree_skb(skb);
1309-
goto err_cleanup;
1310-
}
1311-
kmemleak_not_leak(skb);
1312-
}
1313-
/* continue even if we didn't manage to submit all
1314-
* receive descs
1315-
*/
1316-
cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
1328+
ret = cpsw_fill_rx_channels(priv);
1329+
if (ret < 0)
1330+
goto err_cleanup;
13171331

13181332
if (cpts_register(cpsw->dev, cpsw->cpts,
13191333
cpsw->data.cpts_clock_mult,

drivers/net/ethernet/ti/davinci_cpdma.c

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ struct cpdma_ctlr {
104104
struct cpdma_desc_pool *pool;
105105
spinlock_t lock;
106106
struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS];
107+
int chan_num;
107108
};
108109

109110
struct cpdma_chan {
@@ -256,6 +257,7 @@ struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
256257
ctlr->state = CPDMA_STATE_IDLE;
257258
ctlr->params = *params;
258259
ctlr->dev = params->dev;
260+
ctlr->chan_num = 0;
259261
spin_lock_init(&ctlr->lock);
260262

261263
ctlr->pool = cpdma_desc_pool_create(ctlr->dev,
@@ -399,6 +401,31 @@ void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value)
399401
}
400402
EXPORT_SYMBOL_GPL(cpdma_ctlr_eoi);
401403

404+
/**
405+
* cpdma_chan_split_pool - Splits ctrl pool between all channels.
406+
* Has to be called under ctlr lock
407+
*/
408+
static void cpdma_chan_split_pool(struct cpdma_ctlr *ctlr)
409+
{
410+
struct cpdma_desc_pool *pool = ctlr->pool;
411+
struct cpdma_chan *chan;
412+
int ch_desc_num;
413+
int i;
414+
415+
if (!ctlr->chan_num)
416+
return;
417+
418+
/* calculate average size of pool slice */
419+
ch_desc_num = pool->num_desc / ctlr->chan_num;
420+
421+
/* split ctlr pool */
422+
for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
423+
chan = ctlr->channels[i];
424+
if (chan)
425+
chan->desc_num = ch_desc_num;
426+
}
427+
}
428+
402429
struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
403430
cpdma_handler_fn handler)
404431
{
@@ -447,14 +474,25 @@ struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
447474
spin_lock_init(&chan->lock);
448475

449476
ctlr->channels[chan_num] = chan;
477+
ctlr->chan_num++;
478+
479+
cpdma_chan_split_pool(ctlr);
480+
450481
spin_unlock_irqrestore(&ctlr->lock, flags);
451482
return chan;
452483
}
453484
EXPORT_SYMBOL_GPL(cpdma_chan_create);
454485

455-
int cpdma_chan_get_rx_buf_num(struct cpdma_ctlr *ctlr)
486+
int cpdma_chan_get_rx_buf_num(struct cpdma_chan *chan)
456487
{
457-
return ctlr->pool->num_desc / 2;
488+
unsigned long flags;
489+
int desc_num;
490+
491+
spin_lock_irqsave(&chan->lock, flags);
492+
desc_num = chan->desc_num;
493+
spin_unlock_irqrestore(&chan->lock, flags);
494+
495+
return desc_num;
458496
}
459497
EXPORT_SYMBOL_GPL(cpdma_chan_get_rx_buf_num);
460498

@@ -471,6 +509,10 @@ int cpdma_chan_destroy(struct cpdma_chan *chan)
471509
if (chan->state != CPDMA_STATE_IDLE)
472510
cpdma_chan_stop(chan);
473511
ctlr->channels[chan->chan_num] = NULL;
512+
ctlr->chan_num--;
513+
514+
cpdma_chan_split_pool(ctlr);
515+
474516
spin_unlock_irqrestore(&ctlr->lock, flags);
475517
return 0;
476518
}

drivers/net/ethernet/ti/davinci_cpdma.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr);
8080

8181
struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
8282
cpdma_handler_fn handler);
83-
int cpdma_chan_get_rx_buf_num(struct cpdma_ctlr *ctlr);
83+
int cpdma_chan_get_rx_buf_num(struct cpdma_chan *chan);
8484
int cpdma_chan_destroy(struct cpdma_chan *chan);
8585
int cpdma_chan_start(struct cpdma_chan *chan);
8686
int cpdma_chan_stop(struct cpdma_chan *chan);

0 commit comments

Comments
 (0)