Skip to content

Commit 871e846

Browse files
ikhorndavem330
authored andcommitted
net: ethernet: ti: davinci_cpdma: use idled submit
While data pass suspend, reuse of rx descriptors can be disabled using channel state & lock from cpdma layer. For this, submit to a channel has to be disabled using state != "not active" under lock, what is done with this patch. The same submit is used to fill rx channel while ndo_open, when channel is idled, so add idled submit routine that allows to prepare descs for the channel. All this simplifies code and helps to avoid dormant mode usage and send packets only to active channels, avoiding potential race in later on changes. Also add missed sync barrier analogically like in other places after stopping tx queues. Signed-off-by: Ivan Khoronzhuk <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4e18a8a commit 871e846

File tree

5 files changed

+77
-41
lines changed

5 files changed

+77
-41
lines changed

drivers/net/ethernet/ti/cpsw.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -457,16 +457,13 @@ static void cpsw_rx_handler(void *token, int len, int status)
457457
}
458458

459459
requeue:
460-
if (netif_dormant(ndev)) {
461-
dev_kfree_skb_any(new_skb);
462-
return;
463-
}
464-
465460
ch = cpsw->rxv[skb_get_queue_mapping(new_skb)].ch;
466461
ret = cpdma_chan_submit(ch, new_skb, new_skb->data,
467462
skb_tailroom(new_skb), 0);
468-
if (WARN_ON(ret < 0))
463+
if (ret < 0) {
464+
WARN_ON(ret == -ENOMEM);
469465
dev_kfree_skb_any(new_skb);
466+
}
470467
}
471468

472469
void cpsw_split_res(struct cpsw_common *cpsw)
@@ -1051,9 +1048,9 @@ int cpsw_fill_rx_channels(struct cpsw_priv *priv)
10511048
}
10521049

