1b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* 2a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors * ks8842.c timberdale KS8842 ethernet driver 3b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * Copyright (c) 2009 Intel Corporation 4b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * 5b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * This program is free software; you can redistribute it and/or modify 6b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * it under the terms of the GNU General Public License version 2 as 7b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * published by the Free Software Foundation. 8b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * 9b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * This program is distributed in the hope that it will be useful, 10b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * but WITHOUT ANY WARRANTY; without even the implied warranty of 11b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * GNU General Public License for more details. 13b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * 14b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * You should have received a copy of the GNU General Public License 15b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * along with this program; if not, write to the Free Software 16b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors */ 18b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 19b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* Supports: 20b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors * The Micrel KS8842 behind the timberdale FPGA 2128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi * The genuine Micrel KS8841/42 device with ISA 16/32bit bus interface 22b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors */ 23b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 240dc7d2b3cbfcf4ff20bdc68f563a2e52e6a2178fJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 250dc7d2b3cbfcf4ff20bdc68f563a2e52e6a2178fJoe Perches 26a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/interrupt.h> 27b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#include <linux/kernel.h> 28b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#include <linux/module.h> 29b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#include <linux/platform_device.h> 30b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#include <linux/netdevice.h> 31b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#include <linux/etherdevice.h> 32b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#include <linux/ethtool.h> 33a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors#include <linux/ks8842.h> 3494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors#include <linux/dmaengine.h> 3594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors#include <linux/dma-mapping.h> 3694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors#include <linux/scatterlist.h> 37b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 38b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define DRV_NAME "ks8842" 39b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 40b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* Timberdale specific Registers */ 41db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors#define REG_TIMB_RST 0x1c 42db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors#define REG_TIMB_FIFO 0x20 43db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors#define REG_TIMB_ISR 0x24 44db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors#define REG_TIMB_IER 0x28 45db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors#define REG_TIMB_IAR 0x2C 46db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors#define REQ_TIMB_DMA_RESUME 0x30 47b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 48b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* KS8842 registers */ 49b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 50b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_SELECT_BANK 0x0e 51b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 52b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 0 registers */ 53b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_QRFCR 0x04 54b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 55b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 2 registers */ 56b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_MARL 0x00 57b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_MARM 0x02 58b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_MARH 0x04 59b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 60b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 3 registers */ 61b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_GRR 0x06 62b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 63b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 16 registers */ 64b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_TXCR 0x00 65b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_TXSR 0x02 66b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_RXCR 0x04 67b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_TXMIR 0x08 68b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_RXMIR 0x0A 69b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 70b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 17 registers */ 71b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_TXQCR 0x00 72b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_RXQCR 0x02 73b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_TXFDPR 0x04 74b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_RXFDPR 0x06 75b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_QMU_DATA_LO 0x08 76b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_QMU_DATA_HI 0x0A 77b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 78b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 18 registers */ 79b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_IER 0x00 80b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define IRQ_LINK_CHANGE 0x8000 81b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define IRQ_TX 0x4000 82b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define IRQ_RX 0x2000 83b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define IRQ_RX_OVERRUN 0x0800 84b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define IRQ_TX_STOPPED 0x0200 85b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define IRQ_RX_STOPPED 0x0100 86b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define IRQ_RX_ERROR 0x0080 87b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define ENABLED_IRQS (IRQ_LINK_CHANGE | IRQ_TX | IRQ_RX | IRQ_RX_STOPPED | \ 88b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR) 8994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors/* When running via timberdale in DMA mode, the RX interrupt should be 9094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors enabled in the KS8842, but not in the FPGA IP, since the IP handles 9194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors RX DMA internally. 9294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors TX interrupts are not needed it is handled by the FPGA the driver is 9394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors notified via DMA callbacks. 9494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors*/ 9594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors#define ENABLED_IRQS_DMA_IP (IRQ_LINK_CHANGE | IRQ_RX_STOPPED | \ 9694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR) 9794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors#define ENABLED_IRQS_DMA (ENABLED_IRQS_DMA_IP | IRQ_RX) 98b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_ISR 0x02 99b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_RXSR 0x04 100b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define RXSR_VALID 0x8000 101b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define RXSR_BROADCAST 0x80 102b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define RXSR_MULTICAST 0x40 103b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define RXSR_UNICAST 0x20 104b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define RXSR_FRAMETYPE 0x08 105b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define RXSR_TOO_LONG 0x04 106b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define RXSR_RUNT 0x02 107b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define RXSR_CRC_ERROR 0x01 108b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define RXSR_ERROR (RXSR_TOO_LONG | RXSR_RUNT | RXSR_CRC_ERROR) 109b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 110b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 32 registers */ 111b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_SW_ID_AND_ENABLE 0x00 112b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_SGCR1 0x02 113b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_SGCR2 0x04 114b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_SGCR3 0x06 115b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 116b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 39 registers */ 117b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_MACAR1 0x00 118b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_MACAR2 0x02 119b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_MACAR3 0x04 120b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 121b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 45 registers */ 122b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_P1MBCR 0x00 123b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_P1MBSR 0x02 124b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 125b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 46 registers */ 126b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_P2MBCR 0x00 127b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_P2MBSR 0x02 128b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 129b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 48 registers */ 130b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_P1CR2 0x02 131b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 132b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* bank 49 registers */ 133b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_P1CR4 0x02 134b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors#define REG_P1SR 0x04 135b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 13628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi/* flags passed by platform_device for configuration */ 13728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi#define MICREL_KS884X 0x01 /* 0=Timeberdale(FPGA), 1=Micrel */ 13828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi#define KS884X_16BIT 0x02 /* 1=16bit, 0=32bit */ 13928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 14094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors#define DMA_BUFFER_SIZE 2048 14194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 14294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstruct ks8842_tx_dma_ctl { 14394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct dma_chan *chan; 14494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct dma_async_tx_descriptor *adesc; 14594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors void *buf; 14694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct scatterlist sg; 14794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors int channel; 14894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors}; 14994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 15094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstruct ks8842_rx_dma_ctl { 15194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct dma_chan *chan; 15294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct dma_async_tx_descriptor *adesc; 15394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct sk_buff *skb; 15494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct scatterlist sg; 15594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct tasklet_struct tasklet; 15694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors int channel; 15794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors}; 15894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 15994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors#define KS8842_USE_DMA(adapter) (((adapter)->dma_tx.channel != -1) && \ 16094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ((adapter)->dma_rx.channel != -1)) 16194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 162b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstruct ks8842_adapter { 163b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors void __iomem *hw_addr; 164b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors int irq; 16528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi unsigned long conf_flags; /* copy of platform_device config */ 166b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct tasklet_struct tasklet; 167b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors spinlock_t lock; /* spinlock to be interrupt safe */ 168cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors struct work_struct timeout_work; 169cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors struct net_device *netdev; 17094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct device *dev; 17194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_tx_dma_ctl dma_tx; 17294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_rx_dma_ctl dma_rx; 173b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors}; 174b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 17594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic void ks8842_dma_rx_cb(void *data); 17694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic void ks8842_dma_tx_cb(void *data); 17794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 17894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic inline void ks8842_resume_dma(struct ks8842_adapter *adapter) 17994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 18094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors iowrite32(1, adapter->hw_addr + REQ_TIMB_DMA_RESUME); 18194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 18294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 183b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank) 184b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 185b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iowrite16(bank, adapter->hw_addr + REG_SELECT_BANK); 186b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 187b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 188b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline void ks8842_write8(struct ks8842_adapter *adapter, u16 bank, 189b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u8 value, int offset) 190b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 191b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_select_bank(adapter, bank); 192b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iowrite8(value, adapter->hw_addr + offset); 193b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 194b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 195b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline void ks8842_write16(struct ks8842_adapter *adapter, u16 bank, 196b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 value, int offset) 197b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 198b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_select_bank(adapter, bank); 199b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iowrite16(value, adapter->hw_addr + offset); 200b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 201b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 202b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline void ks8842_enable_bits(struct ks8842_adapter *adapter, u16 bank, 203b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 bits, int offset) 204b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 205b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 reg; 206b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_select_bank(adapter, bank); 207b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors reg = ioread16(adapter->hw_addr + offset); 208b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors reg |= bits; 209b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iowrite16(reg, adapter->hw_addr + offset); 210b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 211b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 212b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline void ks8842_clear_bits(struct ks8842_adapter *adapter, u16 bank, 213b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 bits, int offset) 214b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 215b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 reg; 216b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_select_bank(adapter, bank); 217b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors reg = ioread16(adapter->hw_addr + offset); 218b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors reg &= ~bits; 219b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iowrite16(reg, adapter->hw_addr + offset); 220b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 221b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 222b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline void ks8842_write32(struct ks8842_adapter *adapter, u16 bank, 223b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u32 value, int offset) 224b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 225b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_select_bank(adapter, bank); 226b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iowrite32(value, adapter->hw_addr + offset); 227b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 228b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 229b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline u8 ks8842_read8(struct ks8842_adapter *adapter, u16 bank, 230b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors int offset) 231b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 232b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_select_bank(adapter, bank); 233b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return ioread8(adapter->hw_addr + offset); 234b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 235b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 236b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline u16 ks8842_read16(struct ks8842_adapter *adapter, u16 bank, 237b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors int offset) 238b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 239b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_select_bank(adapter, bank); 240b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return ioread16(adapter->hw_addr + offset); 241b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 242b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 243b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline u32 ks8842_read32(struct ks8842_adapter *adapter, u16 bank, 244b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors int offset) 245b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 246b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_select_bank(adapter, bank); 247b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return ioread32(adapter->hw_addr + offset); 248b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 249b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 250b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic void ks8842_reset(struct ks8842_adapter *adapter) 251b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 25228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi if (adapter->conf_flags & MICREL_KS884X) { 25328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 3, 1, REG_GRR); 25428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi msleep(10); 25528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi iowrite16(0, adapter->hw_addr + REG_GRR); 25628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } else { 25728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi /* The KS8842 goes haywire when doing softare reset 25828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi * a work around in the timberdale IP is implemented to 25928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi * do a hardware reset instead 26028bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 3, 1, REG_GRR); 26128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi msleep(10); 26228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi iowrite16(0, adapter->hw_addr + REG_GRR); 26328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi */ 26428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi iowrite32(0x1, adapter->hw_addr + REG_TIMB_RST); 26528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi msleep(20); 26628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } 267b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 268b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 269b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic void ks8842_update_link_status(struct net_device *netdev, 270b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter) 271b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 272b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* check the status of the link */ 273b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (ks8842_read16(adapter, 45, REG_P1MBSR) & 0x4) { 274b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netif_carrier_on(netdev); 275b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netif_wake_queue(netdev); 276b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } else { 277b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netif_stop_queue(netdev); 278b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netif_carrier_off(netdev); 279b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } 280b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 281b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 282b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic void ks8842_enable_tx(struct ks8842_adapter *adapter) 283b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 284b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_bits(adapter, 16, 0x01, REG_TXCR); 285b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 286b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 287b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic void ks8842_disable_tx(struct ks8842_adapter *adapter) 288b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 289b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_clear_bits(adapter, 16, 0x01, REG_TXCR); 290b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 291b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 292b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic void ks8842_enable_rx(struct ks8842_adapter *adapter) 293b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 294b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_bits(adapter, 16, 0x01, REG_RXCR); 295b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 296b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 297b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic void ks8842_disable_rx(struct ks8842_adapter *adapter) 298b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 299b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_clear_bits(adapter, 16, 0x01, REG_RXCR); 300b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 301b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 302b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic void ks8842_reset_hw(struct ks8842_adapter *adapter) 303b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 304b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* reset the HW */ 305b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_reset(adapter); 306b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 307b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* Enable QMU Transmit flow control / transmit padding / Transmit CRC */ 308b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 16, 0x000E, REG_TXCR); 309b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 310b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* enable the receiver, uni + multi + broadcast + flow ctrl 311b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors + crc strip */ 312b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 16, 0x8 | 0x20 | 0x40 | 0x80 | 0x400, 313b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors REG_RXCR); 314b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 315b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* TX frame pointer autoincrement */ 316b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 17, 0x4000, REG_TXFDPR); 317b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 318b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* RX frame pointer autoincrement */ 319b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 17, 0x4000, REG_RXFDPR); 320b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 321b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* RX 2 kb high watermark */ 322b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 0, 0x1000, REG_QRFCR); 323b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 32425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* aggressive back off in half duplex */ 325b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_bits(adapter, 32, 1 << 8, REG_SGCR1); 326b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 327b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* enable no excessive collison drop */ 328b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_bits(adapter, 32, 1 << 3, REG_SGCR2); 329b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 330b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* Enable port 1 force flow control / back pressure / transmit / recv */ 331b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 48, 0x1E07, REG_P1CR2); 332b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 333b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* restart port auto-negotiation */ 334b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4); 33528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 336b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* Enable the transmitter */ 337b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_tx(adapter); 338b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 339b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* Enable the receiver */ 340b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_rx(adapter); 341b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 342b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* clear all interrupts */ 343b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 18, 0xffff, REG_ISR); 344b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 345b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* enable interrupts */ 34694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) { 34794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* When running in DMA Mode the RX interrupt is not enabled in 34894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors timberdale because RX data is received by DMA callbacks 34994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors it must still be enabled in the KS8842 because it indicates 35094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors to timberdale when there is RX data for it's DMA FIFOs */ 35194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors iowrite16(ENABLED_IRQS_DMA_IP, adapter->hw_addr + REG_TIMB_IER); 35294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_write16(adapter, 18, ENABLED_IRQS_DMA, REG_IER); 35394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } else { 35494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (!(adapter->conf_flags & MICREL_KS884X)) 35594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors iowrite16(ENABLED_IRQS, 35694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors adapter->hw_addr + REG_TIMB_IER); 35794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); 35894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 359b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* enable the switch */ 360b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 32, 0x1, REG_SW_ID_AND_ENABLE); 361b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 362b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 363b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic void ks8842_read_mac_addr(struct ks8842_adapter *adapter, u8 *dest) 364b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 365b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors int i; 366b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 mac; 367b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 368b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors for (i = 0; i < ETH_ALEN; i++) 369b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors dest[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i); 370b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 37128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi if (adapter->conf_flags & MICREL_KS884X) { 37228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi /* 37328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi the sequence of saving mac addr between MAC and Switch is 37428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi different. 37528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi */ 37628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 37728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi mac = ks8842_read16(adapter, 2, REG_MARL); 37828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 39, mac, REG_MACAR3); 37928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi mac = ks8842_read16(adapter, 2, REG_MARM); 38028bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 39, mac, REG_MACAR2); 38128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi mac = ks8842_read16(adapter, 2, REG_MARH); 38228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 39, mac, REG_MACAR1); 38328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } else { 38428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 38528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi /* make sure the switch port uses the same MAC as the QMU */ 38628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi mac = ks8842_read16(adapter, 2, REG_MARL); 38728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 39, mac, REG_MACAR1); 38828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi mac = ks8842_read16(adapter, 2, REG_MARM); 38928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 39, mac, REG_MACAR2); 39028bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi mac = ks8842_read16(adapter, 2, REG_MARH); 39128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 39, mac, REG_MACAR3); 39228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } 393b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 394b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 395a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjforsstatic void ks8842_write_mac_addr(struct ks8842_adapter *adapter, u8 *mac) 396a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors{ 397a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors unsigned long flags; 398a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors unsigned i; 399a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors 400a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors spin_lock_irqsave(&adapter->lock, flags); 401a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors for (i = 0; i < ETH_ALEN; i++) { 402a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors ks8842_write8(adapter, 2, mac[ETH_ALEN - i - 1], REG_MARL + i); 40328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi if (!(adapter->conf_flags & MICREL_KS884X)) 40428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write8(adapter, 39, mac[ETH_ALEN - i - 1], 40528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi REG_MACAR1 + i); 40628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } 40728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 40828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi if (adapter->conf_flags & MICREL_KS884X) { 40928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi /* 41028bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi the sequence of saving mac addr between MAC and Switch is 41128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi different. 41228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi */ 41328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 41428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi u16 mac; 41528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 41628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi mac = ks8842_read16(adapter, 2, REG_MARL); 41728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 39, mac, REG_MACAR3); 41828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi mac = ks8842_read16(adapter, 2, REG_MARM); 41928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 39, mac, REG_MACAR2); 42028bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi mac = ks8842_read16(adapter, 2, REG_MARH); 42128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 39, mac, REG_MACAR1); 422a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors } 423a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors spin_unlock_irqrestore(&adapter->lock, flags); 424a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors} 425a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors 426b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic inline u16 ks8842_tx_fifo_space(struct ks8842_adapter *adapter) 427b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 428b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return ks8842_read16(adapter, 16, REG_TXMIR) & 0x1fff; 429b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 430b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 43194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev) 43294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 43394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 43494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx; 43594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors u8 *buf = ctl->buf; 43694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 43794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (ctl->adesc) { 43894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev_dbg(netdev, "%s: TX ongoing\n", __func__); 43994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* transfer ongoing */ 44094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors return NETDEV_TX_BUSY; 44194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 44294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 44394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_len(&ctl->sg) = skb->len + sizeof(u32); 44494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 44594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* copy data to the TX buffer */ 44694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* the control word, enable IRQ, port 1 and the length */ 44794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors *buf++ = 0x00; 44894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors *buf++ = 0x01; /* Port 1 */ 44994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors *buf++ = skb->len & 0xff; 45094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors *buf++ = (skb->len >> 8) & 0xff; 45194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors skb_copy_from_linear_data(skb, buf, skb->len); 45294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 45394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_sync_single_range_for_device(adapter->dev, 45494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(&ctl->sg), 0, sg_dma_len(&ctl->sg), 45594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors DMA_TO_DEVICE); 45694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 45794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* make sure the length is a multiple of 4 */ 45894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (sg_dma_len(&ctl->sg) % 4) 45994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4; 46094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 46116052827d98fbc13c31ebad560af4bd53e2b4dd5Alexandre Bounine ctl->adesc = dmaengine_prep_slave_sg(ctl->chan, 4628af11fd3f013892c918a39acb691bc7469c5ad77Vinod Koul &ctl->sg, 1, DMA_MEM_TO_DEV, 46394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); 46494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (!ctl->adesc) 46594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors return NETDEV_TX_BUSY; 46694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 46794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->adesc->callback_param = netdev; 46894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->adesc->callback = ks8842_dma_tx_cb; 46994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->adesc->tx_submit(ctl->adesc); 47094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 47194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev->stats.tx_bytes += skb->len; 47294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 47394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dev_kfree_skb(skb); 47494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 47594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors return NETDEV_TX_OK; 47694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 47794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 478b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev) 479b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 480b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 481b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors int len = skb->len; 482b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 483a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s: len %u head %p data %p tail %p end %p\n", 484b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors __func__, skb->len, skb->head, skb->data, 485b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors skb_tail_pointer(skb), skb_end_pointer(skb)); 486b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 487b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* check FIFO buffer space, we need space for CRC and command bits */ 488b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (ks8842_tx_fifo_space(adapter) < len + 8) 489b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return NETDEV_TX_BUSY; 490b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 49128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi if (adapter->conf_flags & KS884X_16BIT) { 49228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi u16 *ptr16 = (u16 *)skb->data; 49328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 17, 0x8000 | 0x100, REG_QMU_DATA_LO); 49428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write16(adapter, 17, (u16)len, REG_QMU_DATA_HI); 49528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi netdev->stats.tx_bytes += len; 49628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 49728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi /* copy buffer */ 49828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi while (len > 0) { 49928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_LO); 50028bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_HI); 50128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi len -= sizeof(u32); 50228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } 50328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } else { 50428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 50528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi u32 *ptr = (u32 *)skb->data; 50628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi u32 ctrl; 50728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi /* the control word, enable IRQ, port 1 and the length */ 50828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ctrl = 0x8000 | 0x100 | (len << 16); 50928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_write32(adapter, 17, ctrl, REG_QMU_DATA_LO); 510b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 51128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi netdev->stats.tx_bytes += len; 512b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 51328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi /* copy buffer */ 51428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi while (len > 0) { 51528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi iowrite32(*ptr, adapter->hw_addr + REG_QMU_DATA_LO); 51628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi len -= sizeof(u32); 51728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ptr++; 51828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } 519b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } 520b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 521b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* enqueue packet */ 522b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 17, 1, REG_TXQCR); 523b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 524b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors dev_kfree_skb(skb); 525b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 526b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return NETDEV_TX_OK; 527b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 528b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 52994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic void ks8842_update_rx_err_counters(struct net_device *netdev, u32 status) 53094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 53194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev_dbg(netdev, "RX error, status: %x\n", status); 53294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 53394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev->stats.rx_errors++; 53494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (status & RXSR_TOO_LONG) 53594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev->stats.rx_length_errors++; 53694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (status & RXSR_CRC_ERROR) 53794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev->stats.rx_crc_errors++; 53894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (status & RXSR_RUNT) 53994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev->stats.rx_frame_errors++; 54094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 54194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 54294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic void ks8842_update_rx_counters(struct net_device *netdev, u32 status, 54394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors int len) 54494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 54594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev_dbg(netdev, "RX packet, len: %d\n", len); 54694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 54794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev->stats.rx_packets++; 54894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev->stats.rx_bytes += len; 54994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (status & RXSR_MULTICAST) 55094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev->stats.multicast++; 55194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 55294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 55394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic int __ks8842_start_new_rx_dma(struct net_device *netdev) 55494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 55594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 55694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx; 55794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct scatterlist *sg = &ctl->sg; 55894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors int err; 55994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 56094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->skb = netdev_alloc_skb(netdev, DMA_BUFFER_SIZE); 56194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (ctl->skb) { 56294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_init_table(sg, 1); 56394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(sg) = dma_map_single(adapter->dev, 56494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->skb->data, DMA_BUFFER_SIZE, DMA_FROM_DEVICE); 56594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors err = dma_mapping_error(adapter->dev, sg_dma_address(sg)); 56694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (unlikely(err)) { 56794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(sg) = 0; 56894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors goto out; 56994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 57094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 57194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_len(sg) = DMA_BUFFER_SIZE; 57294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 57316052827d98fbc13c31ebad560af4bd53e2b4dd5Alexandre Bounine ctl->adesc = dmaengine_prep_slave_sg(ctl->chan, 5748af11fd3f013892c918a39acb691bc7469c5ad77Vinod Koul sg, 1, DMA_DEV_TO_MEM, 57594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); 57694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 57794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (!ctl->adesc) 57894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors goto out; 57994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 58094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->adesc->callback_param = netdev; 58194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->adesc->callback = ks8842_dma_rx_cb; 58294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->adesc->tx_submit(ctl->adesc); 58394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } else { 58494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors err = -ENOMEM; 58594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(sg) = 0; 58694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors goto out; 58794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 58894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 58994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors return err; 59094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsout: 59194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (sg_dma_address(sg)) 59294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_unmap_single(adapter->dev, sg_dma_address(sg), 59394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors DMA_BUFFER_SIZE, DMA_FROM_DEVICE); 59494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(sg) = 0; 59594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (ctl->skb) 59694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dev_kfree_skb(ctl->skb); 59794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 59894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->skb = NULL; 59994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 60094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors printk(KERN_ERR DRV_NAME": Failed to start RX DMA: %d\n", err); 60194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors return err; 60294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 60394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 60494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic void ks8842_rx_frame_dma_tasklet(unsigned long arg) 60594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 60694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct net_device *netdev = (struct net_device *)arg; 60794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 60894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx; 60994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct sk_buff *skb = ctl->skb; 61094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_addr_t addr = sg_dma_address(&ctl->sg); 61194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors u32 status; 61294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 61394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->adesc = NULL; 61494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 61594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* kick next transfer going */ 61694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors __ks8842_start_new_rx_dma(netdev); 61794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 61894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* now handle the data we got */ 61994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_unmap_single(adapter->dev, addr, DMA_BUFFER_SIZE, DMA_FROM_DEVICE); 62094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 62194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors status = *((u32 *)skb->data); 62294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 62394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev_dbg(netdev, "%s - rx_data: status: %x\n", 62494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors __func__, status & 0xffff); 62594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 62694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* check the status */ 62794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) { 62894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors int len = (status >> 16) & 0x7ff; 62994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 63094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_update_rx_counters(netdev, status, len); 63194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 63294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* reserve 4 bytes which is the status word */ 63394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors skb_reserve(skb, 4); 63494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors skb_put(skb, len); 63594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 63694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors skb->protocol = eth_type_trans(skb, netdev); 63794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netif_rx(skb); 63894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } else { 63994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_update_rx_err_counters(netdev, status); 64094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dev_kfree_skb(skb); 64194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 64294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 64394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 644b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic void ks8842_rx_frame(struct net_device *netdev, 645b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter) 646b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 64728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi u32 status; 64828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi int len; 649b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 65028bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi if (adapter->conf_flags & KS884X_16BIT) { 651e2df8b7f6665075f7fe93613897117743c7bf0baDavid S. Miller status = ks8842_read16(adapter, 17, REG_QMU_DATA_LO); 652e2df8b7f6665075f7fe93613897117743c7bf0baDavid S. Miller len = ks8842_read16(adapter, 17, REG_QMU_DATA_HI); 65328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi netdev_dbg(netdev, "%s - rx_data: status: %x\n", 654e2df8b7f6665075f7fe93613897117743c7bf0baDavid S. Miller __func__, status); 65528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } else { 65628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO); 65728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi len = (status >> 16) & 0x7ff; 65828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi status &= 0xffff; 65928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi netdev_dbg(netdev, "%s - rx_data: status: %x\n", 66028bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi __func__, status); 66128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } 662b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 663b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* check the status */ 664b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) { 665b10cec8a4e8167075b9e1ff3f05419769e7f381aDennis Aberilla struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, len + 3); 666b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 667b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (skb) { 668b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 66994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_update_rx_counters(netdev, status, len); 670b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 67128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi if (adapter->conf_flags & KS884X_16BIT) { 67228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi u16 *data16 = (u16 *)skb_put(skb, len); 67328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_select_bank(adapter, 17); 67428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi while (len > 0) { 67528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi *data16++ = ioread16(adapter->hw_addr + 67628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi REG_QMU_DATA_LO); 67728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi *data16++ = ioread16(adapter->hw_addr + 67828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi REG_QMU_DATA_HI); 67928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi len -= sizeof(u32); 68028bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } 68128bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } else { 68228bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi u32 *data = (u32 *)skb_put(skb, len); 68328bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 68428bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi ks8842_select_bank(adapter, 17); 68528bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi while (len > 0) { 68628bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi *data++ = ioread32(adapter->hw_addr + 68728bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi REG_QMU_DATA_LO); 68828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi len -= sizeof(u32); 68928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi } 690b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } 691b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors skb->protocol = eth_type_trans(skb, netdev); 692b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netif_rx(skb); 693b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } else 694b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netdev->stats.rx_dropped++; 69594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } else 69694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_update_rx_err_counters(netdev, status); 697b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 698b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* set high watermark to 3K */ 699b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_clear_bits(adapter, 0, 1 << 12, REG_QRFCR); 700b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 701b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* release the frame */ 702b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 17, 0x01, REG_RXQCR); 703b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 704b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* set high watermark to 2K */ 705b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_bits(adapter, 0, 1 << 12, REG_QRFCR); 706b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 707b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 708b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsvoid ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter) 709b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 710b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff; 711a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s Entry - rx_data: %d\n", __func__, rx_data); 712b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors while (rx_data) { 713b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_rx_frame(netdev, adapter); 714b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff; 715b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } 716b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 717b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 718b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsvoid ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter) 719b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 720b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 sr = ks8842_read16(adapter, 16, REG_TXSR); 721a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s - entry, sr: %x\n", __func__, sr); 722b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netdev->stats.tx_packets++; 723b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (netif_queue_stopped(netdev)) 724b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netif_wake_queue(netdev); 725b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 726b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 727b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsvoid ks8842_handle_rx_overrun(struct net_device *netdev, 728b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter) 729b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 730a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s: entry\n", __func__); 731b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netdev->stats.rx_errors++; 732b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netdev->stats.rx_fifo_errors++; 733b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 734b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 735b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsvoid ks8842_tasklet(unsigned long arg) 736b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 737b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct net_device *netdev = (struct net_device *)arg; 738b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 739b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 isr; 740b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors unsigned long flags; 741b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 entry_bank; 742b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 743b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* read current bank to be able to set it back */ 744b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors spin_lock_irqsave(&adapter->lock, flags); 745b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK); 746b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors spin_unlock_irqrestore(&adapter->lock, flags); 747b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 748b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors isr = ks8842_read16(adapter, 18, REG_ISR); 749a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr); 750b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 75194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* when running in DMA mode, do not ack RX interrupts, it is handled 75294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors internally by timberdale, otherwise it's DMA FIFO:s would stop 75394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors */ 75494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) 75594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors isr &= ~IRQ_RX; 75694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 757b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* Ack */ 758b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 18, isr, REG_ISR); 759b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 760db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors if (!(adapter->conf_flags & MICREL_KS884X)) 761db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors /* Ack in the timberdale IP as well */ 762db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors iowrite32(0x1, adapter->hw_addr + REG_TIMB_IAR); 763db5824dd3d632acd79094b81e07288ba05ae2cc1Richard Röjfors 764b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (!netif_running(netdev)) 765b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return; 766b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 767b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (isr & IRQ_LINK_CHANGE) 768b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_update_link_status(netdev, adapter); 769b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 77094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* should not get IRQ_RX when running DMA mode */ 77194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (isr & (IRQ_RX | IRQ_RX_ERROR) && !KS8842_USE_DMA(adapter)) 772b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_handle_rx(netdev, adapter); 773b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 77494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* should only happen when in PIO mode */ 775b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (isr & IRQ_TX) 776b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_handle_tx(netdev, adapter); 777b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 778b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (isr & IRQ_RX_OVERRUN) 779b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_handle_rx_overrun(netdev, adapter); 780b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 781b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (isr & IRQ_TX_STOPPED) { 782b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_disable_tx(adapter); 783b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_tx(adapter); 784b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } 785b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 786b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (isr & IRQ_RX_STOPPED) { 787b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_disable_rx(adapter); 788b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_enable_rx(adapter); 789b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } 790b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 791b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* re-enable interrupts, put back the bank selection register */ 792b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors spin_lock_irqsave(&adapter->lock, flags); 79394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) 79494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_write16(adapter, 18, ENABLED_IRQS_DMA, REG_IER); 79594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors else 79694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); 797b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK); 79894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 79994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* Make sure timberdale continues DMA operations, they are stopped while 80094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors we are handling the ks8842 because we might change bank */ 80194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) 80294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_resume_dma(adapter); 80394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 804b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors spin_unlock_irqrestore(&adapter->lock, flags); 805b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 806b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 807b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic irqreturn_t ks8842_irq(int irq, void *devid) 808b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 809a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors struct net_device *netdev = devid; 810a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 811b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 isr; 812b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK); 813b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors irqreturn_t ret = IRQ_NONE; 814b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 815b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors isr = ks8842_read16(adapter, 18, REG_ISR); 816a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr); 817b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 818b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (isr) { 81994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) 82094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* disable all but RX IRQ, since the FPGA relies on it*/ 82194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_write16(adapter, 18, IRQ_RX, REG_IER); 82294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors else 82394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* disable IRQ */ 82494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_write16(adapter, 18, 0x00, REG_IER); 825b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 826b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* schedule tasklet */ 827b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors tasklet_schedule(&adapter->tasklet); 828b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 829b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ret = IRQ_HANDLED; 830b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } 831b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 832b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK); 833b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 83494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* After an interrupt, tell timberdale to continue DMA operations. 83594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors DMA is disabled while we are handling the ks8842 because we might 83694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors change bank */ 83794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_resume_dma(adapter); 83894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 839b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return ret; 840b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 841b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 84294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic void ks8842_dma_rx_cb(void *data) 84394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 84494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct net_device *netdev = data; 84594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 84694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 84794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev_dbg(netdev, "RX DMA finished\n"); 84894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* schedule tasklet */ 84994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (adapter->dma_rx.adesc) 85094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tasklet_schedule(&adapter->dma_rx.tasklet); 85194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 85294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 85394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic void ks8842_dma_tx_cb(void *data) 85494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 85594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct net_device *netdev = data; 85694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 85794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx; 85894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 85994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev_dbg(netdev, "TX DMA finished\n"); 86094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 86194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (!ctl->adesc) 86294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors return; 86394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 86494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netdev->stats.tx_packets++; 86594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ctl->adesc = NULL; 86694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 86794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (netif_queue_stopped(netdev)) 86894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netif_wake_queue(netdev); 86994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 87094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 87194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic void ks8842_stop_dma(struct ks8842_adapter *adapter) 87294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 87394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx; 87494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx; 87594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 87694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tx_ctl->adesc = NULL; 87794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (tx_ctl->chan) 87894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tx_ctl->chan->device->device_control(tx_ctl->chan, 87994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors DMA_TERMINATE_ALL, 0); 88094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 88194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors rx_ctl->adesc = NULL; 88294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (rx_ctl->chan) 88394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors rx_ctl->chan->device->device_control(rx_ctl->chan, 88494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors DMA_TERMINATE_ALL, 0); 88594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 88694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (sg_dma_address(&rx_ctl->sg)) 88794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_unmap_single(adapter->dev, sg_dma_address(&rx_ctl->sg), 88894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors DMA_BUFFER_SIZE, DMA_FROM_DEVICE); 88994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(&rx_ctl->sg) = 0; 89094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 89194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dev_kfree_skb(rx_ctl->skb); 89294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors rx_ctl->skb = NULL; 89394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 89494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 89594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic void ks8842_dealloc_dma_bufs(struct ks8842_adapter *adapter) 89694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 89794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx; 89894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx; 89994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 90094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_stop_dma(adapter); 90194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 90294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (tx_ctl->chan) 90394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_release_channel(tx_ctl->chan); 90494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tx_ctl->chan = NULL; 90594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 90694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (rx_ctl->chan) 90794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_release_channel(rx_ctl->chan); 90894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors rx_ctl->chan = NULL; 90994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 91094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tasklet_kill(&rx_ctl->tasklet); 91194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 91294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (sg_dma_address(&tx_ctl->sg)) 91394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_unmap_single(adapter->dev, sg_dma_address(&tx_ctl->sg), 91494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors DMA_BUFFER_SIZE, DMA_TO_DEVICE); 91594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(&tx_ctl->sg) = 0; 91694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 91794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors kfree(tx_ctl->buf); 91894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tx_ctl->buf = NULL; 91994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 92094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 92194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic bool ks8842_dma_filter_fn(struct dma_chan *chan, void *filter_param) 92294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 923bd280635825a2b3981da63a54e38de97e87231b3David S. Miller return chan->chan_id == (long)filter_param; 92494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 92594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 92694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforsstatic int ks8842_alloc_dma_bufs(struct net_device *netdev) 92794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors{ 92894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 92994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx; 93094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx; 93194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors int err; 93294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 93394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_cap_mask_t mask; 93494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 93594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_cap_zero(mask); 93694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_cap_set(DMA_SLAVE, mask); 93794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors dma_cap_set(DMA_PRIVATE, mask); 93894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 93994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_init_table(&tx_ctl->sg, 1); 94094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 94194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tx_ctl->chan = dma_request_channel(mask, ks8842_dma_filter_fn, 942bd280635825a2b3981da63a54e38de97e87231b3David S. Miller (void *)(long)tx_ctl->channel); 94394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (!tx_ctl->chan) { 94494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors err = -ENODEV; 94594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors goto err; 94694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 94794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 94894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* allocate DMA buffer */ 94994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tx_ctl->buf = kmalloc(DMA_BUFFER_SIZE, GFP_KERNEL); 95094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (!tx_ctl->buf) { 95194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors err = -ENOMEM; 95294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors goto err; 95394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 95494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 95594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(&tx_ctl->sg) = dma_map_single(adapter->dev, 95694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tx_ctl->buf, DMA_BUFFER_SIZE, DMA_TO_DEVICE); 95794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors err = dma_mapping_error(adapter->dev, 95894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(&tx_ctl->sg)); 95994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (err) { 96094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors sg_dma_address(&tx_ctl->sg) = 0; 96194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors goto err; 96294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 96394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 96494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors rx_ctl->chan = dma_request_channel(mask, ks8842_dma_filter_fn, 965bd280635825a2b3981da63a54e38de97e87231b3David S. Miller (void *)(long)rx_ctl->channel); 96694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (!rx_ctl->chan) { 96794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors err = -ENODEV; 96894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors goto err; 96994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 97094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 97194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors tasklet_init(&rx_ctl->tasklet, ks8842_rx_frame_dma_tasklet, 97294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors (unsigned long)netdev); 97394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 97494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors return 0; 97594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjforserr: 97694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_dealloc_dma_bufs(adapter); 97794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors return err; 97894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors} 979b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 980b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors/* Netdevice operations */ 981b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 982b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic int ks8842_open(struct net_device *netdev) 983b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 984b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 985b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors int err; 986b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 987a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s - entry\n", __func__); 988b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 98994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) { 99094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors err = ks8842_alloc_dma_bufs(netdev); 99194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 99294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (!err) { 99394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* start RX dma */ 99494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors err = __ks8842_start_new_rx_dma(netdev); 99594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (err) 99694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_dealloc_dma_bufs(adapter); 99794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 99894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 99994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (err) { 100094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors printk(KERN_WARNING DRV_NAME 100194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ": Failed to initiate DMA, running PIO\n"); 100294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_dealloc_dma_bufs(adapter); 100394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors adapter->dma_rx.channel = -1; 100494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors adapter->dma_tx.channel = -1; 100594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 100694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 100794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 1008b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* reset the HW */ 1009b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_reset_hw(adapter); 1010b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1011a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors ks8842_write_mac_addr(adapter, netdev->dev_addr); 1012a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors 1013b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_update_link_status(netdev, adapter); 1014b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1015b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors err = request_irq(adapter->irq, ks8842_irq, IRQF_SHARED, DRV_NAME, 1016a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev); 1017b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (err) { 10180dc7d2b3cbfcf4ff20bdc68f563a2e52e6a2178fJoe Perches pr_err("Failed to request IRQ: %d: %d\n", adapter->irq, err); 1019b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return err; 1020b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } 1021b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1022b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return 0; 1023b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 1024b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1025b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic int ks8842_close(struct net_device *netdev) 1026b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 1027b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 1028b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1029a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s - entry\n", __func__); 1030b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1031cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors cancel_work_sync(&adapter->timeout_work); 1032cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors 103394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) 103494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_dealloc_dma_bufs(adapter); 103594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 1036b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* free the irq */ 1037a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors free_irq(adapter->irq, netdev); 1038b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1039b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* disable the switch */ 1040b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 32, 0x0, REG_SW_ID_AND_ENABLE); 1041b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1042b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return 0; 1043b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 1044b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 104561357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t ks8842_xmit_frame(struct sk_buff *skb, 104661357325f377889a1daffa14962d705dc814dd0eStephen Hemminger struct net_device *netdev) 1047b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 1048b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors int ret; 1049b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 1050b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1051a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s: entry\n", __func__); 1052b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 105394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) { 105494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors unsigned long flags; 105594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ret = ks8842_tx_frame_dma(skb, netdev); 105694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* for now only allow one transfer at the time */ 105794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors spin_lock_irqsave(&adapter->lock, flags); 105894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (adapter->dma_tx.adesc) 105994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors netif_stop_queue(netdev); 106094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors spin_unlock_irqrestore(&adapter->lock, flags); 106194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors return ret; 106294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 106394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 1064b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ret = ks8842_tx_frame(skb, netdev); 1065b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1066b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (ks8842_tx_fifo_space(adapter) < netdev->mtu + 8) 1067b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netif_stop_queue(netdev); 1068b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1069b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return ret; 1070b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 1071b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1072b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic int ks8842_set_mac(struct net_device *netdev, void *p) 1073b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 1074b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 1075b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct sockaddr *addr = p; 1076b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors char *mac = (u8 *)addr->sa_data; 1077b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1078a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s: entry\n", __func__); 1079b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1080b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (!is_valid_ether_addr(addr->sa_data)) 1081b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return -EADDRNOTAVAIL; 1082b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 10837ce5d222190cb3ce3ae88bafde7c4fa52a5103e0Danny Kukawka netdev->addr_assign_type &= ~NET_ADDR_RANDOM; 1084b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors memcpy(netdev->dev_addr, mac, netdev->addr_len); 1085b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1086a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors ks8842_write_mac_addr(adapter, mac); 1087b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return 0; 1088b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 1089b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1090cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjforsstatic void ks8842_tx_timeout_work(struct work_struct *work) 1091b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 1092cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors struct ks8842_adapter *adapter = 1093cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors container_of(work, struct ks8842_adapter, timeout_work); 1094cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors struct net_device *netdev = adapter->netdev; 1095b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors unsigned long flags; 1096b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1097a99db196db1166a2159add4a3013e5df0ea126faRichard Röjfors netdev_dbg(netdev, "%s: entry\n", __func__); 1098b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1099b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors spin_lock_irqsave(&adapter->lock, flags); 110094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 110194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) 110294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors ks8842_stop_dma(adapter); 110394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 1104b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors /* disable interrupts */ 1105b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 18, 0, REG_IER); 1106b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_write16(adapter, 18, 0xFFFF, REG_ISR); 1107cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors 1108cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors netif_stop_queue(netdev); 1109cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors 1110b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors spin_unlock_irqrestore(&adapter->lock, flags); 1111b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1112b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_reset_hw(adapter); 1113b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1114a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors ks8842_write_mac_addr(adapter, netdev->dev_addr); 1115a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors 1116b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors ks8842_update_link_status(netdev, adapter); 111794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 111894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (KS8842_USE_DMA(adapter)) 111994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors __ks8842_start_new_rx_dma(netdev); 1120b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 1121b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1122cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjforsstatic void ks8842_tx_timeout(struct net_device *netdev) 1123cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors{ 1124cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 1125cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors 1126cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors netdev_dbg(netdev, "%s: entry\n", __func__); 1127cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors 1128cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors schedule_work(&adapter->timeout_work); 1129cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors} 1130cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors 1131b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic const struct net_device_ops ks8842_netdev_ops = { 1132b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .ndo_open = ks8842_open, 1133b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .ndo_stop = ks8842_close, 1134b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .ndo_start_xmit = ks8842_xmit_frame, 1135b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .ndo_set_mac_address = ks8842_set_mac, 1136b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .ndo_tx_timeout = ks8842_tx_timeout, 1137b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .ndo_validate_addr = eth_validate_addr 1138b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors}; 1139b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 11400fc0b732eaa38beb93a6fb62f77c7bd9622c76ecStephen Hemmingerstatic const struct ethtool_ops ks8842_ethtool_ops = { 1141b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .get_link = ethtool_op_get_link, 1142b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors}; 1143b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1144b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic int __devinit ks8842_probe(struct platform_device *pdev) 1145b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 1146b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors int err = -ENOMEM; 1147b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct resource *iomem; 1148b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct net_device *netdev; 1149b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter; 11503271d382c3ffe61ef3d059ef47e635dbe031030eSamuel Ortiz struct ks8842_platform_data *pdata = pdev->dev.platform_data; 1151b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors u16 id; 1152a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors unsigned i; 1153b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1154b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1155b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (!request_mem_region(iomem->start, resource_size(iomem), DRV_NAME)) 1156b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors goto err_mem_region; 1157b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1158b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netdev = alloc_etherdev(sizeof(struct ks8842_adapter)); 1159b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (!netdev) 1160b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors goto err_alloc_etherdev; 1161b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1162b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors SET_NETDEV_DEV(netdev, &pdev->dev); 1163b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1164b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors adapter = netdev_priv(netdev); 1165cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors adapter->netdev = netdev; 1166cc88e450ad14a79fd2d083f0827607499cf1ef51Richard Röjfors INIT_WORK(&adapter->timeout_work, ks8842_tx_timeout_work); 1167b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors adapter->hw_addr = ioremap(iomem->start, resource_size(iomem)); 116828bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi adapter->conf_flags = iomem->flags; 116928bd620c7a1244e59459d6293ca11f162e0a67b9David J. Choi 1170b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (!adapter->hw_addr) 1171b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors goto err_ioremap; 1172b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1173b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors adapter->irq = platform_get_irq(pdev, 0); 1174b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (adapter->irq < 0) { 1175b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors err = adapter->irq; 1176b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors goto err_get_irq; 1177b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors } 1178b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 117994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors adapter->dev = (pdev->dev.parent) ? pdev->dev.parent : &pdev->dev; 118094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 118194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors /* DMA is only supported when accessed via timberdale */ 118294fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors if (!(adapter->conf_flags & MICREL_KS884X) && pdata && 118394fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors (pdata->tx_dma_channel != -1) && 118494fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors (pdata->rx_dma_channel != -1)) { 118594fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors adapter->dma_rx.channel = pdata->rx_dma_channel; 118694fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors adapter->dma_tx.channel = pdata->tx_dma_channel; 118794fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } else { 118894fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors adapter->dma_rx.channel = -1; 118994fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors adapter->dma_tx.channel = -1; 119094fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors } 119194fe8c683cea97fe2c59a5f0dc206aa329c5763cRichard Röjfors 1192b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors tasklet_init(&adapter->tasklet, ks8842_tasklet, (unsigned long)netdev); 1193b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors spin_lock_init(&adapter->lock); 1194b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1195b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netdev->netdev_ops = &ks8842_netdev_ops; 1196b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors netdev->ethtool_ops = &ks8842_ethtool_ops; 1197b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1198a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors /* Check if a mac address was given */ 1199a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors i = netdev->addr_len; 1200a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors if (pdata) { 1201a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors for (i = 0; i < netdev->addr_len; i++) 1202a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors if (pdata->macaddr[i] != 0) 1203a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors break; 1204a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors 1205a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors if (i < netdev->addr_len) 1206a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors /* an address was passed, use it */ 1207a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors memcpy(netdev->dev_addr, pdata->macaddr, 1208a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors netdev->addr_len); 1209a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors } 1210a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors 1211a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors if (i == netdev->addr_len) { 1212a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors ks8842_read_mac_addr(adapter, netdev->dev_addr); 1213a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors 1214a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors if (!is_valid_ether_addr(netdev->dev_addr)) 12157ce5d222190cb3ce3ae88bafde7c4fa52a5103e0Danny Kukawka eth_hw_addr_random(netdev); 1216a1aa8822d577c8714f8d343eea028befbab3da9dRichard Röjfors } 1217b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1218b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors id = ks8842_read16(adapter, 32, REG_SW_ID_AND_ENABLE); 1219b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1220b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors strcpy(netdev->name, "eth%d"); 1221b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors err = register_netdev(netdev); 1222b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors if (err) 1223b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors goto err_register; 1224b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1225b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors platform_set_drvdata(pdev, netdev); 1226b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 12270dc7d2b3cbfcf4ff20bdc68f563a2e52e6a2178fJoe Perches pr_info("Found chip, family: 0x%x, id: 0x%x, rev: 0x%x\n", 1228b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors (id >> 8) & 0xff, (id >> 4) & 0xf, (id >> 1) & 0x7); 1229b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1230b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return 0; 1231b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1232b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforserr_register: 1233b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforserr_get_irq: 1234b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iounmap(adapter->hw_addr); 1235b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforserr_ioremap: 1236b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors free_netdev(netdev); 1237b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforserr_alloc_etherdev: 1238b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors release_mem_region(iomem->start, resource_size(iomem)); 1239b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforserr_mem_region: 1240b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return err; 1241b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 1242b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1243b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic int __devexit ks8842_remove(struct platform_device *pdev) 1244b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors{ 1245b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct net_device *netdev = platform_get_drvdata(pdev); 1246b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct ks8842_adapter *adapter = netdev_priv(netdev); 1247b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1248b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1249b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors unregister_netdev(netdev); 1250b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors tasklet_kill(&adapter->tasklet); 1251b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors iounmap(adapter->hw_addr); 1252b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors free_netdev(netdev); 1253b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors release_mem_region(iomem->start, resource_size(iomem)); 1254b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors platform_set_drvdata(pdev, NULL); 1255b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors return 0; 1256b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors} 1257b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1258b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1259b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjforsstatic struct platform_driver ks8842_platform_driver = { 1260b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .driver = { 1261b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .name = DRV_NAME, 1262b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .owner = THIS_MODULE, 1263b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors }, 1264b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .probe = ks8842_probe, 1265b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors .remove = ks8842_remove, 1266b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors}; 1267b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1268db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(ks8842_platform_driver); 1269b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1270b07878e5471a8c880cb3cffee3a73048f38d2001Richard RöjforsMODULE_DESCRIPTION("Timberdale KS8842 ethernet driver"); 1271b07878e5471a8c880cb3cffee3a73048f38d2001Richard RöjforsMODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); 1272b07878e5471a8c880cb3cffee3a73048f38d2001Richard RöjforsMODULE_LICENSE("GPL v2"); 1273b07878e5471a8c880cb3cffee3a73048f38d2001Richard RöjforsMODULE_ALIAS("platform:ks8842"); 1274b07878e5471a8c880cb3cffee3a73048f38d2001Richard Röjfors 1275