.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Texas Instruments CPDMA Driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2010 Texas Instruments |
---|
5 | 6 | * |
---|
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. |
---|
14 | 7 | */ |
---|
15 | 8 | #include <linux/kernel.h> |
---|
16 | 9 | #include <linux/spinlock.h> |
---|
.. | .. |
---|
141 | 134 | #define ACCESS_RW (ACCESS_RO | ACCESS_WO) |
---|
142 | 135 | }; |
---|
143 | 136 | |
---|
| 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 | + |
---|
144 | 146 | static struct cpdma_control_info controls[] = { |
---|
145 | 147 | [CPDMA_TX_RLIM] = {CPDMA_DMACONTROL, 8, 0xffff, ACCESS_RW}, |
---|
146 | 148 | [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO}, |
---|
.. | .. |
---|
182 | 184 | mode |= (CPDMA_DESC_TO_PORT_EN | \ |
---|
183 | 185 | (directed << CPDMA_TO_PORT_SHIFT)); \ |
---|
184 | 186 | } while (0) |
---|
| 187 | + |
---|
| 188 | +#define CPDMA_DMA_EXT_MAP BIT(16) |
---|
185 | 189 | |
---|
186 | 190 | static void cpdma_desc_pool_destroy(struct cpdma_ctlr *ctlr) |
---|
187 | 191 | { |
---|
.. | .. |
---|
527 | 531 | ctlr->num_chan = CPDMA_MAX_CHANNELS; |
---|
528 | 532 | return ctlr; |
---|
529 | 533 | } |
---|
530 | | -EXPORT_SYMBOL_GPL(cpdma_ctlr_create); |
---|
531 | 534 | |
---|
532 | 535 | int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) |
---|
533 | 536 | { |
---|
.. | .. |
---|
588 | 591 | spin_unlock_irqrestore(&ctlr->lock, flags); |
---|
589 | 592 | return 0; |
---|
590 | 593 | } |
---|
591 | | -EXPORT_SYMBOL_GPL(cpdma_ctlr_start); |
---|
592 | 594 | |
---|
593 | 595 | int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr) |
---|
594 | 596 | { |
---|
.. | .. |
---|
621 | 623 | spin_unlock_irqrestore(&ctlr->lock, flags); |
---|
622 | 624 | return 0; |
---|
623 | 625 | } |
---|
624 | | -EXPORT_SYMBOL_GPL(cpdma_ctlr_stop); |
---|
625 | 626 | |
---|
626 | 627 | int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr) |
---|
627 | 628 | { |
---|
.. | .. |
---|
639 | 640 | cpdma_desc_pool_destroy(ctlr); |
---|
640 | 641 | return ret; |
---|
641 | 642 | } |
---|
642 | | -EXPORT_SYMBOL_GPL(cpdma_ctlr_destroy); |
---|
643 | 643 | |
---|
644 | 644 | int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable) |
---|
645 | 645 | { |
---|
.. | .. |
---|
660 | 660 | spin_unlock_irqrestore(&ctlr->lock, flags); |
---|
661 | 661 | return 0; |
---|
662 | 662 | } |
---|
663 | | -EXPORT_SYMBOL_GPL(cpdma_ctlr_int_ctrl); |
---|
664 | 663 | |
---|
665 | 664 | void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value) |
---|
666 | 665 | { |
---|
667 | 666 | dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, value); |
---|
668 | 667 | } |
---|
669 | | -EXPORT_SYMBOL_GPL(cpdma_ctlr_eoi); |
---|
670 | 668 | |
---|
671 | 669 | u32 cpdma_ctrl_rxchs_state(struct cpdma_ctlr *ctlr) |
---|
672 | 670 | { |
---|
673 | 671 | return dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED); |
---|
674 | 672 | } |
---|
675 | | -EXPORT_SYMBOL_GPL(cpdma_ctrl_rxchs_state); |
---|
676 | 673 | |
---|
677 | 674 | u32 cpdma_ctrl_txchs_state(struct cpdma_ctlr *ctlr) |
---|
678 | 675 | { |
---|
679 | 676 | return dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED); |
---|
680 | 677 | } |
---|
681 | | -EXPORT_SYMBOL_GPL(cpdma_ctrl_txchs_state); |
---|
682 | 678 | |
---|
683 | 679 | static void cpdma_chan_set_descs(struct cpdma_ctlr *ctlr, |
---|
684 | 680 | int rx, int desc_num, |
---|
.. | .. |
---|
722 | 718 | most_chan->desc_num += desc_cnt; |
---|
723 | 719 | } |
---|
724 | 720 | |
---|
725 | | -/** |
---|
| 721 | +/* |
---|
726 | 722 | * cpdma_chan_split_pool - Splits ctrl pool between all channels. |
---|
727 | 723 | * Has to be called under ctlr lock |
---|
728 | 724 | */ |
---|
729 | | -int cpdma_chan_split_pool(struct cpdma_ctlr *ctlr) |
---|
| 725 | +static int cpdma_chan_split_pool(struct cpdma_ctlr *ctlr) |
---|
730 | 726 | { |
---|
731 | 727 | int tx_per_ch_desc = 0, rx_per_ch_desc = 0; |
---|
732 | 728 | int free_rx_num = 0, free_tx_num = 0; |
---|
.. | .. |
---|
774 | 770 | |
---|
775 | 771 | return 0; |
---|
776 | 772 | } |
---|
777 | | -EXPORT_SYMBOL_GPL(cpdma_chan_split_pool); |
---|
778 | 773 | |
---|
779 | 774 | |
---|
780 | 775 | /* cpdma_chan_set_weight - set weight of a channel in percentage. |
---|
.. | .. |
---|
807 | 802 | spin_unlock_irqrestore(&ctlr->lock, flags); |
---|
808 | 803 | return ret; |
---|
809 | 804 | } |
---|
810 | | -EXPORT_SYMBOL_GPL(cpdma_chan_set_weight); |
---|
811 | 805 | |
---|
812 | 806 | /* cpdma_chan_get_min_rate - get minimum allowed rate for channel |
---|
813 | 807 | * Should be called before cpdma_chan_set_rate. |
---|
.. | .. |
---|
822 | 816 | |
---|
823 | 817 | return DIV_ROUND_UP(divident, divisor); |
---|
824 | 818 | } |
---|
825 | | -EXPORT_SYMBOL_GPL(cpdma_chan_get_min_rate); |
---|
826 | 819 | |
---|
827 | 820 | /* cpdma_chan_set_rate - limits bandwidth for transmit channel. |
---|
828 | 821 | * The bandwidth * limited channels have to be in order beginning from lowest. |
---|
.. | .. |
---|
867 | 860 | spin_unlock_irqrestore(&ctlr->lock, flags); |
---|
868 | 861 | return ret; |
---|
869 | 862 | } |
---|
870 | | -EXPORT_SYMBOL_GPL(cpdma_chan_set_rate); |
---|
871 | 863 | |
---|
872 | 864 | u32 cpdma_chan_get_rate(struct cpdma_chan *ch) |
---|
873 | 865 | { |
---|
.. | .. |
---|
880 | 872 | |
---|
881 | 873 | return rate; |
---|
882 | 874 | } |
---|
883 | | -EXPORT_SYMBOL_GPL(cpdma_chan_get_rate); |
---|
884 | 875 | |
---|
885 | 876 | struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, |
---|
886 | 877 | cpdma_handler_fn handler, int rx_type) |
---|
.. | .. |
---|
940 | 931 | spin_unlock_irqrestore(&ctlr->lock, flags); |
---|
941 | 932 | return chan; |
---|
942 | 933 | } |
---|
943 | | -EXPORT_SYMBOL_GPL(cpdma_chan_create); |
---|
944 | 934 | |
---|
945 | 935 | int cpdma_chan_get_rx_buf_num(struct cpdma_chan *chan) |
---|
946 | 936 | { |
---|
.. | .. |
---|
953 | 943 | |
---|
954 | 944 | return desc_num; |
---|
955 | 945 | } |
---|
956 | | -EXPORT_SYMBOL_GPL(cpdma_chan_get_rx_buf_num); |
---|
957 | 946 | |
---|
958 | 947 | int cpdma_chan_destroy(struct cpdma_chan *chan) |
---|
959 | 948 | { |
---|
.. | .. |
---|
975 | 964 | spin_unlock_irqrestore(&ctlr->lock, flags); |
---|
976 | 965 | return 0; |
---|
977 | 966 | } |
---|
978 | | -EXPORT_SYMBOL_GPL(cpdma_chan_destroy); |
---|
979 | 967 | |
---|
980 | 968 | int cpdma_chan_get_stats(struct cpdma_chan *chan, |
---|
981 | 969 | struct cpdma_chan_stats *stats) |
---|
.. | .. |
---|
988 | 976 | spin_unlock_irqrestore(&chan->lock, flags); |
---|
989 | 977 | return 0; |
---|
990 | 978 | } |
---|
991 | | -EXPORT_SYMBOL_GPL(cpdma_chan_get_stats); |
---|
992 | 979 | |
---|
993 | 980 | static void __cpdma_chan_submit(struct cpdma_chan *chan, |
---|
994 | 981 | struct cpdma_desc __iomem *desc) |
---|
.. | .. |
---|
1026 | 1013 | } |
---|
1027 | 1014 | } |
---|
1028 | 1015 | |
---|
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) |
---|
1031 | 1017 | { |
---|
| 1018 | + struct cpdma_chan *chan = si->chan; |
---|
1032 | 1019 | struct cpdma_ctlr *ctlr = chan->ctlr; |
---|
| 1020 | + int len = si->len; |
---|
1033 | 1021 | struct cpdma_desc __iomem *desc; |
---|
1034 | 1022 | dma_addr_t buffer; |
---|
1035 | | - unsigned long flags; |
---|
1036 | 1023 | 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; |
---|
1045 | 1025 | |
---|
1046 | 1026 | if (chan->count >= chan->desc_num) { |
---|
1047 | 1027 | chan->stats.desc_alloc_fail++; |
---|
1048 | | - ret = -ENOMEM; |
---|
1049 | | - goto unlock_ret; |
---|
| 1028 | + return -ENOMEM; |
---|
1050 | 1029 | } |
---|
1051 | 1030 | |
---|
1052 | 1031 | desc = cpdma_desc_alloc(ctlr->pool); |
---|
1053 | 1032 | if (!desc) { |
---|
1054 | 1033 | chan->stats.desc_alloc_fail++; |
---|
1055 | | - ret = -ENOMEM; |
---|
1056 | | - goto unlock_ret; |
---|
| 1034 | + return -ENOMEM; |
---|
1057 | 1035 | } |
---|
1058 | 1036 | |
---|
1059 | 1037 | if (len < ctlr->params.min_packet_size) { |
---|
.. | .. |
---|
1061 | 1039 | chan->stats.runt_transmit_buff++; |
---|
1062 | 1040 | } |
---|
1063 | 1041 | |
---|
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 | | - |
---|
1072 | 1042 | 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 | + } |
---|
1074 | 1056 | |
---|
1075 | 1057 | /* Relaxed IO accessors can be used here as there is read barrier |
---|
1076 | 1058 | * at the end of write sequence. |
---|
.. | .. |
---|
1079 | 1061 | writel_relaxed(buffer, &desc->hw_buffer); |
---|
1080 | 1062 | writel_relaxed(len, &desc->hw_len); |
---|
1081 | 1063 | 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); |
---|
1083 | 1065 | 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); |
---|
1085 | 1068 | desc_read(desc, sw_len); |
---|
1086 | 1069 | |
---|
1087 | 1070 | __cpdma_chan_submit(chan, desc); |
---|
.. | .. |
---|
1090 | 1073 | chan_write(chan, rxfree, 1); |
---|
1091 | 1074 | |
---|
1092 | 1075 | chan->count++; |
---|
| 1076 | + return 0; |
---|
| 1077 | +} |
---|
1093 | 1078 | |
---|
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); |
---|
1095 | 1100 | spin_unlock_irqrestore(&chan->lock, flags); |
---|
1096 | 1101 | return ret; |
---|
1097 | 1102 | } |
---|
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 | +} |
---|
1099 | 1178 | |
---|
1100 | 1179 | bool cpdma_check_free_tx_desc(struct cpdma_chan *chan) |
---|
1101 | 1180 | { |
---|
.. | .. |
---|
1110 | 1189 | spin_unlock_irqrestore(&chan->lock, flags); |
---|
1111 | 1190 | return free_tx_desc; |
---|
1112 | 1191 | } |
---|
1113 | | -EXPORT_SYMBOL_GPL(cpdma_check_free_tx_desc); |
---|
1114 | 1192 | |
---|
1115 | 1193 | static void __cpdma_chan_free(struct cpdma_chan *chan, |
---|
1116 | 1194 | struct cpdma_desc __iomem *desc, |
---|
.. | .. |
---|
1123 | 1201 | uintptr_t token; |
---|
1124 | 1202 | |
---|
1125 | 1203 | token = desc_read(desc, sw_token); |
---|
1126 | | - buff_dma = desc_read(desc, sw_buffer); |
---|
1127 | 1204 | origlen = desc_read(desc, sw_len); |
---|
1128 | 1205 | |
---|
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 | + |
---|
1130 | 1215 | cpdma_desc_free(pool, desc, 1); |
---|
1131 | 1216 | (*chan->handler)((void *)token, outlen, status); |
---|
1132 | 1217 | } |
---|
.. | .. |
---|
1204 | 1289 | } |
---|
1205 | 1290 | return used; |
---|
1206 | 1291 | } |
---|
1207 | | -EXPORT_SYMBOL_GPL(cpdma_chan_process); |
---|
1208 | 1292 | |
---|
1209 | 1293 | int cpdma_chan_start(struct cpdma_chan *chan) |
---|
1210 | 1294 | { |
---|
.. | .. |
---|
1224 | 1308 | |
---|
1225 | 1309 | return 0; |
---|
1226 | 1310 | } |
---|
1227 | | -EXPORT_SYMBOL_GPL(cpdma_chan_start); |
---|
1228 | 1311 | |
---|
1229 | 1312 | int cpdma_chan_stop(struct cpdma_chan *chan) |
---|
1230 | 1313 | { |
---|
.. | .. |
---|
1287 | 1370 | spin_unlock_irqrestore(&chan->lock, flags); |
---|
1288 | 1371 | return 0; |
---|
1289 | 1372 | } |
---|
1290 | | -EXPORT_SYMBOL_GPL(cpdma_chan_stop); |
---|
1291 | 1373 | |
---|
1292 | 1374 | int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable) |
---|
1293 | 1375 | { |
---|
.. | .. |
---|
1329 | 1411 | |
---|
1330 | 1412 | return ret; |
---|
1331 | 1413 | } |
---|
1332 | | -EXPORT_SYMBOL_GPL(cpdma_control_set); |
---|
1333 | 1414 | |
---|
1334 | 1415 | int cpdma_get_num_rx_descs(struct cpdma_ctlr *ctlr) |
---|
1335 | 1416 | { |
---|
1336 | 1417 | return ctlr->num_rx_desc; |
---|
1337 | 1418 | } |
---|
1338 | | -EXPORT_SYMBOL_GPL(cpdma_get_num_rx_descs); |
---|
1339 | 1419 | |
---|
1340 | 1420 | int cpdma_get_num_tx_descs(struct cpdma_ctlr *ctlr) |
---|
1341 | 1421 | { |
---|
1342 | 1422 | return ctlr->num_tx_desc; |
---|
1343 | 1423 | } |
---|
1344 | | -EXPORT_SYMBOL_GPL(cpdma_get_num_tx_descs); |
---|
1345 | 1424 | |
---|
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) |
---|
1347 | 1426 | { |
---|
| 1427 | + unsigned long flags; |
---|
| 1428 | + int temp, ret; |
---|
| 1429 | + |
---|
| 1430 | + spin_lock_irqsave(&ctlr->lock, flags); |
---|
| 1431 | + |
---|
| 1432 | + temp = ctlr->num_rx_desc; |
---|
1348 | 1433 | ctlr->num_rx_desc = num_rx_desc; |
---|
1349 | 1434 | 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 | + } |
---|
1352 | 1440 | |
---|
1353 | | -MODULE_LICENSE("GPL"); |
---|
| 1441 | + spin_unlock_irqrestore(&ctlr->lock, flags); |
---|
| 1442 | + |
---|
| 1443 | + return ret; |
---|
| 1444 | +} |
---|