hc
2024-09-20 a36159eec6ca17402b0e146b86efaf76568dc353
kernel/drivers/net/ethernet/ti/davinci_cpdma.c
....@@ -1,16 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * Texas Instruments CPDMA Driver
34 *
45 * Copyright (C) 2010 Texas Instruments
56 *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License as
8
- * published by the Free Software Foundation version 2.
9
- *
10
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11
- * kind, whether express or implied; without even the implied warranty
12
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
147 */
158 #include <linux/kernel.h>
169 #include <linux/spinlock.h>
....@@ -141,6 +134,15 @@
141134 #define ACCESS_RW (ACCESS_RO | ACCESS_WO)
142135 };
143136
137
+struct submit_info {
138
+ struct cpdma_chan *chan;
139
+ int directed;
140
+ void *token;
141
+ void *data_virt;
142
+ dma_addr_t data_dma;
143
+ int len;
144
+};
145
+
144146 static struct cpdma_control_info controls[] = {
145147 [CPDMA_TX_RLIM] = {CPDMA_DMACONTROL, 8, 0xffff, ACCESS_RW},
146148 [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO},
....@@ -182,6 +184,8 @@
182184 mode |= (CPDMA_DESC_TO_PORT_EN | \
183185 (directed << CPDMA_TO_PORT_SHIFT)); \
184186 } while (0)
187
+
188
+#define CPDMA_DMA_EXT_MAP BIT(16)
185189
186190 static void cpdma_desc_pool_destroy(struct cpdma_ctlr *ctlr)
187191 {
....@@ -527,7 +531,6 @@
527531 ctlr->num_chan = CPDMA_MAX_CHANNELS;
528532 return ctlr;
529533 }
530
-EXPORT_SYMBOL_GPL(cpdma_ctlr_create);
531534
532535 int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
533536 {
....@@ -588,7 +591,6 @@
588591 spin_unlock_irqrestore(&ctlr->lock, flags);
589592 return 0;
590593 }
591
-EXPORT_SYMBOL_GPL(cpdma_ctlr_start);
592594
593595 int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
594596 {
....@@ -621,7 +623,6 @@
621623 spin_unlock_irqrestore(&ctlr->lock, flags);
622624 return 0;
623625 }
624
-EXPORT_SYMBOL_GPL(cpdma_ctlr_stop);
625626
626627 int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
627628 {
....@@ -639,7 +640,6 @@
639640 cpdma_desc_pool_destroy(ctlr);
640641 return ret;
641642 }
642
-EXPORT_SYMBOL_GPL(cpdma_ctlr_destroy);
643643
644644 int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
645645 {
....@@ -660,25 +660,21 @@
660660 spin_unlock_irqrestore(&ctlr->lock, flags);
661661 return 0;
662662 }
663
-EXPORT_SYMBOL_GPL(cpdma_ctlr_int_ctrl);
664663
665664 void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value)
666665 {
667666 dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, value);
668667 }
669
-EXPORT_SYMBOL_GPL(cpdma_ctlr_eoi);
670668
671669 u32 cpdma_ctrl_rxchs_state(struct cpdma_ctlr *ctlr)
672670 {
673671 return dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED);
674672 }
675
-EXPORT_SYMBOL_GPL(cpdma_ctrl_rxchs_state);
676673
677674 u32 cpdma_ctrl_txchs_state(struct cpdma_ctlr *ctlr)
678675 {
679676 return dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED);
680677 }
681
-EXPORT_SYMBOL_GPL(cpdma_ctrl_txchs_state);
682678
683679 static void cpdma_chan_set_descs(struct cpdma_ctlr *ctlr,
684680 int rx, int desc_num,
....@@ -722,11 +718,11 @@
722718 most_chan->desc_num += desc_cnt;
723719 }
724720
725
-/**
721
+/*
726722 * cpdma_chan_split_pool - Splits ctrl pool between all channels.
727723 * Has to be called under ctlr lock
728724 */
729
-int cpdma_chan_split_pool(struct cpdma_ctlr *ctlr)
725
+static int cpdma_chan_split_pool(struct cpdma_ctlr *ctlr)
730726 {
731727 int tx_per_ch_desc = 0, rx_per_ch_desc = 0;
732728 int free_rx_num = 0, free_tx_num = 0;
....@@ -774,7 +770,6 @@
774770
775771 return 0;
776772 }
777
-EXPORT_SYMBOL_GPL(cpdma_chan_split_pool);
778773
779774
780775 /* cpdma_chan_set_weight - set weight of a channel in percentage.
....@@ -807,7 +802,6 @@
807802 spin_unlock_irqrestore(&ctlr->lock, flags);
808803 return ret;
809804 }
810
-EXPORT_SYMBOL_GPL(cpdma_chan_set_weight);
811805
812806 /* cpdma_chan_get_min_rate - get minimum allowed rate for channel
813807 * Should be called before cpdma_chan_set_rate.
....@@ -822,7 +816,6 @@
822816
823817 return DIV_ROUND_UP(divident, divisor);
824818 }
825
-EXPORT_SYMBOL_GPL(cpdma_chan_get_min_rate);
826819
827820 /* cpdma_chan_set_rate - limits bandwidth for transmit channel.
828821 * The bandwidth * limited channels have to be in order beginning from lowest.
....@@ -867,7 +860,6 @@
867860 spin_unlock_irqrestore(&ctlr->lock, flags);
868861 return ret;
869862 }
870
-EXPORT_SYMBOL_GPL(cpdma_chan_set_rate);
871863
872864 u32 cpdma_chan_get_rate(struct cpdma_chan *ch)
873865 {
....@@ -880,7 +872,6 @@
880872
881873 return rate;
882874 }
883
-EXPORT_SYMBOL_GPL(cpdma_chan_get_rate);
884875
885876 struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
886877 cpdma_handler_fn handler, int rx_type)
....@@ -940,7 +931,6 @@
940931 spin_unlock_irqrestore(&ctlr->lock, flags);
941932 return chan;
942933 }
943
-EXPORT_SYMBOL_GPL(cpdma_chan_create);
944934
945935 int cpdma_chan_get_rx_buf_num(struct cpdma_chan *chan)
946936 {
....@@ -953,7 +943,6 @@
953943
954944 return desc_num;
955945 }
956
-EXPORT_SYMBOL_GPL(cpdma_chan_get_rx_buf_num);
957946
958947 int cpdma_chan_destroy(struct cpdma_chan *chan)
959948 {
....@@ -975,7 +964,6 @@
975964 spin_unlock_irqrestore(&ctlr->lock, flags);
976965 return 0;
977966 }
978
-EXPORT_SYMBOL_GPL(cpdma_chan_destroy);
979967
980968 int cpdma_chan_get_stats(struct cpdma_chan *chan,
981969 struct cpdma_chan_stats *stats)
....@@ -988,7 +976,6 @@
988976 spin_unlock_irqrestore(&chan->lock, flags);
989977 return 0;
990978 }
991
-EXPORT_SYMBOL_GPL(cpdma_chan_get_stats);
992979
993980 static void __cpdma_chan_submit(struct cpdma_chan *chan,
994981 struct cpdma_desc __iomem *desc)
....@@ -1026,34 +1013,25 @@
10261013 }
10271014 }
10281015
1029
-int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
1030
- int len, int directed)
1016
+static int cpdma_chan_submit_si(struct submit_info *si)
10311017 {
1018
+ struct cpdma_chan *chan = si->chan;
10321019 struct cpdma_ctlr *ctlr = chan->ctlr;
1020
+ int len = si->len;
10331021 struct cpdma_desc __iomem *desc;
10341022 dma_addr_t buffer;
1035
- unsigned long flags;
10361023 u32 mode;
1037
- int ret = 0;
1038
-
1039
- spin_lock_irqsave(&chan->lock, flags);
1040
-
1041
- if (chan->state == CPDMA_STATE_TEARDOWN) {
1042
- ret = -EINVAL;
1043
- goto unlock_ret;
1044
- }
1024
+ int ret;
10451025
10461026 if (chan->count >= chan->desc_num) {
10471027 chan->stats.desc_alloc_fail++;
1048
- ret = -ENOMEM;
1049
- goto unlock_ret;
1028
+ return -ENOMEM;
10501029 }
10511030
10521031 desc = cpdma_desc_alloc(ctlr->pool);
10531032 if (!desc) {
10541033 chan->stats.desc_alloc_fail++;
1055
- ret = -ENOMEM;
1056
- goto unlock_ret;
1034
+ return -ENOMEM;
10571035 }
10581036
10591037 if (len < ctlr->params.min_packet_size) {
....@@ -1061,16 +1039,20 @@
10611039 chan->stats.runt_transmit_buff++;
10621040 }
10631041
1064
- buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
1065
- ret = dma_mapping_error(ctlr->dev, buffer);
1066
- if (ret) {
1067
- cpdma_desc_free(ctlr->pool, desc, 1);
1068
- ret = -EINVAL;
1069
- goto unlock_ret;
1070
- }
1071
-
10721042 mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
1073
- cpdma_desc_to_port(chan, mode, directed);
1043
+ cpdma_desc_to_port(chan, mode, si->directed);
1044
+
1045
+ if (si->data_dma) {
1046
+ buffer = si->data_dma;
1047
+ dma_sync_single_for_device(ctlr->dev, buffer, len, chan->dir);
1048
+ } else {
1049
+ buffer = dma_map_single(ctlr->dev, si->data_virt, len, chan->dir);
1050
+ ret = dma_mapping_error(ctlr->dev, buffer);
1051
+ if (ret) {
1052
+ cpdma_desc_free(ctlr->pool, desc, 1);
1053
+ return -EINVAL;
1054
+ }
1055
+ }
10741056
10751057 /* Relaxed IO accessors can be used here as there is read barrier
10761058 * at the end of write sequence.
....@@ -1079,9 +1061,10 @@
10791061 writel_relaxed(buffer, &desc->hw_buffer);
10801062 writel_relaxed(len, &desc->hw_len);
10811063 writel_relaxed(mode | len, &desc->hw_mode);
1082
- writel_relaxed((uintptr_t)token, &desc->sw_token);
1064
+ writel_relaxed((uintptr_t)si->token, &desc->sw_token);
10831065 writel_relaxed(buffer, &desc->sw_buffer);
1084
- writel_relaxed(len, &desc->sw_len);
1066
+ writel_relaxed(si->data_dma ? len | CPDMA_DMA_EXT_MAP : len,
1067
+ &desc->sw_len);
10851068 desc_read(desc, sw_len);
10861069
10871070 __cpdma_chan_submit(chan, desc);
....@@ -1090,12 +1073,108 @@
10901073 chan_write(chan, rxfree, 1);
10911074
10921075 chan->count++;
1076
+ return 0;
1077
+}
10931078
1094
-unlock_ret:
1079
+int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,
1080
+ int len, int directed)
1081
+{
1082
+ struct submit_info si;
1083
+ unsigned long flags;
1084
+ int ret;
1085
+
1086
+ si.chan = chan;
1087
+ si.token = token;
1088
+ si.data_virt = data;
1089
+ si.data_dma = 0;
1090
+ si.len = len;
1091
+ si.directed = directed;
1092
+
1093
+ spin_lock_irqsave(&chan->lock, flags);
1094
+ if (chan->state == CPDMA_STATE_TEARDOWN) {
1095
+ spin_unlock_irqrestore(&chan->lock, flags);
1096
+ return -EINVAL;
1097
+ }
1098
+
1099
+ ret = cpdma_chan_submit_si(&si);
10951100 spin_unlock_irqrestore(&chan->lock, flags);
10961101 return ret;
10971102 }
1098
-EXPORT_SYMBOL_GPL(cpdma_chan_submit);
1103
+
1104
+int cpdma_chan_idle_submit_mapped(struct cpdma_chan *chan, void *token,
1105
+ dma_addr_t data, int len, int directed)
1106
+{
1107
+ struct submit_info si;
1108
+ unsigned long flags;
1109
+ int ret;
1110
+
1111
+ si.chan = chan;
1112
+ si.token = token;
1113
+ si.data_virt = NULL;
1114
+ si.data_dma = data;
1115
+ si.len = len;
1116
+ si.directed = directed;
1117
+
1118
+ spin_lock_irqsave(&chan->lock, flags);
1119
+ if (chan->state == CPDMA_STATE_TEARDOWN) {
1120
+ spin_unlock_irqrestore(&chan->lock, flags);
1121
+ return -EINVAL;
1122
+ }
1123
+
1124
+ ret = cpdma_chan_submit_si(&si);
1125
+ spin_unlock_irqrestore(&chan->lock, flags);
1126
+ return ret;
1127
+}
1128
+
1129
+int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
1130
+ int len, int directed)
1131
+{
1132
+ struct submit_info si;
1133
+ unsigned long flags;
1134
+ int ret;
1135
+
1136
+ si.chan = chan;
1137
+ si.token = token;
1138
+ si.data_virt = data;
1139
+ si.data_dma = 0;
1140
+ si.len = len;
1141
+ si.directed = directed;
1142
+
1143
+ spin_lock_irqsave(&chan->lock, flags);
1144
+ if (chan->state != CPDMA_STATE_ACTIVE) {
1145
+ spin_unlock_irqrestore(&chan->lock, flags);
1146
+ return -EINVAL;
1147
+ }
1148
+
1149
+ ret = cpdma_chan_submit_si(&si);
1150
+ spin_unlock_irqrestore(&chan->lock, flags);
1151
+ return ret;
1152
+}
1153
+
1154
+int cpdma_chan_submit_mapped(struct cpdma_chan *chan, void *token,
1155
+ dma_addr_t data, int len, int directed)
1156
+{
1157
+ struct submit_info si;
1158
+ unsigned long flags;
1159
+ int ret;
1160
+
1161
+ si.chan = chan;
1162
+ si.token = token;
1163
+ si.data_virt = NULL;
1164
+ si.data_dma = data;
1165
+ si.len = len;
1166
+ si.directed = directed;
1167
+
1168
+ spin_lock_irqsave(&chan->lock, flags);
1169
+ if (chan->state != CPDMA_STATE_ACTIVE) {
1170
+ spin_unlock_irqrestore(&chan->lock, flags);
1171
+ return -EINVAL;
1172
+ }
1173
+
1174
+ ret = cpdma_chan_submit_si(&si);
1175
+ spin_unlock_irqrestore(&chan->lock, flags);
1176
+ return ret;
1177
+}
10991178
11001179 bool cpdma_check_free_tx_desc(struct cpdma_chan *chan)
11011180 {
....@@ -1110,7 +1189,6 @@
11101189 spin_unlock_irqrestore(&chan->lock, flags);
11111190 return free_tx_desc;
11121191 }
1113
-EXPORT_SYMBOL_GPL(cpdma_check_free_tx_desc);
11141192
11151193 static void __cpdma_chan_free(struct cpdma_chan *chan,
11161194 struct cpdma_desc __iomem *desc,
....@@ -1123,10 +1201,17 @@
11231201 uintptr_t token;
11241202
11251203 token = desc_read(desc, sw_token);
1126
- buff_dma = desc_read(desc, sw_buffer);
11271204 origlen = desc_read(desc, sw_len);
11281205
1129
- dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
1206
+ buff_dma = desc_read(desc, sw_buffer);
1207
+ if (origlen & CPDMA_DMA_EXT_MAP) {
1208
+ origlen &= ~CPDMA_DMA_EXT_MAP;
1209
+ dma_sync_single_for_cpu(ctlr->dev, buff_dma, origlen,
1210
+ chan->dir);
1211
+ } else {
1212
+ dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
1213
+ }
1214
+
11301215 cpdma_desc_free(pool, desc, 1);
11311216 (*chan->handler)((void *)token, outlen, status);
11321217 }
....@@ -1204,7 +1289,6 @@
12041289 }
12051290 return used;
12061291 }
1207
-EXPORT_SYMBOL_GPL(cpdma_chan_process);
12081292
12091293 int cpdma_chan_start(struct cpdma_chan *chan)
12101294 {
....@@ -1224,7 +1308,6 @@
12241308
12251309 return 0;
12261310 }
1227
-EXPORT_SYMBOL_GPL(cpdma_chan_start);
12281311
12291312 int cpdma_chan_stop(struct cpdma_chan *chan)
12301313 {
....@@ -1287,7 +1370,6 @@
12871370 spin_unlock_irqrestore(&chan->lock, flags);
12881371 return 0;
12891372 }
1290
-EXPORT_SYMBOL_GPL(cpdma_chan_stop);
12911373
12921374 int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
12931375 {
....@@ -1329,25 +1411,34 @@
13291411
13301412 return ret;
13311413 }
1332
-EXPORT_SYMBOL_GPL(cpdma_control_set);
13331414
13341415 int cpdma_get_num_rx_descs(struct cpdma_ctlr *ctlr)
13351416 {
13361417 return ctlr->num_rx_desc;
13371418 }
1338
-EXPORT_SYMBOL_GPL(cpdma_get_num_rx_descs);
13391419
13401420 int cpdma_get_num_tx_descs(struct cpdma_ctlr *ctlr)
13411421 {
13421422 return ctlr->num_tx_desc;
13431423 }
1344
-EXPORT_SYMBOL_GPL(cpdma_get_num_tx_descs);
13451424
1346
-void cpdma_set_num_rx_descs(struct cpdma_ctlr *ctlr, int num_rx_desc)
1425
+int cpdma_set_num_rx_descs(struct cpdma_ctlr *ctlr, int num_rx_desc)
13471426 {
1427
+ unsigned long flags;
1428
+ int temp, ret;
1429
+
1430
+ spin_lock_irqsave(&ctlr->lock, flags);
1431
+
1432
+ temp = ctlr->num_rx_desc;
13481433 ctlr->num_rx_desc = num_rx_desc;
13491434 ctlr->num_tx_desc = ctlr->pool->num_desc - ctlr->num_rx_desc;
1350
-}
1351
-EXPORT_SYMBOL_GPL(cpdma_set_num_rx_descs);
1435
+ ret = cpdma_chan_split_pool(ctlr);
1436
+ if (ret) {
1437
+ ctlr->num_rx_desc = temp;
1438
+ ctlr->num_tx_desc = ctlr->pool->num_desc - ctlr->num_rx_desc;
1439
+ }
13521440
1353
-MODULE_LICENSE("GPL");
1441
+ spin_unlock_irqrestore(&ctlr->lock, flags);
1442
+
1443
+ return ret;
1444
+}