10531050
skb_set_queue_mapping(skb, ch);
1054-
ret = cpdma_chan_submit(cpsw->rxv[ch].ch, skb,
1055-
skb->data, skb_tailroom(skb),
1056-
0);
1051+
ret = cpdma_chan_idle_submit(cpsw->rxv[ch].ch, skb,
1052+
skb->data,
1053+
skb_tailroom(skb), 0);
10571054
if (ret < 0) {
10581055
cpsw_err(priv, ifup,
10591056
"cannot submit skb to channel %d rx, error %d\n",

drivers/net/ethernet/ti/cpsw_ethtool.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -464,15 +464,16 @@ static void cpsw_suspend_data_pass(struct net_device *ndev)
464464
cpsw_intr_disable(cpsw);
465465

466466
/* Stop all transmit queues for every network device.
467-
* Disable re-using rx descriptors with dormant_on.
468467
*/
469468
for (i = 0; i < cpsw->data.slaves; i++) {
470469
ndev = cpsw->slaves[i].ndev;
471470
if (!(ndev && netif_running(ndev)))
472471
continue;
473472

474473
netif_tx_stop_all_queues(ndev);
475-
netif_dormant_on(ndev);
474+
475+
/* Barrier, so that stop_queue visible to other cpus */
476+
smp_mb__after_atomic();
476477
}
477478

478479
/* Handle rest of tx packets and stop cpdma channels */
@@ -485,13 +486,6 @@ static int cpsw_resume_data_pass(struct net_device *ndev)
485486
struct cpsw_common *cpsw = priv->cpsw;
486487
int i, ret;
487488

488-
/* Allow rx packets handling */
489-
for (i = 0; i < cpsw->data.slaves; i++) {
490-
ndev = cpsw->slaves[i].ndev;
491-
if (ndev && netif_running(ndev))
492-
netif_dormant_off(ndev);
493-
}
494-
495489
/* After this receive is started */
496490
if (cpsw->usage_count) {
497491
ret = cpsw_fill_rx_channels(priv);

drivers/net/ethernet/ti/davinci_cpdma.c

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ struct cpdma_control_info {
134134
#define ACCESS_RW (ACCESS_RO | ACCESS_WO)
135135
};
136136

137+
struct submit_info {
138+
struct cpdma_chan *chan;
139+
int directed;
140+
void *token;
141+
void *data;
142+
int len;
143+
};
144+
137145
static struct cpdma_control_info controls[] = {
138146
[CPDMA_TX_RLIM] = {CPDMA_DMACONTROL, 8, 0xffff, ACCESS_RW},
139147
[CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO},
@@ -1002,51 +1010,41 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan,
10021010
}
10031011
}
10041012

1005-
int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
1006-
int len, int directed)
1013+
static int cpdma_chan_submit_si(struct submit_info *si)
10071014
{
1015+
struct cpdma_chan *chan = si->chan;
10081016
struct cpdma_ctlr *ctlr = chan->ctlr;
1017+
int len = si->len;
10091018
struct cpdma_desc __iomem *desc;
10101019
dma_addr_t buffer;
1011-
unsigned long flags;
10121020
u32 mode;
1013-
int ret = 0;
1014-
1015-
spin_lock_irqsave(&chan->lock, flags);
1016-
1017-
if (chan->state == CPDMA_STATE_TEARDOWN) {
1018-
ret = -EINVAL;
1019-
goto unlock_ret;
1020-
}
1021+
int ret;
10211022

10221023
if (chan->count >= chan->desc_num) {
10231024
chan->stats.desc_alloc_fail++;
1024-
ret = -ENOMEM;
1025-
goto unlock_ret;
1025+
return -ENOMEM;
10261026
}
10271027

10281028
desc = cpdma_desc_alloc(ctlr->pool);
10291029
if (!desc) {
10301030
chan->stats.desc_alloc_fail++;
1031-
ret = -ENOMEM;
1032-
goto unlock_ret;
1031+
return -ENOMEM;
10331032
}
10341033

10351034
if (len < ctlr->params.min_packet_size) {
10361035
len = ctlr->params.min_packet_size;
10371036
chan->stats.runt_transmit_buff++;
10381037
}
10391038

1040-
buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
1039+
buffer = dma_map_single(ctlr->dev, si->data, len, chan->dir);
10411040
ret = dma_mapping_error(ctlr->dev, buffer);
10421041
if (ret) {
10431042
cpdma_desc_free(ctlr->pool, desc, 1);
1044-
ret = -EINVAL;
1045-
goto unlock_ret;
1043+
return -EINVAL;
10461044
}
10471045

10481046
mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
1049-
cpdma_desc_to_port(chan, mode, directed);
1047+
cpdma_desc_to_port(chan, mode, si->directed);
10501048

10511049
/* Relaxed IO accessors can be used here as there is read barrier
10521050
* at the end of write sequence.
@@ -1055,7 +1053,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
10551053
writel_relaxed(buffer, &desc->hw_buffer);
10561054
writel_relaxed(len, &desc->hw_len);
10571055
writel_relaxed(mode | len, &desc->hw_mode);
1058-
writel_relaxed((uintptr_t)token, &desc->sw_token);
1056+
writel_relaxed((uintptr_t)si->token, &desc->sw_token);
10591057
writel_relaxed(buffer, &desc->sw_buffer);
10601058
writel_relaxed(len, &desc->sw_len);
10611059
desc_read(desc, sw_len);
@@ -1066,8 +1064,53 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
10661064
chan_write(chan, rxfree, 1);
10671065

10681066
chan->count++;
1067+
return 0;
1068+
}
10691069

1070-
unlock_ret:
1070+
int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,
1071+
int len, int directed)
1072+
{
1073+
struct submit_info si;
1074+
unsigned long flags;
1075+
int ret;
1076+
1077+
si.chan = chan;
1078+
si.token = token;
1079+
si.data = data;
1080+
si.len = len;
1081+
si.directed = directed;
1082+
1083+
spin_lock_irqsave(&chan->lock, flags);
1084+
if (chan->state == CPDMA_STATE_TEARDOWN) {
1085+
spin_unlock_irqrestore(&chan->lock, flags);
1086+
return -EINVAL;
1087+
}
1088+
1089+
ret = cpdma_chan_submit_si(&si);
1090+
spin_unlock_irqrestore(&chan->lock, flags);
1091+
return ret;
1092+
}
1093+
1094+
int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
1095+
int len, int directed)
1096+
{
1097+
struct submit_info si;
1098+
unsigned long flags;
1099+
int ret;
1100+
1101+
si.chan = chan;
1102+
si.token = token;
1103+
si.data = data;
1104+
si.len = len;
1105+
si.directed = directed;
1106+
1107+
spin_lock_irqsave(&chan->lock, flags);
1108+
if (chan->state != CPDMA_STATE_ACTIVE) {
1109+
spin_unlock_irqrestore(&chan->lock, flags);
1110+
return -EINVAL;
1111+
}
1112+
1113+
ret = cpdma_chan_submit_si(&si);
10711114
spin_unlock_irqrestore(&chan->lock, flags);
10721115
return ret;
10731116
}

drivers/net/ethernet/ti/davinci_cpdma.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ int cpdma_chan_get_stats(struct cpdma_chan *chan,
7979
struct cpdma_chan_stats *stats);
8080
int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
8181
int len, int directed);
82+
int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,
83+
int len, int directed);
8284
int cpdma_chan_process(struct cpdma_chan *chan, int quota);
8385

8486
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);

drivers/net/ethernet/ti/davinci_emac.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,8 +1428,8 @@ static int emac_dev_open(struct net_device *ndev)
14281428
if (!skb)
14291429
break;
14301430

1431-
ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
1432-
skb_tailroom(skb), 0);
1431+
ret = cpdma_chan_idle_submit(priv->rxchan, skb, skb->data,
1432+
skb_tailroom(skb), 0);
14331433
if (WARN_ON(ret < 0))
14341434
break;
14351435
}

0 commit comments

Comments
 (0)