diff options
Diffstat (limited to 'drivers/net/ethernet/micrel')
| -rw-r--r-- | drivers/net/ethernet/micrel/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/micrel/ks8695net.c | 49 | ||||
| -rw-r--r-- | drivers/net/ethernet/micrel/ks8842.c | 42 | ||||
| -rw-r--r-- | drivers/net/ethernet/micrel/ks8851.c | 728 | ||||
| -rw-r--r-- | drivers/net/ethernet/micrel/ks8851.h | 17 | ||||
| -rw-r--r-- | drivers/net/ethernet/micrel/ks8851_mll.c | 139 | ||||
| -rw-r--r-- | drivers/net/ethernet/micrel/ksz884x.c | 164 |
7 files changed, 494 insertions, 650 deletions
diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig index d10c2e15f4e..d16b11ed2e5 100644 --- a/drivers/net/ethernet/micrel/Kconfig +++ b/drivers/net/ethernet/micrel/Kconfig @@ -22,7 +22,6 @@ if NET_VENDOR_MICREL config ARM_KS8695_ETHER tristate "KS8695 Ethernet support" depends on ARM && ARCH_KS8695 - select NET_CORE select MII ---help--- If you wish to compile a kernel for the KS8695 and want to @@ -39,16 +38,15 @@ config KS8842 config KS8851 tristate "Micrel KS8851 SPI" depends on SPI - select NET_CORE select MII select CRC32 + select EEPROM_93CX6 ---help--- SPI driver for Micrel KS8851 SPI attached network chip. config KS8851_MLL tristate "Micrel KS8851 MLL" depends on HAS_IOMEM - select NET_CORE select MII ---help--- This platform driver is for Micrel KS8851 Address/data bus @@ -57,7 +55,6 @@ config KS8851_MLL config KSZ884X_PCI tristate "Micrel KSZ8841/2 PCI" depends on PCI - select NET_CORE select MII select CRC32 ---help--- diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c index ab81c0dc96e..6c7c78baedc 100644 --- a/drivers/net/ethernet/micrel/ks8695net.c +++ b/drivers/net/ethernet/micrel/ks8695net.c @@ -21,7 +21,6 @@ #include <linux/ioport.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/skbuff.h> #include <linux/spinlock.h> @@ -278,7 +277,8 @@ ks8695_refill_rxbuffers(struct ks8695_priv *ksp) for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) { if (!ksp->rx_buffers[buff_n].skb) { - struct sk_buff *skb = dev_alloc_skb(MAX_RXBUF_SIZE); + struct sk_buff *skb = + netdev_alloc_skb(ksp->ndev, MAX_RXBUF_SIZE); dma_addr_t mapping; ksp->rx_buffers[buff_n].skb = skb; @@ -299,7 +299,6 @@ ks8695_refill_rxbuffers(struct ks8695_priv *ksp) break; } ksp->rx_buffers[buff_n].dma_ptr = mapping; - skb->dev = ksp->ndev; ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE; /* Record this into the DMA ring */ @@ -1249,9 +1248,6 @@ ks8695_open(struct net_device *ndev) struct ks8695_priv *ksp = netdev_priv(ndev); int ret; - if (!is_valid_ether_addr(ndev->dev_addr)) - return -EADDRNOTAVAIL; - ks8695_reset(ksp); ks8695_update_mac(ksp); @@ -1277,7 +1273,7 @@ ks8695_open(struct net_device *ndev) * This initialises the LAN switch in the KS8695 to a known-good * set of defaults. */ -static void __devinit +static void ks8695_init_switch(struct ks8695_priv *ksp) { u32 ctrl; @@ -1305,7 +1301,7 @@ ks8695_init_switch(struct ks8695_priv *ksp) * This initialises a KS8695's WAN phy to sensible values for * autonegotiation etc. */ -static void __devinit +static void ks8695_init_wan_phy(struct ks8695_priv *ksp) { u32 ctrl; @@ -1349,7 +1345,7 @@ static const struct net_device_ops ks8695_netdev_ops = { * wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan * port. */ -static int __devinit +static int ks8695_probe(struct platform_device *pdev) { struct ks8695_priv *ksp; @@ -1362,10 +1358,8 @@ ks8695_probe(struct platform_device *pdev) /* Initialise a net_device */ ndev = alloc_etherdev(sizeof(struct ks8695_priv)); - if (!ndev) { - dev_err(&pdev->dev, "could not allocate device.\n"); + if (!ndev) return -ENOMEM; - } SET_NETDEV_DEV(ndev, &pdev->dev); @@ -1510,15 +1504,15 @@ ks8695_probe(struct platform_device *pdev) if (ksp->phyiface_regs && ksp->link_irq == -1) { ks8695_init_switch(ksp); ksp->dtype = KS8695_DTYPE_LAN; - SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); + ndev->ethtool_ops = &ks8695_ethtool_ops; } else if (ksp->phyiface_regs && ksp->link_irq != -1) { ks8695_init_wan_phy(ksp); ksp->dtype = KS8695_DTYPE_WAN; - SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops); + ndev->ethtool_ops = &ks8695_wan_ethtool_ops; } else { /* No initialisation since HPNA does not have a PHY */ ksp->dtype = KS8695_DTYPE_HPNA; - SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); + ndev->ethtool_ops = &ks8695_ethtool_ops; } /* And bring up the net_device with the net core */ @@ -1599,13 +1593,12 @@ ks8695_drv_resume(struct platform_device *pdev) * * This unregisters and releases a KS8695 ethernet device. */ -static int __devexit +static int ks8695_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct ks8695_priv *ksp = netdev_priv(ndev); - platform_set_drvdata(pdev, NULL); netif_napi_del(&ksp->napi); unregister_netdev(ndev); @@ -1622,30 +1615,12 @@ static struct platform_driver ks8695_driver = { .owner = THIS_MODULE, }, .probe = ks8695_probe, - .remove = __devexit_p(ks8695_drv_remove), + .remove = ks8695_drv_remove, .suspend = ks8695_drv_suspend, .resume = ks8695_drv_resume, }; -/* Module interface */ - -static int __init -ks8695_init(void) -{ - printk(KERN_INFO "%s Ethernet driver, V%s\n", - MODULENAME, MODULEVERSION); - - return platform_driver_register(&ks8695_driver); -} - -static void __exit -ks8695_cleanup(void) -{ - platform_driver_unregister(&ks8695_driver); -} - -module_init(ks8695_init); -module_exit(ks8695_cleanup); +module_platform_driver(ks8695_driver); MODULE_AUTHOR("Simtec Electronics"); MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver"); diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c index 4a6ae057e3b..822616e3c37 100644 --- a/drivers/net/ethernet/micrel/ks8842.c +++ b/drivers/net/ethernet/micrel/ks8842.c @@ -458,9 +458,8 @@ static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev) if (sg_dma_len(&ctl->sg) % 4) sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4; - ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan, - &ctl->sg, 1, DMA_TO_DEVICE, - DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); + ctl->adesc = dmaengine_prep_slave_sg(ctl->chan, + &ctl->sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); if (!ctl->adesc) return NETDEV_TX_BUSY; @@ -570,9 +569,8 @@ static int __ks8842_start_new_rx_dma(struct net_device *netdev) sg_dma_len(sg) = DMA_BUFFER_SIZE; - ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan, - sg, 1, DMA_FROM_DEVICE, - DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); + ctl->adesc = dmaengine_prep_slave_sg(ctl->chan, + sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); if (!ctl->adesc) goto out; @@ -705,7 +703,8 @@ static void ks8842_rx_frame(struct net_device *netdev, ks8842_enable_bits(adapter, 0, 1 << 12, REG_QRFCR); } -void ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter) +static void ks8842_handle_rx(struct net_device *netdev, + struct ks8842_adapter *adapter) { u16 rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff; netdev_dbg(netdev, "%s Entry - rx_data: %d\n", __func__, rx_data); @@ -715,7 +714,8 @@ void ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter) } } -void ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter) +static void ks8842_handle_tx(struct net_device *netdev, + struct ks8842_adapter *adapter) { u16 sr = ks8842_read16(adapter, 16, REG_TXSR); netdev_dbg(netdev, "%s - entry, sr: %x\n", __func__, sr); @@ -724,7 +724,7 @@ void ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter) netif_wake_queue(netdev); } -void ks8842_handle_rx_overrun(struct net_device *netdev, +static void ks8842_handle_rx_overrun(struct net_device *netdev, struct ks8842_adapter *adapter) { netdev_dbg(netdev, "%s: entry\n", __func__); @@ -732,7 +732,7 @@ void ks8842_handle_rx_overrun(struct net_device *netdev, netdev->stats.rx_fifo_errors++; } -void ks8842_tasklet(unsigned long arg) +static void ks8842_tasklet(unsigned long arg) { struct net_device *netdev = (struct net_device *)arg; struct ks8842_adapter *adapter = netdev_priv(netdev); @@ -1140,13 +1140,13 @@ static const struct ethtool_ops ks8842_ethtool_ops = { .get_link = ethtool_op_get_link, }; -static int __devinit ks8842_probe(struct platform_device *pdev) +static int ks8842_probe(struct platform_device *pdev) { int err = -ENOMEM; struct resource *iomem; struct net_device *netdev; struct ks8842_adapter *adapter; - struct ks8842_platform_data *pdata = pdev->dev.platform_data; + struct ks8842_platform_data *pdata = dev_get_platdata(&pdev->dev); u16 id; unsigned i; @@ -1211,7 +1211,7 @@ static int __devinit ks8842_probe(struct platform_device *pdev) ks8842_read_mac_addr(adapter, netdev->dev_addr); if (!is_valid_ether_addr(netdev->dev_addr)) - random_ether_addr(netdev->dev_addr); + eth_hw_addr_random(netdev); } id = ks8842_read16(adapter, 32, REG_SW_ID_AND_ENABLE); @@ -1239,7 +1239,7 @@ err_mem_region: return err; } -static int __devexit ks8842_remove(struct platform_device *pdev) +static int ks8842_remove(struct platform_device *pdev) { struct net_device *netdev = platform_get_drvdata(pdev); struct ks8842_adapter *adapter = netdev_priv(netdev); @@ -1250,7 +1250,6 @@ static int __devexit ks8842_remove(struct platform_device *pdev) iounmap(adapter->hw_addr); free_netdev(netdev); release_mem_region(iomem->start, resource_size(iomem)); - platform_set_drvdata(pdev, NULL); return 0; } @@ -1264,18 +1263,7 @@ static struct platform_driver ks8842_platform_driver = { .remove = ks8842_remove, }; -static int __init ks8842_init(void) -{ - return platform_driver_register(&ks8842_platform_driver); -} - -static void __exit ks8842_exit(void) -{ - platform_driver_unregister(&ks8842_platform_driver); -} - -module_init(ks8842_init); -module_exit(ks8842_exit); +module_platform_driver(ks8842_platform_driver); MODULE_DESCRIPTION("Timberdale KS8842 ethernet driver"); MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 115e374f2c2..66d4ab703f4 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -1,4 +1,4 @@ -/* drivers/net/ks8851.c +/* drivers/net/ethernet/micrel/ks8851.c * * Copyright 2009 Simtec Electronics * http://www.simtec.co.uk/ @@ -22,8 +22,12 @@ #include <linux/cache.h> #include <linux/crc32.h> #include <linux/mii.h> +#include <linux/eeprom_93cx6.h> +#include <linux/regulator/consumer.h> #include <linux/spi/spi.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> #include "ks8851.h" @@ -68,7 +72,6 @@ union ks8851_tx_hdr { * @mii: The MII state information for the mii calls. * @rxctrl: RX settings for @rxctrl_work. * @tx_work: Work queue for tx packets - * @irq_work: Work queue for servicing interrupts * @rxctrl_work: Work queue for updating RX mode and multicast lists * @txq: Queue of packets for transmission. * @spi_msg1: pre-setup SPI transfer with one message, @spi_xfer1. @@ -82,6 +85,10 @@ union ks8851_tx_hdr { * @rc_ccr: Cached copy of KS_CCR. * @rc_rxqcr: Cached copy of KS_RXQCR. * @eeprom_size: Companion eeprom size in Bytes, 0 if no eeprom + * @eeprom: 93CX6 EEPROM state for accessing on-board EEPROM. + * @vdd_reg: Optional regulator supplying the chip + * @vdd_io: Optional digital power supply for IO + * @gpio: Optional reset_n gpio * * The @lock ensures that the chip is protected when certain operations are * in progress. When the read or write packet transfer is in progress, most @@ -119,7 +126,6 @@ struct ks8851_net { struct ks8851_rxctrl rxctrl; struct work_struct tx_work; - struct work_struct irq_work; struct work_struct rxctrl_work; struct sk_buff_head txq; @@ -128,6 +134,11 @@ struct ks8851_net { struct spi_message spi_msg2; struct spi_transfer spi_xfer1; struct spi_transfer spi_xfer2[2]; + + struct eeprom_93cx6 eeprom; + struct regulator *vdd_reg; + struct regulator *vdd_io; + int gpio; }; static int msg_enable; @@ -343,6 +354,26 @@ static void ks8851_soft_reset(struct ks8851_net *ks, unsigned op) } /** + * ks8851_set_powermode - set power mode of the device + * @ks: The device state + * @pwrmode: The power mode value to write to KS_PMECR. + * + * Change the power mode of the chip. + */ +static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode) +{ + unsigned pmecr; + + netif_dbg(ks, hw, ks->netdev, "setting power mode %d\n", pwrmode); + + pmecr = ks8851_rdreg16(ks, KS_PMECR); + pmecr &= ~PMECR_PM_MASK; + pmecr |= pwrmode; + + ks8851_wrreg16(ks, KS_PMECR, pmecr); +} + +/** * ks8851_write_mac_addr - write mac address to device registers * @dev: The network device * @@ -358,8 +389,15 @@ static int ks8851_write_mac_addr(struct net_device *dev) mutex_lock(&ks->lock); + /* + * Wake up chip in case it was powered off when stopped; otherwise, + * the first write to the MAC address does not take effect. + */ + ks8851_set_powermode(ks, PMECR_PM_NORMAL); for (i = 0; i < ETH_ALEN; i++) ks8851_wrreg8(ks, KS_MAR(i), dev->dev_addr[i]); + if (!netif_running(dev)) + ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); mutex_unlock(&ks->lock); @@ -367,40 +405,49 @@ static int ks8851_write_mac_addr(struct net_device *dev) } /** + * ks8851_read_mac_addr - read mac address from device registers + * @dev: The network device + * + * Update our copy of the KS8851 MAC address from the registers of @dev. +*/ +static void ks8851_read_mac_addr(struct net_device *dev) +{ + struct ks8851_net *ks = netdev_priv(dev); + int i; + + mutex_lock(&ks->lock); + + for (i = 0; i < ETH_ALEN; i++) + dev->dev_addr[i] = ks8851_rdreg8(ks, KS_MAR(i)); + + mutex_unlock(&ks->lock); +} + +/** * ks8851_init_mac - initialise the mac address * @ks: The device structure * * Get or create the initial mac address for the device and then set that - * into the station address register. Currently we assume that the device - * does not have a valid mac address in it, and so we use random_ether_addr() + * into the station address register. If there is an EEPROM present, then + * we try that. If no valid mac address is found we use eth_random_addr() * to create a new one. - * - * In future, the driver should check to see if the device has an EEPROM - * attached and whether that has a valid ethernet address in it. */ static void ks8851_init_mac(struct ks8851_net *ks) { struct net_device *dev = ks->netdev; - random_ether_addr(dev->dev_addr); - ks8851_write_mac_addr(dev); -} + /* first, try reading what we've got already */ + if (ks->rc_ccr & CCR_EEPROM) { + ks8851_read_mac_addr(dev); + if (is_valid_ether_addr(dev->dev_addr)) + return; -/** - * ks8851_irq - device interrupt handler - * @irq: Interrupt number passed from the IRQ hnalder. - * @pw: The private word passed to register_irq(), our struct ks8851_net. - * - * Disable the interrupt from happening again until we've processed the - * current status by scheduling ks8851_irq_work(). - */ -static irqreturn_t ks8851_irq(int irq, void *pw) -{ - struct ks8851_net *ks = pw; + netdev_err(ks->netdev, "invalid mac address read %pM\n", + dev->dev_addr); + } - disable_irq_nosync(irq); - schedule_work(&ks->irq_work); - return IRQ_HANDLED; + eth_hw_addr_random(dev); + ks8851_write_mac_addr(dev); } /** @@ -526,7 +573,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) ks8851_dbg_dumpkkt(ks, rxpkt); skb->protocol = eth_type_trans(skb, ks->netdev); - netif_rx(skb); + netif_rx_ni(skb); ks->netdev->stats.rx_packets++; ks->netdev->stats.rx_bytes += rxlen; @@ -538,19 +585,20 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) } /** - * ks8851_irq_work - work queue handler for dealing with interrupt requests - * @work: The work structure that was scheduled by schedule_work() + * ks8851_irq - IRQ handler for dealing with interrupt requests + * @irq: IRQ number + * @_ks: cookie * - * This is the handler invoked when the ks8851_irq() is called to find out - * what happened, as we cannot allow ourselves to sleep whilst waiting for - * anything other process has the chip's lock. + * This handler is invoked when the IRQ line asserts to find out what happened. + * As we cannot allow ourselves to sleep in HARDIRQ context, this handler runs + * in thread context. * * Read the interrupt status, work out what needs to be done and then clear * any of the interrupts that are not needed. */ -static void ks8851_irq_work(struct work_struct *work) +static irqreturn_t ks8851_irq(int irq, void *_ks) { - struct ks8851_net *ks = container_of(work, struct ks8851_net, irq_work); + struct ks8851_net *ks = _ks; unsigned status; unsigned handled = 0; @@ -561,10 +609,8 @@ static void ks8851_irq_work(struct work_struct *work) netif_dbg(ks, intr, ks->netdev, "%s: status 0x%04x\n", __func__, status); - if (status & IRQ_LCI) { - /* should do something about checking link status */ + if (status & IRQ_LCI) handled |= IRQ_LCI; - } if (status & IRQ_LDI) { u16 pmecr = ks8851_rdreg16(ks, KS_PMECR); @@ -627,10 +673,13 @@ static void ks8851_irq_work(struct work_struct *work) mutex_unlock(&ks->lock); + if (status & IRQ_LCI) + mii_check_link(&ks->mii); + if (status & IRQ_TXI) netif_wake_queue(ks->netdev); - enable_irq(ks->netdev->irq); + return IRQ_HANDLED; } /** @@ -739,26 +788,6 @@ static void ks8851_tx_work(struct work_struct *work) } /** - * ks8851_set_powermode - set power mode of the device - * @ks: The device state - * @pwrmode: The power mode value to write to KS_PMECR. - * - * Change the power mode of the chip. - */ -static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode) -{ - unsigned pmecr; - - netif_dbg(ks, hw, ks->netdev, "setting power mode %d\n", pwrmode); - - pmecr = ks8851_rdreg16(ks, KS_PMECR); - pmecr &= ~PMECR_PM_MASK; - pmecr |= pwrmode; - - ks8851_wrreg16(ks, KS_PMECR, pmecr); -} - -/** * ks8851_net_open - open network device * @dev: The network device being opened. * @@ -852,16 +881,16 @@ static int ks8851_net_stop(struct net_device *dev) netif_stop_queue(dev); mutex_lock(&ks->lock); + /* turn off the IRQs and ack any outstanding */ + ks8851_wrreg16(ks, KS_IER, 0x0000); + ks8851_wrreg16(ks, KS_ISR, 0xffff); + mutex_unlock(&ks->lock); /* stop any outstanding work */ - flush_work(&ks->irq_work); flush_work(&ks->tx_work); flush_work(&ks->rxctrl_work); - /* turn off the IRQs and ack any outstanding */ - ks8851_wrreg16(ks, KS_IER, 0x0000); - ks8851_wrreg16(ks, KS_ISR, 0xffff); - + mutex_lock(&ks->lock); /* shutdown RX process */ ks8851_wrreg16(ks, KS_RXCR1, 0x0000); @@ -870,6 +899,7 @@ static int ks8851_net_stop(struct net_device *dev) /* set powermode to soft power down to save power */ ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); + mutex_unlock(&ks->lock); /* ensure any queued tx buffers are dumped */ while (!skb_queue_empty(&ks->txq)) { @@ -881,7 +911,6 @@ static int ks8851_net_stop(struct net_device *dev) dev_kfree_skb(txb); } - mutex_unlock(&ks->lock); return 0; } @@ -1038,234 +1067,6 @@ static const struct net_device_ops ks8851_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -/* Companion eeprom access */ - -enum { /* EEPROM programming states */ - EEPROM_CONTROL, - EEPROM_ADDRESS, - EEPROM_DATA, - EEPROM_COMPLETE -}; - -/** - * ks8851_eeprom_read - read a 16bits word in ks8851 companion EEPROM - * @dev: The network device the PHY is on. - * @addr: EEPROM address to read - * - * eeprom_size: used to define the data coding length. Can be changed - * through debug-fs. - * - * Programs a read on the EEPROM using ks8851 EEPROM SW access feature. - * Warning: The READ feature is not supported on ks8851 revision 0. - * - * Rough programming model: - * - on period start: set clock high and read value on bus - * - on period / 2: set clock low and program value on bus - * - start on period / 2 - */ -unsigned int ks8851_eeprom_read(struct net_device *dev, unsigned int addr) -{ - struct ks8851_net *ks = netdev_priv(dev); - int eepcr; - int ctrl = EEPROM_OP_READ; - int state = EEPROM_CONTROL; - int bit_count = EEPROM_OP_LEN - 1; - unsigned int data = 0; - int dummy; - unsigned int addr_len; - - addr_len = (ks->eeprom_size == 128) ? 6 : 8; - - /* start transaction: chip select high, authorize write */ - mutex_lock(&ks->lock); - eepcr = EEPCR_EESA | EEPCR_EESRWA; - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - eepcr |= EEPCR_EECS; - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - mutex_unlock(&ks->lock); - - while (state != EEPROM_COMPLETE) { - /* falling clock period starts... */ - /* set EED_IO pin for control and address */ - eepcr &= ~EEPCR_EEDO; - switch (state) { - case EEPROM_CONTROL: - eepcr |= ((ctrl >> bit_count) & 1) << 2; - if (bit_count-- <= 0) { - bit_count = addr_len - 1; - state = EEPROM_ADDRESS; - } - break; - case EEPROM_ADDRESS: - eepcr |= ((addr >> bit_count) & 1) << 2; - bit_count--; - break; - case EEPROM_DATA: - /* Change to receive mode */ - eepcr &= ~EEPCR_EESRWA; - break; - } - - /* lower clock */ - eepcr &= ~EEPCR_EESCK; - - mutex_lock(&ks->lock); - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - mutex_unlock(&ks->lock); - - /* waitread period / 2 */ - udelay(EEPROM_SK_PERIOD / 2); - - /* rising clock period starts... */ - - /* raise clock */ - mutex_lock(&ks->lock); - eepcr |= EEPCR_EESCK; - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - mutex_unlock(&ks->lock); - - /* Manage read */ - switch (state) { - case EEPROM_ADDRESS: - if (bit_count < 0) { - bit_count = EEPROM_DATA_LEN - 1; - state = EEPROM_DATA; - } - break; - case EEPROM_DATA: - mutex_lock(&ks->lock); - dummy = ks8851_rdreg16(ks, KS_EEPCR); - mutex_unlock(&ks->lock); - data |= ((dummy >> EEPCR_EESB_OFFSET) & 1) << bit_count; - if (bit_count-- <= 0) - state = EEPROM_COMPLETE; - break; - } - - /* wait period / 2 */ - udelay(EEPROM_SK_PERIOD / 2); - } - - /* close transaction */ - mutex_lock(&ks->lock); - eepcr &= ~EEPCR_EECS; - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - eepcr = 0; - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - mutex_unlock(&ks->lock); - - return data; -} - -/** - * ks8851_eeprom_write - write a 16bits word in ks8851 companion EEPROM - * @dev: The network device the PHY is on. - * @op: operand (can be WRITE, EWEN, EWDS) - * @addr: EEPROM address to write - * @data: data to write - * - * eeprom_size: used to define the data coding length. Can be changed - * through debug-fs. - * - * Programs a write on the EEPROM using ks8851 EEPROM SW access feature. - * - * Note that a write enable is required before writing data. - * - * Rough programming model: - * - on period start: set clock high - * - on period / 2: set clock low and program value on bus - * - start on period / 2 - */ -void ks8851_eeprom_write(struct net_device *dev, unsigned int op, - unsigned int addr, unsigned int data) -{ - struct ks8851_net *ks = netdev_priv(dev); - int eepcr; - int state = EEPROM_CONTROL; - int bit_count = EEPROM_OP_LEN - 1; - unsigned int addr_len; - - addr_len = (ks->eeprom_size == 128) ? 6 : 8; - - switch (op) { - case EEPROM_OP_EWEN: - addr = 0x30; - break; - case EEPROM_OP_EWDS: - addr = 0; - break; - } - - /* start transaction: chip select high, authorize write */ - mutex_lock(&ks->lock); - eepcr = EEPCR_EESA | EEPCR_EESRWA; - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - eepcr |= EEPCR_EECS; - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - mutex_unlock(&ks->lock); - - while (state != EEPROM_COMPLETE) { - /* falling clock period starts... */ - /* set EED_IO pin for control and address */ - eepcr &= ~EEPCR_EEDO; - switch (state) { - case EEPROM_CONTROL: - eepcr |= ((op >> bit_count) & 1) << 2; - if (bit_count-- <= 0) { - bit_count = addr_len - 1; - state = EEPROM_ADDRESS; - } - break; - case EEPROM_ADDRESS: - eepcr |= ((addr >> bit_count) & 1) << 2; - if (bit_count-- <= 0) { - if (op == EEPROM_OP_WRITE) { - bit_count = EEPROM_DATA_LEN - 1; - state = EEPROM_DATA; - } else { - state = EEPROM_COMPLETE; - } - } - break; - case EEPROM_DATA: - eepcr |= ((data >> bit_count) & 1) << 2; - if (bit_count-- <= 0) - state = EEPROM_COMPLETE; - break; - } - - /* lower clock */ - eepcr &= ~EEPCR_EESCK; - - mutex_lock(&ks->lock); - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - mutex_unlock(&ks->lock); - - /* wait period / 2 */ - udelay(EEPROM_SK_PERIOD / 2); - - /* rising clock period starts... */ - - /* raise clock */ - eepcr |= EEPCR_EESCK; - mutex_lock(&ks->lock); - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - mutex_unlock(&ks->lock); - - /* wait period / 2 */ - udelay(EEPROM_SK_PERIOD / 2); - } - - /* close transaction */ - mutex_lock(&ks->lock); - eepcr &= ~EEPCR_EECS; - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - eepcr = 0; - ks8851_wrreg16(ks, KS_EEPCR, eepcr); - mutex_unlock(&ks->lock); - -} - /* ethtool support */ static void ks8851_get_drvinfo(struct net_device *dev, @@ -1312,115 +1113,141 @@ static int ks8851_nway_reset(struct net_device *dev) return mii_nway_restart(&ks->mii); } -static int ks8851_get_eeprom_len(struct net_device *dev) -{ - struct ks8851_net *ks = netdev_priv(dev); - return ks->eeprom_size; -} +/* EEPROM support */ -static int ks8851_get_eeprom(struct net_device *dev, - struct ethtool_eeprom *eeprom, u8 *bytes) +static void ks8851_eeprom_regread(struct eeprom_93cx6 *ee) { - struct ks8851_net *ks = netdev_priv(dev); - u16 *eeprom_buff; - int first_word; - int last_word; - int ret_val = 0; - u16 i; + struct ks8851_net *ks = ee->data; + unsigned val; - if (eeprom->len == 0) - return -EINVAL; + val = ks8851_rdreg16(ks, KS_EEPCR); - if (eeprom->len > ks->eeprom_size) - return -EINVAL; - - eeprom->magic = ks8851_rdreg16(ks, KS_CIDER); + ee->reg_data_out = (val & EEPCR_EESB) ? 1 : 0; + ee->reg_data_clock = (val & EEPCR_EESCK) ? 1 : 0; + ee->reg_chip_select = (val & EEPCR_EECS) ? 1 : 0; +} - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; +static void ks8851_eeprom_regwrite(struct eeprom_93cx6 *ee) +{ + struct ks8851_net *ks = ee->data; + unsigned val = EEPCR_EESA; /* default - eeprom access on */ + + if (ee->drive_data) + val |= EEPCR_EESRWA; + if (ee->reg_data_in) + val |= EEPCR_EEDO; + if (ee->reg_data_clock) + val |= EEPCR_EESCK; + if (ee->reg_chip_select) + val |= EEPCR_EECS; + + ks8851_wrreg16(ks, KS_EEPCR, val); +} - eeprom_buff = kmalloc(sizeof(u16) * - (last_word - first_word + 1), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; +/** + * ks8851_eeprom_claim - claim device EEPROM and activate the interface + * @ks: The network device state. + * + * Check for the presence of an EEPROM, and then activate software access + * to the device. + */ +static int ks8851_eeprom_claim(struct ks8851_net *ks) +{ + if (!(ks->rc_ccr & CCR_EEPROM)) + return -ENOENT; - for (i = 0; i < last_word - first_word + 1; i++) - eeprom_buff[i] = ks8851_eeprom_read(dev, first_word + 1); + mutex_lock(&ks->lock); - /* Device's eeprom is little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); + /* start with clock low, cs high */ + ks8851_wrreg16(ks, KS_EEPCR, EEPCR_EESA | EEPCR_EECS); + return 0; +} - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); - kfree(eeprom_buff); +/** + * ks8851_eeprom_release - release the EEPROM interface + * @ks: The device state + * + * Release the software access to the device EEPROM + */ +static void ks8851_eeprom_release(struct ks8851_net *ks) +{ + unsigned val = ks8851_rdreg16(ks, KS_EEPCR); - return ret_val; + ks8851_wrreg16(ks, KS_EEPCR, val & ~EEPCR_EESA); + mutex_unlock(&ks->lock); } +#define KS_EEPROM_MAGIC (0x00008851) + static int ks8851_set_eeprom(struct net_device *dev, - struct ethtool_eeprom *eeprom, u8 *bytes) + struct ethtool_eeprom *ee, u8 *data) { struct ks8851_net *ks = netdev_priv(dev); - u16 *eeprom_buff; - void *ptr; - int max_len; - int first_word; - int last_word; - int ret_val = 0; - u16 i; - - if (eeprom->len == 0) - return -EOPNOTSUPP; - - if (eeprom->len > ks->eeprom_size) + int offset = ee->offset; + int len = ee->len; + u16 tmp; + + /* currently only support byte writing */ + if (len != 1) + return -EINVAL; + + if (ee->magic != KS_EEPROM_MAGIC) return -EINVAL; - if (eeprom->magic != ks8851_rdreg16(ks, KS_CIDER)) - return -EFAULT; + if (ks8851_eeprom_claim(ks)) + return -ENOENT; - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - max_len = (last_word - first_word + 1) * 2; - eeprom_buff = kmalloc(max_len, GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; + eeprom_93cx6_wren(&ks->eeprom, true); - ptr = (void *)eeprom_buff; + /* ethtool currently only supports writing bytes, which means + * we have to read/modify/write our 16bit EEPROMs */ - if (eeprom->offset & 1) { - /* need read/modify/write of first changed EEPROM word */ - /* only the second byte of the word is being modified */ - eeprom_buff[0] = ks8851_eeprom_read(dev, first_word); - ptr++; + eeprom_93cx6_read(&ks->eeprom, offset/2, &tmp); + + if (offset & 1) { + tmp &= 0xff; + tmp |= *data << 8; + } else { + tmp &= 0xff00; + tmp |= *data; } - if ((eeprom->offset + eeprom->len) & 1) - /* need read/modify/write of last changed EEPROM word */ - /* only the first byte of the word is being modified */ - eeprom_buff[last_word - first_word] = - ks8851_eeprom_read(dev, last_word); + eeprom_93cx6_write(&ks->eeprom, offset/2, tmp); + eeprom_93cx6_wren(&ks->eeprom, false); - /* Device's eeprom is little-endian, word addressable */ - le16_to_cpus(&eeprom_buff[0]); - le16_to_cpus(&eeprom_buff[last_word - first_word]); + ks8851_eeprom_release(ks); - memcpy(ptr, bytes, eeprom->len); + return 0; +} - for (i = 0; i < last_word - first_word + 1; i++) - eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); +static int ks8851_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *ee, u8 *data) +{ + struct ks8851_net *ks = netdev_priv(dev); + int offset = ee->offset; + int len = ee->len; - ks8851_eeprom_write(dev, EEPROM_OP_EWEN, 0, 0); + /* must be 2 byte aligned */ + if (len & 1 || offset & 1) + return -EINVAL; - for (i = 0; i < last_word - first_word + 1; i++) { - ks8851_eeprom_write(dev, EEPROM_OP_WRITE, first_word + i, - eeprom_buff[i]); - mdelay(EEPROM_WRITE_TIME); - } + if (ks8851_eeprom_claim(ks)) + return -ENOENT; - ks8851_eeprom_write(dev, EEPROM_OP_EWDS, 0, 0); + ee->magic = KS_EEPROM_MAGIC; - kfree(eeprom_buff); - return ret_val; + eeprom_93cx6_multiread(&ks->eeprom, offset/2, (__le16 *)data, len/2); + ks8851_eeprom_release(ks); + + return 0; +} + +static int ks8851_get_eeprom_len(struct net_device *dev) +{ + struct ks8851_net *ks = netdev_priv(dev); + + /* currently, we assume it is an 93C46 attached, so return 128 */ + return ks->rc_ccr & CCR_EEPROM ? 128 : 0; } static const struct ethtool_ops ks8851_ethtool_ops = { @@ -1546,48 +1373,48 @@ static int ks8851_read_selftest(struct ks8851_net *ks) /* driver bus management functions */ -#ifdef CONFIG_PM -static int ks8851_suspend(struct spi_device *spi, pm_message_t state) +#ifdef CONFIG_PM_SLEEP + +static int ks8851_suspend(struct device *dev) { - struct ks8851_net *ks = dev_get_drvdata(&spi->dev); - struct net_device *dev = ks->netdev; + struct ks8851_net *ks = dev_get_drvdata(dev); + struct net_device *netdev = ks->netdev; - if (netif_running(dev)) { - netif_device_detach(dev); - ks8851_net_stop(dev); + if (netif_running(netdev)) { + netif_device_detach(netdev); + ks8851_net_stop(netdev); } return 0; } -static int ks8851_resume(struct spi_device *spi) +static int ks8851_resume(struct device *dev) { - struct ks8851_net *ks = dev_get_drvdata(&spi->dev); - struct net_device *dev = ks->netdev; + struct ks8851_net *ks = dev_get_drvdata(dev); + struct net_device *netdev = ks->netdev; - if (netif_running(dev)) { - ks8851_net_open(dev); - netif_device_attach(dev); + if (netif_running(netdev)) { + ks8851_net_open(netdev); + netif_device_attach(netdev); } return 0; } -#else -#define ks8851_suspend NULL -#define ks8851_resume NULL #endif -static int __devinit ks8851_probe(struct spi_device *spi) +static SIMPLE_DEV_PM_OPS(ks8851_pm_ops, ks8851_suspend, ks8851_resume); + +static int ks8851_probe(struct spi_device *spi) { struct net_device *ndev; struct ks8851_net *ks; int ret; + unsigned cider; + int gpio; ndev = alloc_etherdev(sizeof(struct ks8851_net)); - if (!ndev) { - dev_err(&spi->dev, "failed to alloc ethernet device\n"); + if (!ndev) return -ENOMEM; - } spi->bits_per_word = 8; @@ -1597,11 +1424,58 @@ static int __devinit ks8851_probe(struct spi_device *spi) ks->spidev = spi; ks->tx_space = 6144; + gpio = of_get_named_gpio_flags(spi->dev.of_node, "reset-gpios", + 0, NULL); + if (gpio == -EPROBE_DEFER) { + ret = gpio; + goto err_gpio; + } + + ks->gpio = gpio; + if (gpio_is_valid(gpio)) { + ret = devm_gpio_request_one(&spi->dev, gpio, + GPIOF_OUT_INIT_LOW, "ks8851_rst_n"); + if (ret) { + dev_err(&spi->dev, "reset gpio request failed\n"); + goto err_gpio; + } + } + + ks->vdd_io = devm_regulator_get(&spi->dev, "vdd-io"); + if (IS_ERR(ks->vdd_io)) { + ret = PTR_ERR(ks->vdd_io); + goto err_reg_io; + } + + ret = regulator_enable(ks->vdd_io); + if (ret) { + dev_err(&spi->dev, "regulator vdd_io enable fail: %d\n", + ret); + goto err_reg_io; + } + + ks->vdd_reg = devm_regulator_get(&spi->dev, "vdd"); + if (IS_ERR(ks->vdd_reg)) { + ret = PTR_ERR(ks->vdd_reg); + goto err_reg; + } + + ret = regulator_enable(ks->vdd_reg); + if (ret) { + dev_err(&spi->dev, "regulator vdd enable fail: %d\n", + ret); + goto err_reg; + } + + if (gpio_is_valid(gpio)) { + usleep_range(10000, 11000); + gpio_set_value(gpio, 1); + } + mutex_init(&ks->lock); spin_lock_init(&ks->statelock); INIT_WORK(&ks->tx_work, ks8851_tx_work); - INIT_WORK(&ks->irq_work, ks8851_irq_work); INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work); /* initialise pre-made spi transfer messages */ @@ -1613,6 +1487,13 @@ static int __devinit ks8851_probe(struct spi_device *spi) spi_message_add_tail(&ks->spi_xfer2[0], &ks->spi_msg2); spi_message_add_tail(&ks->spi_xfer2[1], &ks->spi_msg2); + /* setup EEPROM state */ + + ks->eeprom.data = ks; + ks->eeprom.width = PCI_EEPROM_WIDTH_93C46; + ks->eeprom.register_read = ks8851_eeprom_regread; + ks->eeprom.register_write = ks8851_eeprom_regwrite; + /* setup mii state */ ks->mii.dev = ndev; ks->mii.phy_id = 1, @@ -1630,10 +1511,10 @@ static int __devinit ks8851_probe(struct spi_device *spi) skb_queue_head_init(&ks->txq); - SET_ETHTOOL_OPS(ndev, &ks8851_ethtool_ops); + ndev->ethtool_ops = &ks8851_ethtool_ops; SET_NETDEV_DEV(ndev, &spi->dev); - dev_set_drvdata(&spi->dev, ks); + spi_set_drvdata(spi, ks); ndev->if_port = IF_PORT_100BASET; ndev->netdev_ops = &ks8851_netdev_ops; @@ -1643,8 +1524,8 @@ static int __devinit ks8851_probe(struct spi_device *spi) ks8851_soft_reset(ks, GRR_GSR); /* simple check for a valid chip being connected to the bus */ - - if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) { + cider = ks8851_rdreg16(ks, KS_CIDER); + if ((cider & ~CIDER_REV_MASK) != CIDER_ID) { dev_err(&spi->dev, "failed to read device ID\n"); ret = -ENODEV; goto err_id; @@ -1661,8 +1542,9 @@ static int __devinit ks8851_probe(struct spi_device *spi) ks8851_read_selftest(ks); ks8851_init_mac(ks); - ret = request_irq(spi->irq, ks8851_irq, IRQF_TRIGGER_LOW, - ndev->name, ks); + ret = request_threaded_irq(spi->irq, NULL, ks8851_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + ndev->name, ks); if (ret < 0) { dev_err(&spi->dev, "failed to get irq\n"); goto err_irq; @@ -1674,59 +1556,63 @@ static int __devinit ks8851_probe(struct spi_device *spi) goto err_netdev; } - netdev_info(ndev, "revision %d, MAC %pM, IRQ %d\n", - CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)), - ndev->dev_addr, ndev->irq); + netdev_info(ndev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n", + CIDER_REV_GET(cider), ndev->dev_addr, ndev->irq, + ks->rc_ccr & CCR_EEPROM ? "has" : "no"); return 0; err_netdev: - free_irq(ndev->irq, ndev); + free_irq(ndev->irq, ks); -err_id: err_irq: + if (gpio_is_valid(gpio)) + gpio_set_value(gpio, 0); +err_id: + regulator_disable(ks->vdd_reg); +err_reg: + regulator_disable(ks->vdd_io); +err_reg_io: +err_gpio: free_netdev(ndev); return ret; } -static int __devexit ks8851_remove(struct spi_device *spi) +static int ks8851_remove(struct spi_device *spi) { - struct ks8851_net *priv = dev_get_drvdata(&spi->dev); + struct ks8851_net *priv = spi_get_drvdata(spi); if (netif_msg_drv(priv)) dev_info(&spi->dev, "remove\n"); unregister_netdev(priv->netdev); free_irq(spi->irq, priv); + if (gpio_is_valid(priv->gpio)) + gpio_set_value(priv->gpio, 0); + regulator_disable(priv->vdd_reg); + regulator_disable(priv->vdd_io); free_netdev(priv->netdev); return 0; } +static const struct of_device_id ks8851_match_table[] = { + { .compatible = "micrel,ks8851" }, + { } +}; + static struct spi_driver ks8851_driver = { .driver = { .name = "ks8851", + .of_match_table = ks8851_match_table, .owner = THIS_MODULE, + .pm = &ks8851_pm_ops, }, .probe = ks8851_probe, - .remove = __devexit_p(ks8851_remove), - .suspend = ks8851_suspend, - .resume = ks8851_resume, + .remove = ks8851_remove, }; - -static int __init ks8851_init(void) -{ - return spi_register_driver(&ks8851_driver); -} - -static void __exit ks8851_exit(void) -{ - spi_unregister_driver(&ks8851_driver); -} - -module_init(ks8851_init); -module_exit(ks8851_exit); +module_spi_driver(ks8851_driver); MODULE_DESCRIPTION("KS8851 Network driver"); MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); diff --git a/drivers/net/ethernet/micrel/ks8851.h b/drivers/net/ethernet/micrel/ks8851.h index 537fb06e593..852256ef1f2 100644 --- a/drivers/net/ethernet/micrel/ks8851.h +++ b/drivers/net/ethernet/micrel/ks8851.h @@ -1,4 +1,4 @@ -/* drivers/net/ks8851.h +/* drivers/net/ethernet/micrel/ks8851.h * * Copyright 2009 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> @@ -16,7 +16,7 @@ #define CCR_32PIN (1 << 0) /* MAC address registers */ -#define KS_MAR(_m) 0x15 - (_m) +#define KS_MAR(_m) (0x15 - (_m)) #define KS_MARL 0x10 #define KS_MARM 0x12 #define KS_MARH 0x14 @@ -27,22 +27,11 @@ #define KS_EEPCR 0x22 #define EEPCR_EESRWA (1 << 5) #define EEPCR_EESA (1 << 4) -#define EEPCR_EESB_OFFSET 3 -#define EEPCR_EESB (1 << EEPCR_EESB_OFFSET) +#define EEPCR_EESB (1 << 3) #define EEPCR_EEDO (1 << 2) #define EEPCR_EESCK (1 << 1) #define EEPCR_EECS (1 << 0) -#define EEPROM_OP_LEN 3 /* bits:*/ -#define EEPROM_OP_READ 0x06 -#define EEPROM_OP_EWEN 0x04 -#define EEPROM_OP_WRITE 0x05 -#define EEPROM_OP_EWDS 0x14 - -#define EEPROM_DATA_LEN 16 /* 16 bits EEPROM */ -#define EEPROM_WRITE_TIME 4 /* wrt ack time in ms */ -#define EEPROM_SK_PERIOD 400 /* in us */ - #define KS_MBIR 0x24 #define MBIR_TXMBF (1 << 12) #define MBIR_TXMBFA (1 << 11) diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index 77241b618c7..c83d16dc7cd 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -1,5 +1,5 @@ /** - * drivers/net/ks8851_mll.c + * drivers/net/ethernet/micrel/ks8851_mll.c * Copyright (c) 2009 Micrel Inc. * * This program is free software; you can redistribute it and/or modify @@ -16,8 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/** - * Supports: +/* Supports: * KS8851 16bit MLL chip from Micrel Inc. */ @@ -35,7 +34,10 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/ks8851_mll.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_net.h> #define DRV_NAME "ks8851_mll" @@ -394,7 +396,6 @@ union ks_tx_hdr { * @msg_enable : The message flags controlling driver output (see ethtool). * @frame_cnt : number of frames received. * @bus_width : i/o bus width. - * @irq : irq number assigned to this device. * @rc_rxqcr : Cached copy of KS_RXQCR. * @rc_txcr : Cached copy of KS_TXCR. * @rc_ier : Cached copy of KS_IER. @@ -441,7 +442,6 @@ struct ks_net { u32 msg_enable; u32 frame_cnt; int bus_width; - int irq; u16 rc_rxqcr; u16 rc_txcr; @@ -467,8 +467,7 @@ static int msg_enable; #define BE1 0x2000 /* Byte Enable 1 */ #define BE0 0x1000 /* Byte Enable 0 */ -/** - * register read/write calls. +/* register read/write calls. * * All these calls issue transactions to access the chip's registers. They * all require that the necessary lock is held to prevent accesses when the @@ -689,7 +688,7 @@ static void ks_soft_reset(struct ks_net *ks, unsigned op) } -void ks_enable_qmu(struct ks_net *ks) +static void ks_enable_qmu(struct ks_net *ks) { u16 w; @@ -796,20 +795,35 @@ static void ks_rcv(struct ks_net *ks, struct net_device *netdev) frame_hdr = ks->frame_head_info; while (ks->frame_cnt--) { - skb = dev_alloc_skb(frame_hdr->len + 16); - if (likely(skb && (frame_hdr->sts & RXFSHR_RXFV) && - (frame_hdr->len < RX_BUF_SIZE) && frame_hdr->len)) { + if (unlikely(!(frame_hdr->sts & RXFSHR_RXFV) || + frame_hdr->len >= RX_BUF_SIZE || + frame_hdr->len <= 0)) { + + /* discard an invalid packet */ + ks_wrreg16(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_RRXEF)); + netdev->stats.rx_dropped++; + if (!(frame_hdr->sts & RXFSHR_RXFV)) + netdev->stats.rx_frame_errors++; + else + netdev->stats.rx_length_errors++; + frame_hdr++; + continue; + } + + skb = netdev_alloc_skb(netdev, frame_hdr->len + 16); + if (likely(skb)) { skb_reserve(skb, 2); /* read data block including CRC 4 bytes */ ks_read_qmu(ks, (u16 *)skb->data, frame_hdr->len); - skb_put(skb, frame_hdr->len); + skb_put(skb, frame_hdr->len - 4); skb->protocol = eth_type_trans(skb, netdev); netif_rx(skb); + /* exclude CRC size */ + netdev->stats.rx_bytes += frame_hdr->len - 4; + netdev->stats.rx_packets++; } else { - pr_err("%s: err:skb alloc\n", __func__); ks_wrreg16(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_RRXEF)); - if (skb) - dev_kfree_skb_irq(skb); + netdev->stats.rx_dropped++; } frame_hdr++; } @@ -839,7 +853,7 @@ static void ks_update_link_status(struct net_device *netdev, struct ks_net *ks) /** * ks_irq - device interrupt handler - * @irq: Interrupt number passed from the IRQ hnalder. + * @irq: Interrupt number passed from the IRQ handler. * @pw: The private word passed to register_irq(), our struct ks_net. * * This is the handler invoked to find out what happened @@ -881,6 +895,8 @@ static irqreturn_t ks_irq(int irq, void *pw) ks_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK); } + if (unlikely(status & IRQ_RXOI)) + ks->netdev->stats.rx_over_errors++; /* this should be the last in IRQ handler*/ ks_restore_cmd_reg(ks); return IRQ_HANDLED; @@ -899,7 +915,7 @@ static int ks_net_open(struct net_device *netdev) struct ks_net *ks = netdev_priv(netdev); int err; -#define KS_INT_FLAGS (IRQF_DISABLED|IRQF_TRIGGER_LOW) +#define KS_INT_FLAGS IRQF_TRIGGER_LOW /* lock the card, even if we may not actually do anything * else at the moment. */ @@ -907,10 +923,10 @@ static int ks_net_open(struct net_device *netdev) netif_dbg(ks, ifup, ks->netdev, "%s - entry\n", __func__); /* reset the HW */ - err = request_irq(ks->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, netdev); + err = request_irq(netdev->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, netdev); if (err) { - pr_err("Failed to request IRQ: %d: %d\n", ks->irq, err); + pr_err("Failed to request IRQ: %d: %d\n", netdev->irq, err); return err; } @@ -955,7 +971,7 @@ static int ks_net_stop(struct net_device *netdev) /* set powermode to soft power down to save power */ ks_set_powermode(ks, PMECR_PM_SOFTDOWN); - free_irq(ks->irq, netdev); + free_irq(netdev->irq, netdev); mutex_unlock(&ks->lock); return 0; } @@ -1019,6 +1035,9 @@ static int ks_start_xmit(struct sk_buff *skb, struct net_device *netdev) if (likely(ks_tx_fifo_space(ks) >= skb->len + 12)) { ks_write_qmu(ks, skb->data, skb->len); + /* add tx statistics */ + netdev->stats.tx_bytes += skb->len; + netdev->stats.tx_packets++; dev_kfree_skb(skb); } else retv = NETDEV_TX_BUSY; @@ -1105,7 +1124,7 @@ static void ks_set_grpaddr(struct ks_net *ks) } } /* ks_set_grpaddr */ -/* +/** * ks_clear_mcast - clear multicast information * * @ks : The chip information @@ -1229,7 +1248,7 @@ static void ks_set_mac(struct ks_net *ks, u8 *data) w = ((u & 0xFF) << 8) | ((u >> 8) & 0xFF); ks_wrreg16(ks, KS_MARL, w); - memcpy(ks->mac_addr, data, 6); + memcpy(ks->mac_addr, data, ETH_ALEN); if (ks->enabled) ks_start_rx(ks); @@ -1500,25 +1519,30 @@ static int ks_hw_init(struct ks_net *ks) ks->all_mcast = 0; ks->mcast_lst_size = 0; - ks->frame_head_info = (struct type_frame_head *) \ - kmalloc(MHEADER_SIZE, GFP_KERNEL); - if (!ks->frame_head_info) { - pr_err("Error: Fail to allocate frame memory\n"); + ks->frame_head_info = kmalloc(MHEADER_SIZE, GFP_KERNEL); + if (!ks->frame_head_info) return false; - } ks_set_mac(ks, KS_DEFAULT_MAC_ADDRESS); return true; } +#if defined(CONFIG_OF) +static const struct of_device_id ks8851_ml_dt_ids[] = { + { .compatible = "micrel,ks8851-mll" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ks8851_ml_dt_ids); +#endif -static int __devinit ks8851_probe(struct platform_device *pdev) +static int ks8851_probe(struct platform_device *pdev) { int err = -ENOMEM; struct resource *io_d, *io_c; struct net_device *netdev; struct ks_net *ks; u16 id, data; + const char *mac; io_d = platform_get_resource(pdev, IORESOURCE_MEM, 0); io_c = platform_get_resource(pdev, IORESOURCE_MEM, 1); @@ -1546,10 +1570,10 @@ static int __devinit ks8851_probe(struct platform_device *pdev) if (!ks->hw_addr_cmd) goto err_ioremap1; - ks->irq = platform_get_irq(pdev, 0); + netdev->irq = platform_get_irq(pdev, 0); - if (ks->irq < 0) { - err = ks->irq; + if ((int)netdev->irq < 0) { + err = netdev->irq; goto err_get_irq; } @@ -1600,17 +1624,35 @@ static int __devinit ks8851_probe(struct platform_device *pdev) ks_disable_qmu(ks); ks_setup(ks); ks_setup_int(ks); - memcpy(netdev->dev_addr, ks->mac_addr, 6); data = ks_rdreg16(ks, KS_OBCR); ks_wrreg16(ks, KS_OBCR, data | OBCR_ODS_16MA); - /** - * If you want to use the default MAC addr, - * comment out the 2 functions below. - */ + /* overwriting the default MAC address */ + if (pdev->dev.of_node) { + mac = of_get_mac_address(pdev->dev.of_node); + if (mac) + memcpy(ks->mac_addr, mac, ETH_ALEN); + } else { + struct ks8851_mll_platform_data *pdata; + + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) { + netdev_err(netdev, "No platform data\n"); + err = -ENODEV; + goto err_pdata; + } + memcpy(ks->mac_addr, pdata->mac_addr, ETH_ALEN); + } + if (!is_valid_ether_addr(ks->mac_addr)) { + /* Use random MAC address if none passed */ + eth_random_addr(ks->mac_addr); + netdev_info(netdev, "Using random mac address\n"); + } + netdev_info(netdev, "Mac address is: %pM\n", ks->mac_addr); + + memcpy(netdev->dev_addr, ks->mac_addr, ETH_ALEN); - random_ether_addr(netdev->dev_addr); ks_set_mac(ks, netdev->dev_addr); id = ks_rdreg16(ks, KS_CIDER); @@ -1619,6 +1661,8 @@ static int __devinit ks8851_probe(struct platform_device *pdev) (id >> 8) & 0xff, (id >> 4) & 0xf, (id >> 1) & 0x7); return 0; +err_pdata: + unregister_netdev(netdev); err_register: err_get_irq: iounmap(ks->hw_addr_cmd); @@ -1634,7 +1678,7 @@ err_mem_region: return err; } -static int __devexit ks8851_remove(struct platform_device *pdev) +static int ks8851_remove(struct platform_device *pdev) { struct net_device *netdev = platform_get_drvdata(pdev); struct ks_net *ks = netdev_priv(netdev); @@ -1645,7 +1689,6 @@ static int __devexit ks8851_remove(struct platform_device *pdev) iounmap(ks->hw_addr); free_netdev(netdev); release_mem_region(iomem->start, resource_size(iomem)); - platform_set_drvdata(pdev, NULL); return 0; } @@ -1654,23 +1697,13 @@ static struct platform_driver ks8851_platform_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ks8851_ml_dt_ids), }, .probe = ks8851_probe, - .remove = __devexit_p(ks8851_remove), + .remove = ks8851_remove, }; -static int __init ks8851_init(void) -{ - return platform_driver_register(&ks8851_platform_driver); -} - -static void __exit ks8851_exit(void) -{ - platform_driver_unregister(&ks8851_platform_driver); -} - -module_init(ks8851_init); -module_exit(ks8851_exit); +module_platform_driver(ks8851_platform_driver); MODULE_DESCRIPTION("KS8851 MLL Network driver"); MODULE_AUTHOR("David Choi <david.choi@micrel.com>"); diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 4b9f4bd14ae..064a48d0c36 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -1,5 +1,5 @@ /** - * drivers/net/ksx884x.c - Micrel KSZ8841/2 PCI Ethernet driver + * drivers/net/ethernet/micrel/ksx884x.c - Micrel KSZ8841/2 PCI Ethernet driver * * Copyright (c) 2009-2010 Micrel, Inc. * Tristram Ha <Tristram.Ha@micrel.com> @@ -743,11 +743,10 @@ /* Change default LED mode. */ #define SET_DEFAULT_LED LED_SPEED_DUPLEX_ACT -#define MAC_ADDR_LEN 6 -#define MAC_ADDR_ORDER(i) (MAC_ADDR_LEN - 1 - (i)) +#define MAC_ADDR_ORDER(i) (ETH_ALEN - 1 - (i)) #define MAX_ETHERNET_BODY_SIZE 1500 -#define ETHERNET_HEADER_SIZE 14 +#define ETHERNET_HEADER_SIZE (14 + VLAN_HLEN) #define MAX_ETHERNET_PACKET_SIZE \ (MAX_ETHERNET_BODY_SIZE + ETHERNET_HEADER_SIZE) @@ -1043,7 +1042,7 @@ enum { * @valid: Valid setting indicating the entry is being used. */ struct ksz_mac_table { - u8 mac_addr[MAC_ADDR_LEN]; + u8 mac_addr[ETH_ALEN]; u16 vid; u8 fid; u8 ports; @@ -1187,8 +1186,8 @@ struct ksz_switch { u8 diffserv[DIFFSERV_ENTRIES]; u8 p_802_1p[PRIO_802_1P_ENTRIES]; - u8 br_addr[MAC_ADDR_LEN]; - u8 other_addr[MAC_ADDR_LEN]; + u8 br_addr[ETH_ALEN]; + u8 other_addr[ETH_ALEN]; u8 broad_per; u8 member; @@ -1292,14 +1291,14 @@ struct ksz_hw { int tx_int_mask; int tx_size; - u8 perm_addr[MAC_ADDR_LEN]; - u8 override_addr[MAC_ADDR_LEN]; - u8 address[ADDITIONAL_ENTRIES][MAC_ADDR_LEN]; + u8 perm_addr[ETH_ALEN]; + u8 override_addr[ETH_ALEN]; + u8 address[ADDITIONAL_ENTRIES][ETH_ALEN]; u8 addr_list_size; u8 mac_override; u8 promiscuous; u8 all_multi; - u8 multi_list[MAX_MULTICAST_LIST][MAC_ADDR_LEN]; + u8 multi_list[MAX_MULTICAST_LIST][ETH_ALEN]; u8 multi_bits[HW_MULTICAST_SIZE]; u8 multi_list_size; @@ -1488,7 +1487,7 @@ struct dev_priv { #define DRV_VERSION "1.0.0" #define DRV_RELDATE "Feb 8, 2010" -static char version[] __devinitdata = +static char version[] = "Micrel " DEVICE_NAME " " DRV_VERSION " (" DRV_RELDATE ")"; static u8 DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x88, 0x42, 0x01 }; @@ -3654,7 +3653,7 @@ static void hw_add_wol_bcast(struct ksz_hw *hw) static const u8 mask[] = { 0x3F }; static const u8 pattern[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - hw_set_wol_frame(hw, 2, 1, mask, MAC_ADDR_LEN, pattern); + hw_set_wol_frame(hw, 2, 1, mask, ETH_ALEN, pattern); } /** @@ -3689,7 +3688,7 @@ static void hw_add_wol_ucast(struct ksz_hw *hw) { static const u8 mask[] = { 0x3F }; - hw_set_wol_frame(hw, 0, 1, mask, MAC_ADDR_LEN, hw->override_addr); + hw_set_wol_frame(hw, 0, 1, mask, ETH_ALEN, hw->override_addr); } /** @@ -3914,7 +3913,7 @@ static void hw_start_rx(struct ksz_hw *hw) hw->rx_stop = 2; } -/* +/** * hw_stop_rx - stop receiving * @hw: The hardware instance. * @@ -4055,7 +4054,7 @@ static void hw_set_addr(struct ksz_hw *hw) { int i; - for (i = 0; i < MAC_ADDR_LEN; i++) + for (i = 0; i < ETH_ALEN; i++) writeb(hw->override_addr[MAC_ADDR_ORDER(i)], hw->io + KS884X_ADDR_0_OFFSET + i); @@ -4072,17 +4071,16 @@ static void hw_read_addr(struct ksz_hw *hw) { int i; - for (i = 0; i < MAC_ADDR_LEN; i++) + for (i = 0; i < ETH_ALEN; i++) hw->perm_addr[MAC_ADDR_ORDER(i)] = readb(hw->io + KS884X_ADDR_0_OFFSET + i); if (!hw->mac_override) { - memcpy(hw->override_addr, hw->perm_addr, MAC_ADDR_LEN); + memcpy(hw->override_addr, hw->perm_addr, ETH_ALEN); if (empty_addr(hw->override_addr)) { - memcpy(hw->perm_addr, DEFAULT_MAC_ADDRESS, - MAC_ADDR_LEN); + memcpy(hw->perm_addr, DEFAULT_MAC_ADDRESS, ETH_ALEN); memcpy(hw->override_addr, DEFAULT_MAC_ADDRESS, - MAC_ADDR_LEN); + ETH_ALEN); hw->override_addr[5] += hw->id; hw_set_addr(hw); } @@ -4130,16 +4128,16 @@ static int hw_add_addr(struct ksz_hw *hw, u8 *mac_addr) int i; int j = ADDITIONAL_ENTRIES; - if (!memcmp(hw->override_addr, mac_addr, MAC_ADDR_LEN)) + if (ether_addr_equal(hw->override_addr, mac_addr)) return 0; for (i = 0; i < hw->addr_list_size; i++) { - if (!memcmp(hw->address[i], mac_addr, MAC_ADDR_LEN)) + if (ether_addr_equal(hw->address[i], mac_addr)) return 0; if (ADDITIONAL_ENTRIES == j && empty_addr(hw->address[i])) j = i; } if (j < ADDITIONAL_ENTRIES) { - memcpy(hw->address[j], mac_addr, MAC_ADDR_LEN); + memcpy(hw->address[j], mac_addr, ETH_ALEN); hw_ena_add_addr(hw, j, hw->address[j]); return 0; } @@ -4151,8 +4149,8 @@ static int hw_del_addr(struct ksz_hw *hw, u8 *mac_addr) int i; for (i = 0; i < hw->addr_list_size; i++) { - if (!memcmp(hw->address[i], mac_addr, MAC_ADDR_LEN)) { - memset(hw->address[i], 0, MAC_ADDR_LEN); + if (ether_addr_equal(hw->address[i], mac_addr)) { + memset(hw->address[i], 0, ETH_ALEN); writel(0, hw->io + ADD_ADDR_INCR * i + KS_ADD_ADDR_0_HI); return 0; @@ -4382,12 +4380,10 @@ static void ksz_update_timer(struct ksz_timer_info *info) */ static int ksz_alloc_soft_desc(struct ksz_desc_info *desc_info, int transmit) { - desc_info->ring = kmalloc(sizeof(struct ksz_desc) * desc_info->alloc, - GFP_KERNEL); + desc_info->ring = kzalloc(sizeof(struct ksz_desc) * desc_info->alloc, + GFP_KERNEL); if (!desc_info->ring) return 1; - memset((void *) desc_info->ring, 0, - sizeof(struct ksz_desc) * desc_info->alloc); hw_init_desc(desc_info, transmit); return 0; } @@ -4484,14 +4480,12 @@ static void ksz_init_rx_buffers(struct dev_info *adapter) dma_buf->len = adapter->mtu; if (!dma_buf->skb) dma_buf->skb = alloc_skb(dma_buf->len, GFP_ATOMIC); - if (dma_buf->skb && !dma_buf->dma) { - dma_buf->skb->dev = adapter->dev; + if (dma_buf->skb && !dma_buf->dma) dma_buf->dma = pci_map_single( adapter->pdev, skb_tail_pointer(dma_buf->skb), dma_buf->len, PCI_DMA_FROMDEVICE); - } /* Set descriptor. */ set_rx_buf(desc, dma_buf->dma); @@ -4767,7 +4761,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal) struct ksz_dma_buf *dma_buf; struct net_device *dev = NULL; - spin_lock(&hw_priv->hwlock); + spin_lock_irq(&hw_priv->hwlock); last = info->last; while (info->avail < info->alloc) { @@ -4801,7 +4795,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal) info->avail++; } info->last = last; - spin_unlock(&hw_priv->hwlock); + spin_unlock_irq(&hw_priv->hwlock); /* Notify the network subsystem that the packet has been sent. */ if (dev) @@ -4838,7 +4832,7 @@ static inline void copy_old_skb(struct sk_buff *old, struct sk_buff *skb) skb->csum = old->csum; skb_set_network_header(skb, ETH_HLEN); - dev_kfree_skb(old); + dev_consume_skb_any(old); } /** @@ -4867,7 +4861,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev) memset(&skb->data[skb->len], 0, 50 - skb->len); skb->len = 50; } else { - skb = dev_alloc_skb(50); + skb = netdev_alloc_skb(dev, 50); if (!skb) return NETDEV_TX_BUSY; memcpy(skb->data, org_skb->data, org_skb->len); @@ -4885,11 +4879,11 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev) left = hw_alloc_pkt(hw, skb->len, num); if (left) { if (left < num || - ((CHECKSUM_PARTIAL == skb->ip_summed) && - (ETH_P_IPV6 == htons(skb->protocol)))) { + (CHECKSUM_PARTIAL == skb->ip_summed && + skb->protocol == htons(ETH_P_IPV6))) { struct sk_buff *org_skb = skb; - skb = dev_alloc_skb(org_skb->len); + skb = netdev_alloc_skb(dev, org_skb->len); if (!skb) { rc = NETDEV_TX_BUSY; goto unlock; @@ -4936,7 +4930,7 @@ static void netdev_tx_timeout(struct net_device *dev) * Only reset the hardware if time between calls is long * enough. */ - if (jiffies - last_reset <= dev->watchdog_timeo) + if (time_before_eq(jiffies, last_reset + dev->watchdog_timeo)) hw_priv = NULL; } @@ -5023,7 +5017,7 @@ static inline int rx_proc(struct net_device *dev, struct ksz_hw* hw, do { /* skb->data != skb->head */ - skb = dev_alloc_skb(packet_len + 2); + skb = netdev_alloc_skb(dev, packet_len + 2); if (!skb) { dev->stats.rx_dropped++; return -ENOMEM; @@ -5265,11 +5259,15 @@ static irqreturn_t netdev_intr(int irq, void *dev_id) struct dev_info *hw_priv = priv->adapter; struct ksz_hw *hw = &hw_priv->hw; + spin_lock(&hw_priv->hwlock); + hw_read_intr(hw, &int_enable); /* Not our interrupt! */ - if (!int_enable) + if (!int_enable) { + spin_unlock(&hw_priv->hwlock); return IRQ_NONE; + } do { hw_ack_intr(hw, int_enable); @@ -5316,6 +5314,8 @@ static irqreturn_t netdev_intr(int irq, void *dev_id) hw_ena_intr(hw); + spin_unlock(&hw_priv->hwlock); + return IRQ_HANDLED; } @@ -5413,8 +5413,8 @@ static int netdev_close(struct net_device *dev) /* Delay for receive task to stop scheduling itself. */ msleep(2000 / HZ); - tasklet_disable(&hw_priv->rx_tasklet); - tasklet_disable(&hw_priv->tx_tasklet); + tasklet_kill(&hw_priv->rx_tasklet); + tasklet_kill(&hw_priv->tx_tasklet); free_irq(dev->irq, hw_priv->dev); transmit_cleanup(hw_priv, 0); @@ -5465,8 +5465,10 @@ static int prepare_hardware(struct net_device *dev) rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev); if (rc) return rc; - tasklet_enable(&hw_priv->rx_tasklet); - tasklet_enable(&hw_priv->tx_tasklet); + tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, + (unsigned long) hw_priv); + tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, + (unsigned long) hw_priv); hw->promiscuous = 0; hw->all_multi = 0; @@ -5676,7 +5678,7 @@ static int netdev_set_mac_address(struct net_device *dev, void *addr) hw_del_addr(hw, dev->dev_addr); else { hw->mac_override = 1; - memcpy(hw->override_addr, mac->sa_data, MAC_ADDR_LEN); + memcpy(hw->override_addr, mac->sa_data, ETH_ALEN); } memcpy(dev->dev_addr, mac->sa_data, ETH_ALEN); @@ -5786,7 +5788,7 @@ static void netdev_set_rx_mode(struct net_device *dev) netdev_for_each_mc_addr(ha, dev) { if (i >= MAX_MULTICAST_LIST) break; - memcpy(hw->multi_list[i++], ha->addr, MAC_ADDR_LEN); + memcpy(hw->multi_list[i++], ha->addr, ETH_ALEN); } hw->multi_list_size = (u8) i; hw_set_grp_addr(hw); @@ -5851,15 +5853,12 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) struct dev_info *hw_priv = priv->adapter; struct ksz_hw *hw = &hw_priv->hw; struct ksz_port *port = &priv->port; - int rc; int result = 0; struct mii_ioctl_data *data = if_mii(ifr); if (down_interruptible(&priv->proc_sem)) return -ERESTARTSYS; - /* assume success */ - rc = 0; switch (cmd) { /* Get address of MII PHY in use. */ case SIOCGMIIPHY: @@ -6093,9 +6092,10 @@ static void netdev_get_drvinfo(struct net_device *dev, struct dev_priv *priv = netdev_priv(dev); struct dev_info *hw_priv = priv->adapter; - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(hw_priv->pdev)); + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + strlcpy(info->bus_info, pci_name(hw_priv->pdev), + sizeof(info->bus_info)); } /** @@ -6587,7 +6587,8 @@ static void netdev_get_ethtool_stats(struct net_device *dev, * * Return 0 if successful; otherwise an error code. */ -static int netdev_set_features(struct net_device *dev, u32 features) +static int netdev_set_features(struct net_device *dev, + netdev_features_t features) { struct dev_priv *priv = netdev_priv(dev); struct dev_info *hw_priv = priv->adapter; @@ -6609,7 +6610,7 @@ static int netdev_set_features(struct net_device *dev, u32 features) return 0; } -static struct ethtool_ops netdev_ethtool_ops = { +static const struct ethtool_ops netdev_ethtool_ops = { .get_settings = netdev_get_settings, .set_settings = netdev_set_settings, .nway_reset = netdev_nway_reset, @@ -6771,7 +6772,7 @@ static int stp; /* * This enables fast aging in the KSZ8842 switch. Not sure what situation * needs that. However, fast aging is used to flush the dynamic MAC table when - * STP suport is enabled. + * STP support is enabled. */ static int fast_aging; @@ -6860,7 +6861,7 @@ static void get_mac_addr(struct dev_info *hw_priv, u8 *macaddr, int port) int num; i = j = num = got_num = 0; - while (j < MAC_ADDR_LEN) { + while (j < ETH_ALEN) { if (macaddr[i]) { int digit; @@ -6891,7 +6892,7 @@ static void get_mac_addr(struct dev_info *hw_priv, u8 *macaddr, int port) } i++; } - if (MAC_ADDR_LEN == j) { + if (ETH_ALEN == j) { if (MAIN_PORT == port) hw_priv->hw.mac_override = 1; } @@ -6921,8 +6922,7 @@ static void read_other_addr(struct ksz_hw *hw) #define PCI_VENDOR_ID_MICREL_KS 0x16c6 #endif -static int __devinit pcidev_init(struct pci_dev *pdev, - const struct pci_device_id *id) +static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id) { struct net_device *dev; struct dev_priv *priv; @@ -7037,16 +7037,6 @@ static int __devinit pcidev_init(struct pci_dev *pdev, spin_lock_init(&hw_priv->hwlock); mutex_init(&hw_priv->lock); - /* tasklet is enabled. */ - tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, - (unsigned long) hw_priv); - tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, - (unsigned long) hw_priv); - - /* tasklet_enable will decrement the atomic counter. */ - tasklet_disable(&hw_priv->rx_tasklet); - tasklet_disable(&hw_priv->tx_tasklet); - for (i = 0; i < TOTAL_PORT_NUM; i++) init_waitqueue_head(&hw_priv->counter[i].counter); @@ -7058,7 +7048,7 @@ static int __devinit pcidev_init(struct pci_dev *pdev, /* Multiple device interfaces mode requires a second MAC address. */ if (hw->dev_count > 1) { - memcpy(sw->other_addr, hw->override_addr, MAC_ADDR_LEN); + memcpy(sw->other_addr, hw->override_addr, ETH_ALEN); read_other_addr(hw); if (mac1addr[0] != ':') get_mac_addr(hw_priv, mac1addr, OTHER_PORT); @@ -7082,6 +7072,7 @@ static int __devinit pcidev_init(struct pci_dev *pdev, dev = alloc_etherdev(sizeof(struct dev_priv)); if (!dev) goto pcidev_init_reg_err; + SET_NETDEV_DEV(dev, &pdev->dev); info->netdev[i] = dev; priv = netdev_priv(dev); @@ -7108,17 +7099,15 @@ static int __devinit pcidev_init(struct pci_dev *pdev, dev->irq = pdev->irq; if (MAIN_PORT == i) memcpy(dev->dev_addr, hw_priv->hw.override_addr, - MAC_ADDR_LEN); + ETH_ALEN); else { - memcpy(dev->dev_addr, sw->other_addr, - MAC_ADDR_LEN); - if (!memcmp(sw->other_addr, hw->override_addr, - MAC_ADDR_LEN)) + memcpy(dev->dev_addr, sw->other_addr, ETH_ALEN); + if (ether_addr_equal(sw->other_addr, hw->override_addr)) dev->dev_addr[5] += port->first_port; } dev->netdev_ops = &netdev_ops; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); + dev->ethtool_ops = &netdev_ethtool_ops; if (register_netdev(dev)) goto pcidev_init_reg_err; port_set_power_saving(port, true); @@ -7158,8 +7147,6 @@ static void pcidev_exit(struct pci_dev *pdev) struct platform_info *info = pci_get_drvdata(pdev); struct dev_info *hw_priv = &info->dev_info; - pci_set_drvdata(pdev, NULL); - release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); for (i = 0; i < hw_priv->hw.dev_count; i++) { @@ -7235,7 +7222,7 @@ static int pcidev_suspend(struct pci_dev *pdev, pm_message_t state) static char pcidev_name[] = "ksz884xp"; -static struct pci_device_id pcidev_table[] = { +static DEFINE_PCI_DEVICE_TABLE(pcidev_table) = { { PCI_VENDOR_ID_MICREL_KS, 0x8841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_MICREL_KS, 0x8842, @@ -7256,18 +7243,7 @@ static struct pci_driver pci_device_driver = { .remove = pcidev_exit }; -static int __init ksz884x_init_module(void) -{ - return pci_register_driver(&pci_device_driver); -} - -static void __exit ksz884x_cleanup_module(void) -{ - pci_unregister_driver(&pci_device_driver); -} - -module_init(ksz884x_init_module); -module_exit(ksz884x_cleanup_module); +module_pci_driver(pci_device_driver); MODULE_DESCRIPTION("KSZ8841/2 PCI network driver"); MODULE_AUTHOR("Tristram Ha <Tristram.Ha@micrel.com>"); |
