aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ks8842.c464
-rw-r--r--include/linux/ks8842.h4
2 files changed, 447 insertions, 21 deletions
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index 289b0bee3462..3fe38c787f29 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -30,6 +30,9 @@
30#include <linux/etherdevice.h> 30#include <linux/etherdevice.h>
31#include <linux/ethtool.h> 31#include <linux/ethtool.h>
32#include <linux/ks8842.h> 32#include <linux/ks8842.h>
33#include <linux/dmaengine.h>
34#include <linux/dma-mapping.h>
35#include <linux/scatterlist.h>
33 36
34#define DRV_NAME "ks8842" 37#define DRV_NAME "ks8842"
35 38
@@ -82,6 +85,15 @@
82#define IRQ_RX_ERROR 0x0080 85#define IRQ_RX_ERROR 0x0080
83#define ENABLED_IRQS (IRQ_LINK_CHANGE | IRQ_TX | IRQ_RX | IRQ_RX_STOPPED | \ 86#define ENABLED_IRQS (IRQ_LINK_CHANGE | IRQ_TX | IRQ_RX | IRQ_RX_STOPPED | \
84 IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR) 87 IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR)
88/* When running via timberdale in DMA mode, the RX interrupt should be
89 enabled in the KS8842, but not in the FPGA IP, since the IP handles
90 RX DMA internally.
91 TX interrupts are not needed it is handled by the FPGA the driver is
92 notified via DMA callbacks.
93*/
94#define ENABLED_IRQS_DMA_IP (IRQ_LINK_CHANGE | IRQ_RX_STOPPED | \
95 IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR)
96#define ENABLED_IRQS_DMA (ENABLED_IRQS_DMA_IP | IRQ_RX)
85#define REG_ISR 0x02 97#define REG_ISR 0x02
86#define REG_RXSR 0x04 98#define REG_RXSR 0x04
87#define RXSR_VALID 0x8000 99#define RXSR_VALID 0x8000
@@ -124,6 +136,28 @@
124#define MICREL_KS884X 0x01 /* 0=Timeberdale(FPGA), 1=Micrel */ 136#define MICREL_KS884X 0x01 /* 0=Timeberdale(FPGA), 1=Micrel */
125#define KS884X_16BIT 0x02 /* 1=16bit, 0=32bit */ 137#define KS884X_16BIT 0x02 /* 1=16bit, 0=32bit */
126 138
139#define DMA_BUFFER_SIZE 2048
140
141struct ks8842_tx_dma_ctl {
142 struct dma_chan *chan;
143 struct dma_async_tx_descriptor *adesc;
144 void *buf;
145 struct scatterlist sg;
146 int channel;
147};
148
149struct ks8842_rx_dma_ctl {
150 struct dma_chan *chan;
151 struct dma_async_tx_descriptor *adesc;
152 struct sk_buff *skb;
153 struct scatterlist sg;
154 struct tasklet_struct tasklet;
155 int channel;
156};
157
158#define KS8842_USE_DMA(adapter) (((adapter)->dma_tx.channel != -1) && \
159 ((adapter)->dma_rx.channel != -1))
160
127struct ks8842_adapter { 161struct ks8842_adapter {
128 void __iomem *hw_addr; 162 void __iomem *hw_addr;
129 int irq; 163 int irq;
@@ -132,8 +166,19 @@ struct ks8842_adapter {
132 spinlock_t lock; /* spinlock to be interrupt safe */ 166 spinlock_t lock; /* spinlock to be interrupt safe */
133 struct work_struct timeout_work; 167 struct work_struct timeout_work;
134 struct net_device *netdev; 168 struct net_device *netdev;
169 struct device *dev;
170 struct ks8842_tx_dma_ctl dma_tx;
171 struct ks8842_rx_dma_ctl dma_rx;
135}; 172};
136 173
174static void ks8842_dma_rx_cb(void *data);
175static void ks8842_dma_tx_cb(void *data);
176
177static inline void ks8842_resume_dma(struct ks8842_adapter *adapter)
178{
179 iowrite32(1, adapter->hw_addr + REQ_TIMB_DMA_RESUME);
180}
181
137static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank) 182static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank)
138{ 183{
139 iowrite16(bank, adapter->hw_addr + REG_SELECT_BANK); 184 iowrite16(bank, adapter->hw_addr + REG_SELECT_BANK);
@@ -297,8 +342,19 @@ static void ks8842_reset_hw(struct ks8842_adapter *adapter)
297 ks8842_write16(adapter, 18, 0xffff, REG_ISR); 342 ks8842_write16(adapter, 18, 0xffff, REG_ISR);
298 343
299 /* enable interrupts */ 344 /* enable interrupts */
300 ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); 345 if (KS8842_USE_DMA(adapter)) {
301 346 /* When running in DMA Mode the RX interrupt is not enabled in
347 timberdale because RX data is received by DMA callbacks
348 it must still be enabled in the KS8842 because it indicates
349 to timberdale when there is RX data for it's DMA FIFOs */
350 iowrite16(ENABLED_IRQS_DMA_IP, adapter->hw_addr + REG_TIMB_IER);
351 ks8842_write16(adapter, 18, ENABLED_IRQS_DMA, REG_IER);
352 } else {
353 if (!(adapter->conf_flags & MICREL_KS884X))
354 iowrite16(ENABLED_IRQS,
355 adapter->hw_addr + REG_TIMB_IER);
356 ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER);
357 }
302 /* enable the switch */ 358 /* enable the switch */
303 ks8842_write16(adapter, 32, 0x1, REG_SW_ID_AND_ENABLE); 359 ks8842_write16(adapter, 32, 0x1, REG_SW_ID_AND_ENABLE);
304} 360}
@@ -371,6 +427,53 @@ static inline u16 ks8842_tx_fifo_space(struct ks8842_adapter *adapter)
371 return ks8842_read16(adapter, 16, REG_TXMIR) & 0x1fff; 427 return ks8842_read16(adapter, 16, REG_TXMIR) & 0x1fff;
372} 428}
373 429
430static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev)
431{
432 struct ks8842_adapter *adapter = netdev_priv(netdev);
433 struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx;
434 u8 *buf = ctl->buf;
435
436 if (ctl->adesc) {
437 netdev_dbg(netdev, "%s: TX ongoing\n", __func__);
438 /* transfer ongoing */
439 return NETDEV_TX_BUSY;
440 }
441
442 sg_dma_len(&ctl->sg) = skb->len + sizeof(u32);
443
444 /* copy data to the TX buffer */
445 /* the control word, enable IRQ, port 1 and the length */
446 *buf++ = 0x00;
447 *buf++ = 0x01; /* Port 1 */
448 *buf++ = skb->len & 0xff;
449 *buf++ = (skb->len >> 8) & 0xff;
450 skb_copy_from_linear_data(skb, buf, skb->len);
451
452 dma_sync_single_range_for_device(adapter->dev,
453 sg_dma_address(&ctl->sg), 0, sg_dma_len(&ctl->sg),
454 DMA_TO_DEVICE);
455
456 /* make sure the length is a multiple of 4 */
457 if (sg_dma_len(&ctl->sg) % 4)
458 sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4;
459
460 ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan,
461 &ctl->sg, 1, DMA_TO_DEVICE,
462 DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
463 if (!ctl->adesc)
464 return NETDEV_TX_BUSY;
465
466 ctl->adesc->callback_param = netdev;
467 ctl->adesc->callback = ks8842_dma_tx_cb;
468 ctl->adesc->tx_submit(ctl->adesc);
469
470 netdev->stats.tx_bytes += skb->len;
471
472 dev_kfree_skb(skb);
473
474 return NETDEV_TX_OK;
475}
476
374static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev) 477static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
375{ 478{
376 struct ks8842_adapter *adapter = netdev_priv(netdev); 479 struct ks8842_adapter *adapter = netdev_priv(netdev);
@@ -422,6 +525,121 @@ static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
422 return NETDEV_TX_OK; 525 return NETDEV_TX_OK;
423} 526}
424 527
528static void ks8842_update_rx_err_counters(struct net_device *netdev, u32 status)
529{
530 netdev_dbg(netdev, "RX error, status: %x\n", status);
531
532 netdev->stats.rx_errors++;
533 if (status & RXSR_TOO_LONG)
534 netdev->stats.rx_length_errors++;
535 if (status & RXSR_CRC_ERROR)
536 netdev->stats.rx_crc_errors++;
537 if (status & RXSR_RUNT)
538 netdev->stats.rx_frame_errors++;
539}
540
541static void ks8842_update_rx_counters(struct net_device *netdev, u32 status,
542 int len)
543{
544 netdev_dbg(netdev, "RX packet, len: %d\n", len);
545
546 netdev->stats.rx_packets++;
547 netdev->stats.rx_bytes += len;
548 if (status & RXSR_MULTICAST)
549 netdev->stats.multicast++;
550}
551
552static int __ks8842_start_new_rx_dma(struct net_device *netdev)
553{
554 struct ks8842_adapter *adapter = netdev_priv(netdev);
555 struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx;
556 struct scatterlist *sg = &ctl->sg;
557 int err;
558
559 ctl->skb = netd