diff options
Diffstat (limited to 'drivers/net/ethernet/altera/altera_sgdma.c')
-rw-r--r-- | drivers/net/ethernet/altera/altera_sgdma.c | 179 |
1 files changed, 106 insertions, 73 deletions
diff --git a/drivers/net/ethernet/altera/altera_sgdma.c b/drivers/net/ethernet/altera/altera_sgdma.c index 0ee96639ae44..9ce8630692b6 100644 --- a/drivers/net/ethernet/altera/altera_sgdma.c +++ b/drivers/net/ethernet/altera/altera_sgdma.c | |||
@@ -20,15 +20,15 @@ | |||
20 | #include "altera_sgdmahw.h" | 20 | #include "altera_sgdmahw.h" |
21 | #include "altera_sgdma.h" | 21 | #include "altera_sgdma.h" |
22 | 22 | ||
23 | static void sgdma_descrip(struct sgdma_descrip *desc, | 23 | static void sgdma_setup_descrip(struct sgdma_descrip *desc, |
24 | struct sgdma_descrip *ndesc, | 24 | struct sgdma_descrip *ndesc, |
25 | dma_addr_t ndesc_phys, | 25 | dma_addr_t ndesc_phys, |
26 | dma_addr_t raddr, | 26 | dma_addr_t raddr, |
27 | dma_addr_t waddr, | 27 | dma_addr_t waddr, |
28 | u16 length, | 28 | u16 length, |
29 | int generate_eop, | 29 | int generate_eop, |
30 | int rfixed, | 30 | int rfixed, |
31 | int wfixed); | 31 | int wfixed); |
32 | 32 | ||
33 | static int sgdma_async_write(struct altera_tse_private *priv, | 33 | static int sgdma_async_write(struct altera_tse_private *priv, |
34 | struct sgdma_descrip *desc); | 34 | struct sgdma_descrip *desc); |
@@ -64,11 +64,15 @@ queue_rx_peekhead(struct altera_tse_private *priv); | |||
64 | 64 | ||
65 | int sgdma_initialize(struct altera_tse_private *priv) | 65 | int sgdma_initialize(struct altera_tse_private *priv) |
66 | { | 66 | { |
67 | priv->txctrlreg = SGDMA_CTRLREG_ILASTD; | 67 | priv->txctrlreg = SGDMA_CTRLREG_ILASTD | |
68 | SGDMA_CTRLREG_INTEN; | ||
68 | 69 | ||
69 | priv->rxctrlreg = SGDMA_CTRLREG_IDESCRIP | | 70 | priv->rxctrlreg = SGDMA_CTRLREG_IDESCRIP | |
71 | SGDMA_CTRLREG_INTEN | | ||
70 | SGDMA_CTRLREG_ILASTD; | 72 | SGDMA_CTRLREG_ILASTD; |
71 | 73 | ||
74 | priv->sgdmadesclen = sizeof(struct sgdma_descrip); | ||
75 | |||
72 | INIT_LIST_HEAD(&priv->txlisthd); | 76 | INIT_LIST_HEAD(&priv->txlisthd); |
73 | INIT_LIST_HEAD(&priv->rxlisthd); | 77 | INIT_LIST_HEAD(&priv->rxlisthd); |
74 | 78 | ||
@@ -93,6 +97,16 @@ int sgdma_initialize(struct altera_tse_private *priv) | |||
93 | return -EINVAL; | 97 | return -EINVAL; |
94 | } | 98 | } |
95 | 99 | ||
100 | /* Initialize descriptor memory to all 0's, sync memory to cache */ | ||
101 | memset(priv->tx_dma_desc, 0, priv->txdescmem); | ||
102 | memset(priv->rx_dma_desc, 0, priv->rxdescmem); | ||
103 | |||
104 | dma_sync_single_for_device(priv->device, priv->txdescphys, | ||
105 | priv->txdescmem, DMA_TO_DEVICE); | ||
106 | |||
107 | dma_sync_single_for_device(priv->device, priv->rxdescphys, | ||
108 | priv->rxdescmem, DMA_TO_DEVICE); | ||
109 | |||
96 | return 0; | 110 | return 0; |
97 | } | 111 | } |
98 | 112 | ||
@@ -130,26 +144,23 @@ void sgdma_reset(struct altera_tse_private *priv) | |||
130 | iowrite32(0, &prxsgdma->control); | 144 | iowrite32(0, &prxsgdma->control); |
131 | } | 145 | } |
132 | 146 | ||
147 | /* For SGDMA, interrupts remain enabled after initially enabling, | ||
148 | * so no need to provide implementations for abstract enable | ||
149 | * and disable | ||
150 | */ | ||
151 | |||
133 | void sgdma_enable_rxirq(struct altera_tse_private *priv) | 152 | void sgdma_enable_rxirq(struct altera_tse_private *priv) |
134 | { | 153 | { |
135 | struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr; | ||
136 | priv->rxctrlreg |= SGDMA_CTRLREG_INTEN; | ||
137 | tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN); | ||
138 | } | 154 | } |
139 | 155 | ||
140 | void sgdma_enable_txirq(struct altera_tse_private *priv) | 156 | void sgdma_enable_txirq(struct altera_tse_private *priv) |
141 | { | 157 | { |
142 | struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr; | ||
143 | priv->txctrlreg |= SGDMA_CTRLREG_INTEN; | ||
144 | tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN); | ||
145 | } | 158 | } |
146 | 159 | ||
147 | /* for SGDMA, RX interrupts remain enabled after enabling */ | ||
148 | void sgdma_disable_rxirq(struct altera_tse_private *priv) | 160 | void sgdma_disable_rxirq(struct altera_tse_private *priv) |
149 | { | 161 | { |
150 | } | 162 | } |
151 | 163 | ||
152 | /* for SGDMA, TX interrupts remain enabled after enabling */ | ||
153 | void sgdma_disable_txirq(struct altera_tse_private *priv) | 164 | void sgdma_disable_txirq(struct altera_tse_private *priv) |
154 | { | 165 | { |
155 | } | 166 | } |
@@ -184,15 +195,15 @@ int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer) | |||
184 | if (sgdma_txbusy(priv)) | 195 | if (sgdma_txbusy(priv)) |
185 | return 0; | 196 | return 0; |
186 | 197 | ||
187 | sgdma_descrip(cdesc, /* current descriptor */ | 198 | sgdma_setup_descrip(cdesc, /* current descriptor */ |
188 | ndesc, /* next descriptor */ | 199 | ndesc, /* next descriptor */ |
189 | sgdma_txphysaddr(priv, ndesc), | 200 | sgdma_txphysaddr(priv, ndesc), |
190 | buffer->dma_addr, /* address of packet to xmit */ | 201 | buffer->dma_addr, /* address of packet to xmit */ |
191 | 0, /* write addr 0 for tx dma */ | 202 | 0, /* write addr 0 for tx dma */ |
192 | buffer->len, /* length of packet */ | 203 | buffer->len, /* length of packet */ |
193 | SGDMA_CONTROL_EOP, /* Generate EOP */ | 204 | SGDMA_CONTROL_EOP, /* Generate EOP */ |
194 | 0, /* read fixed */ | 205 | 0, /* read fixed */ |
195 | SGDMA_CONTROL_WR_FIXED); /* Generate SOP */ | 206 | SGDMA_CONTROL_WR_FIXED); /* Generate SOP */ |
196 | 207 | ||
197 | pktstx = sgdma_async_write(priv, cdesc); | 208 | pktstx = sgdma_async_write(priv, cdesc); |
198 | 209 | ||
@@ -219,11 +230,15 @@ u32 sgdma_tx_completions(struct altera_tse_private *priv) | |||
219 | return ready; | 230 | return ready; |
220 | } | 231 | } |
221 | 232 | ||
222 | int sgdma_add_rx_desc(struct altera_tse_private *priv, | 233 | void sgdma_start_rxdma(struct altera_tse_private *priv) |
223 | struct tse_buffer *rxbuffer) | 234 | { |
235 | sgdma_async_read(priv); | ||
236 | } | ||
237 | |||
238 | void sgdma_add_rx_desc(struct altera_tse_private *priv, | ||
239 | struct tse_buffer *rxbuffer) | ||
224 | { | 240 | { |
225 | queue_rx(priv, rxbuffer); | 241 | queue_rx(priv, rxbuffer); |
226 | return sgdma_async_read(priv); | ||
227 | } | 242 | } |
228 | 243 | ||
229 | /* status is returned on upper 16 bits, | 244 | /* status is returned on upper 16 bits, |
@@ -240,28 +255,52 @@ u32 sgdma_rx_status(struct altera_tse_private *priv) | |||
240 | unsigned int pktstatus = 0; | 255 | unsigned int pktstatus = 0; |
241 | struct tse_buffer *rxbuffer = NULL; | 256 | struct tse_buffer *rxbuffer = NULL; |
242 | 257 | ||
243 | dma_sync_single_for_cpu(priv->device, | 258 | u32 sts = ioread32(&csr->status); |
244 | priv->rxdescphys, | ||
245 | priv->rxdescmem, | ||
246 | DMA_BIDIRECTIONAL); | ||
247 | 259 | ||
248 | desc = &base[0]; | 260 | desc = &base[0]; |
249 | if ((ioread32(&csr->status) & SGDMA_STSREG_EOP) || | 261 | if (sts & SGDMA_STSREG_EOP) { |
250 | (desc->status & SGDMA_STATUS_EOP)) { | 262 | dma_sync_single_for_cpu(priv->device, |
263 | priv->rxdescphys, | ||
264 | priv->sgdmadesclen, | ||
265 | DMA_FROM_DEVICE); | ||
266 | |||
251 | pktlength = desc->bytes_xferred; | 267 | pktlength = desc->bytes_xferred; |
252 | pktstatus = desc->status & 0x3f; | 268 | pktstatus = desc->status & 0x3f; |
253 | rxstatus = pktstatus; | 269 | rxstatus = pktstatus; |
254 | rxstatus = rxstatus << 16; | 270 | rxstatus = rxstatus << 16; |
255 | rxstatus |= (pktlength & 0xffff); | 271 | rxstatus |= (pktlength & 0xffff); |
256 | 272 | ||
257 | desc->status = 0; | 273 | if (rxstatus) { |
274 | desc->status = 0; | ||
258 | 275 | ||
259 | rxbuffer = dequeue_rx(priv); | 276 | rxbuffer = dequeue_rx(priv); |
260 | if (rxbuffer == NULL) | 277 | if (rxbuffer == NULL) |
261 | netdev_err(priv->dev, | 278 | netdev_info(priv->dev, |
262 | "sgdma rx and rx queue empty!\n"); | 279 | "sgdma rx and rx queue empty!\n"); |
280 | |||
281 | /* Clear control */ | ||
282 | iowrite32(0, &csr->control); | ||
283 | /* clear status */ | ||
284 | iowrite32(0xf, &csr->status); | ||
263 | 285 | ||
264 | /* kick the rx sgdma after reaping this descriptor */ | 286 | /* kick the rx sgdma after reaping this descriptor */ |
287 | pktsrx = sgdma_async_read(priv); | ||
288 | |||
289 | } else { | ||
290 | /* If the SGDMA indicated an end of packet on recv, | ||
291 | * then it's expected that the rxstatus from the | ||
292 | * descriptor is non-zero - meaning a valid packet | ||
293 | * with a nonzero length, or an error has been | ||
294 | * indicated. if not, then all we can do is signal | ||
295 | * an error and return no packet received. Most likely | ||
296 | * there is a system design error, or an error in the | ||
297 | * underlying kernel (cache or cache management problem) | ||
298 | */ | ||
299 | netdev_err(priv->dev, | ||
300 | "SGDMA RX Error Info: %x, %x, %x\n", | ||
301 | sts, desc->status, rxstatus); | ||
302 | } | ||
303 | } else if (sts == 0) { | ||
265 | pktsrx = sgdma_async_read(priv); | 304 | pktsrx = sgdma_async_read(priv); |
266 | } | 305 | } |
267 | 306 | ||
@@ -270,15 +309,15 @@ u32 sgdma_rx_status(struct altera_tse_private *priv) | |||
270 | 309 | ||
271 | 310 | ||
272 | /* Private functions */ | 311 | /* Private functions */ |
273 | static void sgdma_descrip(struct sgdma_descrip *desc, | 312 | static void sgdma_setup_descrip(struct sgdma_descrip *desc, |
274 | struct sgdma_descrip *ndesc, | 313 | struct sgdma_descrip *ndesc, |
275 | dma_addr_t ndesc_phys, | 314 | dma_addr_t ndesc_phys, |
276 | dma_addr_t raddr, | 315 | dma_addr_t raddr, |
277 | dma_addr_t waddr, | 316 | dma_addr_t waddr, |
278 | u16 length, | 317 | u16 length, |
279 | int generate_eop, | 318 | int generate_eop, |
280 | int rfixed, | 319 | int rfixed, |
281 | int wfixed) | 320 | int wfixed) |
282 | { | 321 | { |
283 | /* Clear the next descriptor as not owned by hardware */ | 322 | /* Clear the next descriptor as not owned by hardware */ |
284 | u32 ctrl = ndesc->control; | 323 | u32 ctrl = ndesc->control; |
@@ -319,35 +358,29 @@ static int sgdma_async_read(struct altera_tse_private *priv) | |||
319 | struct sgdma_descrip *cdesc = &descbase[0]; | 358 | struct sgdma_descrip *cdesc = &descbase[0]; |
320 | struct sgdma_descrip *ndesc = &descbase[1]; | 359 | struct sgdma_descrip *ndesc = &descbase[1]; |
321 | 360 | ||
322 | unsigned int sts = ioread32(&csr->status); | ||
323 | struct tse_buffer *rxbuffer = NULL; | 361 | struct tse_buffer *rxbuffer = NULL; |
324 | 362 | ||
325 | if (!sgdma_rxbusy(priv)) { | 363 | if (!sgdma_rxbusy(priv)) { |
326 | rxbuffer = queue_rx_peekhead(priv); | 364 | rxbuffer = queue_rx_peekhead(priv); |
327 | if (rxbuffer == NULL) | 365 | if (rxbuffer == NULL) { |
366 | netdev_err(priv->dev, "no rx buffers available\n"); | ||
328 | return 0; | 367 | return 0; |
329 | 368 | } | |
330 | sgdma_descrip(cdesc, /* current descriptor */ | 369 | |
331 | ndesc, /* next descriptor */ | 370 | sgdma_setup_descrip(cdesc, /* current descriptor */ |
332 | sgdma_rxphysaddr(priv, ndesc), | 371 | ndesc, /* next descriptor */ |
333 | 0, /* read addr 0 for rx dma */ | 372 | sgdma_rxphysaddr(priv, ndesc), |
334 | rxbuffer->dma_addr, /* write addr for rx dma */ | 373 | 0, /* read addr 0 for rx dma */ |
335 | 0, /* read 'til EOP */ | 374 | rxbuffer->dma_addr, /* write addr for rx dma */ |
336 | 0, /* EOP: NA for rx dma */ | 375 | 0, /* read 'til EOP */ |
337 | 0, /* read fixed: NA for rx dma */ | 376 | 0, /* EOP: NA for rx dma */ |
338 | 0); /* SOP: NA for rx DMA */ | 377 | 0, /* read fixed: NA for rx dma */ |
339 | 378 | 0); /* SOP: NA for rx DMA */ | |
340 | /* clear control and status */ | ||
341 | iowrite32(0, &csr->control); | ||
342 | |||
343 | /* If status available, clear those bits */ | ||
344 | if (sts & 0xf) | ||
345 | iowrite32(0xf, &csr->status); | ||
346 | 379 | ||
347 | dma_sync_single_for_device(priv->device, | 380 | dma_sync_single_for_device(priv->device, |
348 | priv->rxdescphys, | 381 | priv->rxdescphys, |
349 | priv->rxdescmem, | 382 | priv->sgdmadesclen, |
350 | DMA_BIDIRECTIONAL); | 383 | DMA_TO_DEVICE); |
351 | 384 | ||
352 | iowrite32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)), | 385 | iowrite32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)), |
353 | &csr->next_descrip); | 386 | &csr->next_descrip); |
@@ -374,7 +407,7 @@ static int sgdma_async_write(struct altera_tse_private *priv, | |||
374 | iowrite32(0x1f, &csr->status); | 407 | iowrite32(0x1f, &csr->status); |
375 | 408 | ||
376 | dma_sync_single_for_device(priv->device, priv->txdescphys, | 409 | dma_sync_single_for_device(priv->device, priv->txdescphys, |
377 | priv->txdescmem, DMA_TO_DEVICE); | 410 | priv->sgdmadesclen, DMA_TO_DEVICE); |
378 | 411 | ||
379 | iowrite32(lower_32_bits(sgdma_txphysaddr(priv, desc)), | 412 | iowrite32(lower_32_bits(sgdma_txphysaddr(priv, desc)), |
380 | &csr->next_descrip); | 413 | &csr->next_descrip); |