]>
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 | { |
5bacd778 LC |
29 | struct stmmac_priv *priv = (struct stmmac_priv *)p; |
30 | unsigned int entry = priv->cur_tx; | |
31 | struct dma_desc *desc = priv->dma_tx + entry; | |
286a8372 | 32 | unsigned int nopaged_len = skb_headlen(skb); |
f8be0d78 | 33 | unsigned int bmax, des2; |
286a8372 GC |
34 | unsigned int i = 1, len; |
35 | ||
36 | if (priv->plat->enh_desc) | |
37 | bmax = BUF_SIZE_8KiB; | |
38 | else | |
39 | bmax = BUF_SIZE_2KiB; | |
40 | ||
41 | len = nopaged_len - bmax; | |
42 | ||
f8be0d78 MW |
43 | des2 = dma_map_single(priv->device, skb->data, |
44 | bmax, DMA_TO_DEVICE); | |
45 | desc->des2 = cpu_to_le32(des2); | |
46 | if (dma_mapping_error(priv->device, des2)) | |
362b37be | 47 | return -1; |
5bacd778 LC |
48 | priv->tx_skbuff_dma[entry].buf = des2; |
49 | priv->tx_skbuff_dma[entry].len = bmax; | |
be434d50 GC |
50 | /* do not close the descriptor and do not set own bit */ |
51 | priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE, | |
52 | 0, false); | |
286a8372 GC |
53 | |
54 | while (len != 0) { | |
5bacd778 | 55 | priv->tx_skbuff[entry] = NULL; |
e3ad57c9 | 56 | entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); |
5bacd778 | 57 | desc = priv->dma_tx + entry; |
286a8372 GC |
58 | |
59 | if (len > bmax) { | |
f8be0d78 MW |
60 | des2 = dma_map_single(priv->device, |
61 | (skb->data + bmax * i), | |
62 | bmax, DMA_TO_DEVICE); | |
63 | desc->des2 = cpu_to_le32(des2); | |
64 | if (dma_mapping_error(priv->device, des2)) | |
362b37be | 65 | return -1; |
5bacd778 LC |
66 | priv->tx_skbuff_dma[entry].buf = des2; |
67 | priv->tx_skbuff_dma[entry].len = bmax; | |
4a7d666a | 68 | priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum, |
be434d50 GC |
69 | STMMAC_CHAIN_MODE, 1, |
70 | false); | |
286a8372 GC |
71 | len -= bmax; |
72 | i++; | |
73 | } else { | |
f8be0d78 MW |
74 | des2 = dma_map_single(priv->device, |
75 | (skb->data + bmax * i), len, | |
76 | DMA_TO_DEVICE); | |
77 | desc->des2 = cpu_to_le32(des2); | |
78 | if (dma_mapping_error(priv->device, des2)) | |
362b37be | 79 | return -1; |
5bacd778 LC |
80 | priv->tx_skbuff_dma[entry].buf = des2; |
81 | priv->tx_skbuff_dma[entry].len = len; | |
be434d50 | 82 | /* last descriptor can be set now */ |
4a7d666a | 83 | priv->hw->desc->prepare_tx_desc(desc, 0, len, csum, |
be434d50 GC |
84 | STMMAC_CHAIN_MODE, 1, |
85 | true); | |
286a8372 GC |
86 | len = 0; |
87 | } | |
88 | } | |
e3ad57c9 | 89 | |
5bacd778 | 90 | priv->cur_tx = entry; |
e3ad57c9 | 91 | |
286a8372 GC |
92 | return entry; |
93 | } | |
94 | ||
95 | static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc) | |
96 | { | |
97 | unsigned int ret = 0; | |
98 | ||
99 | if ((enh_desc && (len > BUF_SIZE_8KiB)) || | |
100 | (!enh_desc && (len > BUF_SIZE_2KiB))) { | |
101 | ret = 1; | |
102 | } | |
103 | ||
104 | return ret; | |
105 | } | |
106 | ||
c24602ef GC |
107 | static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr, |
108 | unsigned int size, unsigned int extend_desc) | |
286a8372 GC |
109 | { |
110 | /* | |
111 | * In chained mode the des3 points to the next element in the ring. | |
112 | * The latest element has to point to the head. | |
113 | */ | |
114 | int i; | |
286a8372 GC |
115 | dma_addr_t dma_phy = phy_addr; |
116 | ||
c24602ef | 117 | if (extend_desc) { |
ceb69499 | 118 | struct dma_extended_desc *p = (struct dma_extended_desc *)des; |
c24602ef GC |
119 | for (i = 0; i < (size - 1); i++) { |
120 | dma_phy += sizeof(struct dma_extended_desc); | |
f8be0d78 | 121 | p->basic.des3 = cpu_to_le32((unsigned int)dma_phy); |
c24602ef GC |
122 | p++; |
123 | } | |
f8be0d78 | 124 | p->basic.des3 = cpu_to_le32((unsigned int)phy_addr); |
c24602ef GC |
125 | |
126 | } else { | |
ceb69499 | 127 | struct dma_desc *p = (struct dma_desc *)des; |
c24602ef GC |
128 | for (i = 0; i < (size - 1); i++) { |
129 | dma_phy += sizeof(struct dma_desc); | |
f8be0d78 | 130 | p->des3 = cpu_to_le32((unsigned int)dma_phy); |
c24602ef GC |
131 | p++; |
132 | } | |
f8be0d78 | 133 | p->des3 = cpu_to_le32((unsigned int)phy_addr); |
286a8372 | 134 | } |
286a8372 GC |
135 | } |
136 | ||
891434b1 RK |
137 | static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p) |
138 | { | |
5bacd778 | 139 | struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr; |
891434b1 RK |
140 | |
141 | if (priv->hwts_rx_en && !priv->extend_desc) | |
142 | /* NOTE: Device will overwrite des3 with timestamp value if | |
143 | * 1588-2002 time stamping is enabled, hence reinitialize it | |
144 | * to keep explicit chaining in the descriptor. | |
145 | */ | |
5bacd778 LC |
146 | p->des3 = cpu_to_le32((unsigned int)(priv->dma_rx_phy + |
147 | (((priv->dirty_rx) + 1) % | |
f8be0d78 MW |
148 | DMA_RX_SIZE) * |
149 | sizeof(struct dma_desc))); | |
891434b1 RK |
150 | } |
151 | ||
152 | static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p) | |
153 | { | |
5bacd778 LC |
154 | struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr; |
155 | unsigned int entry = priv->dirty_tx; | |
891434b1 | 156 | |
5bacd778 | 157 | if (priv->tx_skbuff_dma[entry].last_segment && !priv->extend_desc && |
96951366 | 158 | priv->hwts_tx_en) |
891434b1 RK |
159 | /* NOTE: Device will overwrite des3 with timestamp value if |
160 | * 1588-2002 time stamping is enabled, hence reinitialize it | |
161 | * to keep explicit chaining in the descriptor. | |
162 | */ | |
5bacd778 LC |
163 | p->des3 = cpu_to_le32((unsigned int)((priv->dma_tx_phy + |
164 | ((priv->dirty_tx + 1) % DMA_TX_SIZE)) | |
f8be0d78 | 165 | * sizeof(struct dma_desc))); |
891434b1 RK |
166 | } |
167 | ||
29896a67 | 168 | const struct stmmac_mode_ops chain_mode_ops = { |
c24602ef | 169 | .init = stmmac_init_dma_chain, |
286a8372 GC |
170 | .is_jumbo_frm = stmmac_is_jumbo_frm, |
171 | .jumbo_frm = stmmac_jumbo_frm, | |
891434b1 RK |
172 | .refill_desc3 = stmmac_refill_desc3, |
173 | .clean_desc3 = stmmac_clean_desc3, | |
286a8372 | 174 | }; |