1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include "stmmac.h"
30
31static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
32{
33 struct stmmac_priv *priv = (struct stmmac_priv *)p;
34 unsigned int txsize = priv->dma_tx_size;
35 unsigned int entry = priv->cur_tx % txsize;
36 struct dma_desc *desc = priv->dma_tx + entry;
37 unsigned int nopaged_len = skb_headlen(skb);
38 unsigned int bmax;
39 unsigned int i = 1, len;
40
41 if (priv->plat->enh_desc)
42 bmax = BUF_SIZE_8KiB;
43 else
44 bmax = BUF_SIZE_2KiB;
45
46 len = nopaged_len - bmax;
47
48 desc->des2 = dma_map_single(priv->device, skb->data,
49 bmax, DMA_TO_DEVICE);
50 if (dma_mapping_error(priv->device, desc->des2))
51 return -1;
52 priv->tx_skbuff_dma[entry].buf = desc->des2;
53 priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
54
55 while (len != 0) {
56 priv->tx_skbuff[entry] = NULL;
57 entry = (++priv->cur_tx) % txsize;
58 desc = priv->dma_tx + entry;
59
60 if (len > bmax) {
61 desc->des2 = dma_map_single(priv->device,
62 (skb->data + bmax * i),
63 bmax, DMA_TO_DEVICE);
64 if (dma_mapping_error(priv->device, desc->des2))
65 return -1;
66 priv->tx_skbuff_dma[entry].buf = desc->des2;
67 priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
68 STMMAC_CHAIN_MODE);
69 priv->hw->desc->set_tx_owner(desc);
70 len -= bmax;
71 i++;
72 } else {
73 desc->des2 = dma_map_single(priv->device,
74 (skb->data + bmax * i), len,
75 DMA_TO_DEVICE);
76 if (dma_mapping_error(priv->device, desc->des2))
77 return -1;
78 priv->tx_skbuff_dma[entry].buf = desc->des2;
79 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
80 STMMAC_CHAIN_MODE);
81 priv->hw->desc->set_tx_owner(desc);
82 len = 0;
83 }
84 }
85 return entry;
86}
87
88static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
89{
90 unsigned int ret = 0;
91
92 if ((enh_desc && (len > BUF_SIZE_8KiB)) ||
93 (!enh_desc && (len > BUF_SIZE_2KiB))) {
94 ret = 1;
95 }
96
97 return ret;
98}
99
100static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
101 unsigned int size, unsigned int extend_desc)
102{
103
104
105
106
107 int i;
108 dma_addr_t dma_phy = phy_addr;
109
110 if (extend_desc) {
111 struct dma_extended_desc *p = (struct dma_extended_desc *)des;
112 for (i = 0; i < (size - 1); i++) {
113 dma_phy += sizeof(struct dma_extended_desc);
114 p->basic.des3 = (unsigned int)dma_phy;
115 p++;
116 }
117 p->basic.des3 = (unsigned int)phy_addr;
118
119 } else {
120 struct dma_desc *p = (struct dma_desc *)des;
121 for (i = 0; i < (size - 1); i++) {
122 dma_phy += sizeof(struct dma_desc);
123 p->des3 = (unsigned int)dma_phy;
124 p++;
125 }
126 p->des3 = (unsigned int)phy_addr;
127 }
128}
129
130static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
131{
132 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
133
134 if (priv->hwts_rx_en && !priv->extend_desc)
135
136
137
138
139 p->des3 = (unsigned int)(priv->dma_rx_phy +
140 (((priv->dirty_rx) + 1) %
141 priv->dma_rx_size) *
142 sizeof(struct dma_desc));
143}
144
145static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
146{
147 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
148
149 if (priv->hw->desc->get_tx_ls(p) && !priv->extend_desc)
150
151
152
153
154 p->des3 = (unsigned int)(priv->dma_tx_phy +
155 (((priv->dirty_tx + 1) %
156 priv->dma_tx_size) *
157 sizeof(struct dma_desc)));
158}
159
160const struct stmmac_mode_ops chain_mode_ops = {
161 .init = stmmac_init_dma_chain,
162 .is_jumbo_frm = stmmac_is_jumbo_frm,
163 .jumbo_frm = stmmac_jumbo_frm,
164 .refill_desc3 = stmmac_refill_desc3,
165 .clean_desc3 = stmmac_clean_desc3,
166};
167