| .. | .. |
|---|
| 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 | +} |
|---|