]>
Commit | Line | Data |
---|---|---|
286a8372 GC |
1 | /******************************************************************************* |
2 | Specialised functions for managing Chained mode | |
3 | ||
4 | Copyright(C) 2011 STMicroelectronics Ltd | |
5 | ||
6 | It defines all the functions used to handle the normal/enhanced | |
7 | descriptors in case of the DMA is configured to work in chained or | |
8 | in ring mode. | |
9 | ||
10 | This program is free software; you can redistribute it and/or modify it | |
11 | under the terms and conditions of the GNU General Public License, | |
12 | version 2, as published by the Free Software Foundation. | |
13 | ||
14 | This program is distributed in the hope it will be useful, but WITHOUT | |
15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
17 | more details. | |
18 | ||
286a8372 GC |
19 | The full GNU General Public License is included in this distribution in |
20 | the file called "COPYING". | |
21 | ||
22 | Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> | |
23 | *******************************************************************************/ | |
24 | ||
25 | #include "stmmac.h" | |
26 | ||
362b37be | 27 | static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) |
286a8372 | 28 | { |
ce736788 | 29 | struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)p; |
286a8372 | 30 | unsigned int nopaged_len = skb_headlen(skb); |
ce736788 JP |
31 | struct stmmac_priv *priv = tx_q->priv_data; |
32 | unsigned int entry = tx_q->cur_tx; | |
f8be0d78 | 33 | unsigned int bmax, des2; |
286a8372 | 34 | unsigned int i = 1, len; |
ce736788 JP |
35 | struct dma_desc *desc; |
36 | ||
37 | desc = tx_q->dma_tx + entry; | |
286a8372 GC |
38 | |
39 | if (priv->plat->enh_desc) | |
40 | bmax = BUF_SIZE_8KiB; | |
41 | else | |
42 | bmax = BUF_SIZE_2KiB; | |
43 | ||
44 | len = nopaged_len - bmax; | |
45 | ||
f8be0d78 MW |
46 | des2 = dma_map_single(priv->device, skb->data, |
47 | bmax, DMA_TO_DEVICE); | |
48 | desc->des2 = cpu_to_le32(des2); | |
49 | if (dma_mapping_error(priv->device, des2)) | |
362b37be | 50 | return -1; |
ce736788 JP |
51 | tx_q->tx_skbuff_dma[entry].buf = des2; |
52 | tx_q->tx_skbuff_dma[entry].len = bmax; | |
be434d50 GC |
53 | /* do not close the descriptor and do not set own bit */ |
54 | priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE, | |
fe6af0e1 | 55 | 0, false, skb->len); |
286a8372 GC |
56 | |
57 | while (len != 0) { | |
ce736788 | 58 | tx_q->tx_skbuff[entry] = NULL; |
e3ad57c9 | 59 | entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); |
ce736788 | 60 | desc = tx_q->dma_tx + entry; |
286a8372 GC |
61 | |
62 | if (len > bmax) { | |
f8be0d78 MW |
63 | des2 = dma_map_single(priv->device, |
64 | (skb->data + bmax * i), | |
65 | bmax, DMA_TO_DEVICE); | |
66 | desc->des2 = cpu_to_le32(des2); | |
67 | if (dma_mapping_error(priv->device, des2)) | |
362b37be | 68 | return -1; |
ce736788 JP |
69 | tx_q->tx_skbuff_dma[entry].buf = des2; |
70 | tx_q->tx_skbuff_dma[entry].len = bmax; | |
4a7d666a | 71 | priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum, |
be434d50 | 72 | STMMAC_CHAIN_MODE, 1, |
fe6af0e1 | 73 | false, skb->len); |
286a8372 GC |
74 | len -= bmax; |
75 | i++; | |
76 | } else { | |
f8be0d78 MW |
77 | des2 = dma_map_single(priv->device, |
78 | (skb->data + bmax * i), len, | |
79 | DMA_TO_DEVICE); | |
80 | desc->des2 = cpu_to_le32(des2); | |
81 | if (dma_mapping_error(priv->device, des2)) | |
362b37be | 82 | return -1; |
ce736788 JP |
83 | tx_q->tx_skbuff_dma[entry].buf = des2; |
84 | tx_q->tx_skbuff_dma[entry].len = len; | |
be434d50 | 85 | /* last descriptor can be set now */ |
4a7d666a | 86 | priv->hw->desc->prepare_tx_desc(desc, 0, len, csum, |
be434d50 | 87 | STMMAC_CHAIN_MODE, 1, |
fe6af0e1 | 88 | true, skb->len); |
286a8372 GC |
89 | len = 0; |
90 | } | |
91 | } | |
e3ad57c9 | 92 | |
ce736788 | 93 | tx_q->cur_tx = entry; |
e3ad57c9 | 94 | |
286a8372 GC |
95 | return entry; |
96 | } | |
97 | ||
98 | static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc) | |
99 | { | |
100 | unsigned int ret = 0; | |
101 | ||
102 | if ((enh_desc && (len > BUF_SIZE_8KiB)) || | |
103 | (!enh_desc && (len > BUF_SIZE_2KiB))) { | |
104 | ret = 1; | |
105 | } | |
106 | ||
107 | return ret; | |
108 | } | |
109 | ||
c24602ef GC |
110 | static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr, |
111 | unsigned int size, unsigned int extend_desc) | |
286a8372 GC |
112 | { |
113 | /* | |
114 | * In chained mode the des3 points to the next element in the ring. | |
115 | * The latest element has to point to the head. | |
116 | */ | |
117 | int i; | |
286a8372 GC |
118 | dma_addr_t dma_phy = phy_addr; |
119 | ||
c24602ef | 120 | if (extend_desc) { |
ceb69499 | 121 | struct dma_extended_desc *p = (struct dma_extended_desc *)des; |
c24602ef GC |
122 | for (i = 0; i < (size - 1); i++) { |
123 | dma_phy += sizeof(struct dma_extended_desc); | |
f8be0d78 | 124 | p->basic.des3 = cpu_to_le32((unsigned int)dma_phy); |
c24602ef GC |
125 | p++; |
126 | } | |
f8be0d78 | 127 | p->basic.des3 = cpu_to_le32((unsigned int)phy_addr); |
c24602ef GC |
128 | |
129 | } else { | |
ceb69499 | 130 | struct dma_desc *p = (struct dma_desc *)des; |
c24602ef GC |
131 | for (i = 0; i < (size - 1); i++) { |
132 | dma_phy += sizeof(struct dma_desc); | |
f8be0d78 | 133 | p->des3 = cpu_to_le32((unsigned int)dma_phy); |
c24602ef GC |
134 | p++; |
135 | } | |
f8be0d78 | 136 | p->des3 = cpu_to_le32((unsigned int)phy_addr); |
286a8372 | 137 | } |
286a8372 GC |
138 | } |
139 | ||
891434b1 RK |
140 | static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p) |
141 | { | |
54139cf3 JP |
142 | struct stmmac_rx_queue *rx_q = (struct stmmac_rx_queue *)priv_ptr; |
143 | struct stmmac_priv *priv = rx_q->priv_data; | |
891434b1 RK |
144 | |
145 | if (priv->hwts_rx_en && !priv->extend_desc) | |
146 | /* NOTE: Device will overwrite des3 with timestamp value if | |
147 | * 1588-2002 time stamping is enabled, hence reinitialize it | |
148 | * to keep explicit chaining in the descriptor. | |
149 | */ | |
54139cf3 JP |
150 | p->des3 = cpu_to_le32((unsigned int)(rx_q->dma_rx_phy + |
151 | (((rx_q->dirty_rx) + 1) % | |
f8be0d78 MW |
152 | DMA_RX_SIZE) * |
153 | sizeof(struct dma_desc))); | |
891434b1 RK |
154 | } |
155 | ||
156 | static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p) | |
157 | { | |
ce736788 JP |
158 | struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)priv_ptr; |
159 | struct stmmac_priv *priv = tx_q->priv_data; | |
160 | unsigned int entry = tx_q->dirty_tx; | |
891434b1 | 161 | |
ce736788 | 162 | if (tx_q->tx_skbuff_dma[entry].last_segment && !priv->extend_desc && |
96951366 | 163 | priv->hwts_tx_en) |
891434b1 RK |
164 | /* NOTE: Device will overwrite des3 with timestamp value if |
165 | * 1588-2002 time stamping is enabled, hence reinitialize it | |
166 | * to keep explicit chaining in the descriptor. | |
167 | */ | |
ce736788 JP |
168 | p->des3 = cpu_to_le32((unsigned int)((tx_q->dma_tx_phy + |
169 | ((tx_q->dirty_tx + 1) % DMA_TX_SIZE)) | |
f8be0d78 | 170 | * sizeof(struct dma_desc))); |
891434b1 RK |
171 | } |
172 | ||
29896a67 | 173 | const struct stmmac_mode_ops chain_mode_ops = { |
c24602ef | 174 | .init = stmmac_init_dma_chain, |
286a8372 GC |
175 | .is_jumbo_frm = stmmac_is_jumbo_frm, |
176 | .jumbo_frm = stmmac_jumbo_frm, | |
891434b1 RK |
177 | .refill_desc3 = stmmac_refill_desc3, |
178 | .clean_desc3 = stmmac_clean_desc3, | |
286a8372 | 179 | }; |