diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-05-12 20:21:07 -0700 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-10 20:04:03 -0700 |
commit | ae150435b59e68de00546330241727f2fec54517 (patch) | |
tree | 29a1cb71053306e8a8e0dff1f927d16a9a396917 /drivers/net/smc91x.c | |
parent | aa43c2158d5ae1dc76cccb08cd57a3ffd32c3825 (diff) |
smsc: Move the SMC (SMSC) drivers
Moves the SMC (SMSC) drivers into drivers/net/ethernet/smsc/ and the
necessary Kconfig and Makefile changes. Also did some cleanup
of NET_VENDOR_SMC Kconfig tag for the 8390 based drivers.
CC: Nicolas Pitre <nico@fluxnic.net>
CC: Donald Becker <becker@scyld.com>
CC: Erik Stahlman <erik@vt.edu>
CC: Dustin McIntire <dustin@sensoria.com>
CC: Steve Glendinning <steve.glendinning@smsc.com>
CC: David Hinds <dahinds@users.sourceforge.net>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/smc91x.c')
-rw-r--r-- | drivers/net/smc91x.c | 2431 |
1 files changed, 0 insertions, 2431 deletions
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c deleted file mode 100644 index 2b1d254d59a..00000000000 --- a/drivers/net/smc91x.c +++ /dev/null @@ -1,2431 +0,0 @@ -/* - * smc91x.c - * This is a driver for SMSC's 91C9x/91C1xx single-chip Ethernet devices. - * - * Copyright (C) 1996 by Erik Stahlman - * Copyright (C) 2001 Standard Microsystems Corporation - * Developed by Simple Network Magic Corporation - * Copyright (C) 2003 Monta Vista Software, Inc. - * Unified SMC91x driver by Nicolas Pitre - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Arguments: - * io = for the base address - * irq = for the IRQ - * nowait = 0 for normal wait states, 1 eliminates additional wait states - * - * original author: - * Erik Stahlman <erik@vt.edu> - * - * hardware multicast code: - * Peter Cammaert <pc@denkart.be> - * - * contributors: - * Daris A Nevil <dnevil@snmc.com> - * Nicolas Pitre <nico@fluxnic.net> - * Russell King <rmk@arm.linux.org.uk> - * - * History: - * 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet - * 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ" - * 03/16/01 Daris A Nevil modified smc9194.c for use with LAN91C111 - * 08/22/01 Scott Anderson merge changes from smc9194 to smc91111 - * 08/21/01 Pramod B Bhardwaj added support for RevB of LAN91C111 - * 12/20/01 Jeff Sutherland initial port to Xscale PXA with DMA support - * 04/07/03 Nicolas Pitre unified SMC91x driver, killed irq races, - * more bus abstraction, big cleanup, etc. - * 29/09/03 Russell King - add driver model support - * - ethtool support - * - convert to use generic MII interface - * - add link up/down notification - * - don't try to handle full negotiation in - * smc_phy_configure - * - clean up (and fix stack overrun) in PHY - * MII read/write functions - * 22/09/04 Nicolas Pitre big update (see commit log for details) - */ -static const char version[] = - "smc91x.c: v1.1, sep 22 2004 by Nicolas Pitre <nico@fluxnic.net>\n"; - -/* Debugging level */ -#ifndef SMC_DEBUG -#define SMC_DEBUG 0 -#endif - - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/crc32.h> -#include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/ethtool.h> -#include <linux/mii.h> -#include <linux/workqueue.h> -#include <linux/of.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <asm/io.h> - -#include "smc91x.h" - -#ifndef SMC_NOWAIT -# define SMC_NOWAIT 0 -#endif -static int nowait = SMC_NOWAIT; -module_param(nowait, int, 0400); -MODULE_PARM_DESC(nowait, "set to 1 for no wait state"); - -/* - * Transmit timeout, default 5 seconds. - */ -static int watchdog = 1000; -module_param(watchdog, int, 0400); -MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:smc91x"); - -/* - * The internal workings of the driver. If you are changing anything - * here with the SMC stuff, you should have the datasheet and know - * what you are doing. - */ -#define CARDNAME "smc91x" - -/* - * Use power-down feature of the chip - */ -#define POWER_DOWN 1 - -/* - * Wait time for memory to be free. This probably shouldn't be - * tuned that much, as waiting for this means nothing else happens - * in the system - */ -#define MEMORY_WAIT_TIME 16 - -/* - * The maximum number of processing loops allowed for each call to the - * IRQ handler. - */ -#define MAX_IRQ_LOOPS 8 - -/* - * This selects whether TX packets are sent one by one to the SMC91x internal - * memory and throttled until transmission completes. This may prevent - * RX overruns a litle by keeping much of the memory free for RX packets - * but to the expense of reduced TX throughput and increased IRQ overhead. - * Note this is not a cure for a too slow data bus or too high IRQ latency. - */ -#define THROTTLE_TX_PKTS 0 - -/* - * The MII clock high/low times. 2x this number gives the MII clock period - * in microseconds. (was 50, but this gives 6.4ms for each MII transaction!) - */ -#define MII_DELAY 1 - -#if SMC_DEBUG > 0 -#define DBG(n, args...) \ - do { \ - if (SMC_DEBUG >= (n)) \ - printk(args); \ - } while (0) - -#define PRINTK(args...) printk(args) -#else -#define DBG(n, args...) do { } while(0) -#define PRINTK(args...) printk(KERN_DEBUG args) -#endif - -#if SMC_DEBUG > 3 -static void PRINT_PKT(u_char *buf, int length) -{ - int i; - int remainder; - int lines; - - lines = length / 16; - remainder = length % 16; - - for (i = 0; i < lines ; i ++) { - int cur; - for (cur = 0; cur < 8; cur++) { - u_char a, b; - a = *buf++; - b = *buf++; - printk("%02x%02x ", a, b); - } - printk("\n"); - } - for (i = 0; i < remainder/2 ; i++) { - u_char a, b; - a = *buf++; - b = *buf++; - printk("%02x%02x ", a, b); - } - printk("\n"); -} -#else -#define PRINT_PKT(x...) do { } while(0) -#endif - - -/* this enables an interrupt in the interrupt mask register */ -#define SMC_ENABLE_INT(lp, x) do { \ - unsigned char mask; \ - unsigned long smc_enable_flags; \ - spin_lock_irqsave(&lp->lock, smc_enable_flags); \ - mask = SMC_GET_INT_MASK(lp); \ - mask |= (x); \ - SMC_SET_INT_MASK(lp, mask); \ - spin_unlock_irqrestore(&lp->lock, smc_enable_flags); \ -} while (0) - -/* this disables an interrupt from the interrupt mask register */ -#define SMC_DISABLE_INT(lp, x) do { \ - unsigned char mask; \ - unsigned long smc_disable_flags; \ - spin_lock_irqsave(&lp->lock, smc_disable_flags); \ - mask = SMC_GET_INT_MASK(lp); \ - mask &= ~(x); \ - SMC_SET_INT_MASK(lp, mask); \ - spin_unlock_irqrestore(&lp->lock, smc_disable_flags); \ -} while (0) - -/* - * Wait while MMU is busy. This is usually in the order of a few nanosecs - * if at all, but let's avoid deadlocking the system if the hardware - * decides to go south. - */ -#define SMC_WAIT_MMU_BUSY(lp) do { \ - if (unlikely(SMC_GET_MMU_CMD(lp) & MC_BUSY)) { \ - unsigned long timeout = jiffies + 2; \ - while (SMC_GET_MMU_CMD(lp) & MC_BUSY) { \ - if (time_after(jiffies, timeout)) { \ - printk("%s: timeout %s line %d\n", \ - dev->name, __FILE__, __LINE__); \ - break; \ - } \ - cpu_relax(); \ - } \ - } \ -} while (0) - - -/* - * this does a soft reset on the device - */ -static void smc_reset(struct net_device *dev) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - unsigned int ctl, cfg; - struct sk_buff *pending_skb; - - DBG(2, "%s: %s\n", dev->name, __func__); - - /* Disable all interrupts, block TX tasklet */ - spin_lock_irq(&lp->lock); - SMC_SELECT_BANK(lp, 2); - SMC_SET_INT_MASK(lp, 0); - pending_skb = lp->pending_tx_skb; - lp->pending_tx_skb = NULL; - spin_unlock_irq(&lp->lock); - - /* free any pending tx skb */ - if (pending_skb) { - dev_kfree_skb(pending_skb); - dev->stats.tx_errors++; - dev->stats.tx_aborted_errors++; - } - - /* - * This resets the registers mostly to defaults, but doesn't - * affect EEPROM. That seems unnecessary - */ - SMC_SELECT_BANK(lp, 0); - SMC_SET_RCR(lp, RCR_SOFTRST); - - /* - * Setup the Configuration Register - * This is necessary because the CONFIG_REG is not affected - * by a soft reset - */ - SMC_SELECT_BANK(lp, 1); - - cfg = CONFIG_DEFAULT; - - /* - * Setup for fast accesses if requested. If the card/system - * can't handle it then there will be no recovery except for - * a hard reset or power cycle - */ - if (lp->cfg.flags & SMC91X_NOWAIT) - cfg |= CONFIG_NO_WAIT; - - /* - * Release from possible power-down state - * Configuration register is not affected by Soft Reset - */ - cfg |= CONFIG_EPH_POWER_EN; - - SMC_SET_CONFIG(lp, cfg); - - /* this should pause enough for the chip to be happy */ - /* - * elaborate? What does the chip _need_? --jgarzik - * - * This seems to be undocumented, but something the original - * driver(s) have always done. Suspect undocumented timing - * info/determined empirically. --rmk - */ - udelay(1); - - /* Disable transmit and receive functionality */ - SMC_SELECT_BANK(lp, 0); - SMC_SET_RCR(lp, RCR_CLEAR); - SMC_SET_TCR(lp, TCR_CLEAR); - - SMC_SELECT_BANK(lp, 1); - ctl = SMC_GET_CTL(lp) | CTL_LE_ENABLE; - - /* - * Set the control register to automatically release successfully - * transmitted packets, to make the best use out of our limited - * memory - */ - if(!THROTTLE_TX_PKTS) - ctl |= CTL_AUTO_RELEASE; - else - ctl &= ~CTL_AUTO_RELEASE; - SMC_SET_CTL(lp, ctl); - - /* Reset the MMU */ - SMC_SELECT_BANK(lp, 2); - SMC_SET_MMU_CMD(lp, MC_RESET); - SMC_WAIT_MMU_BUSY(lp); -} - -/* - * Enable Interrupts, Receive, and Transmit - */ -static void smc_enable(struct net_device *dev) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - int mask; - - DBG(2, "%s: %s\n", dev->name, __func__); - - /* see the header file for options in TCR/RCR DEFAULT */ - SMC_SELECT_BANK(lp, 0); - SMC_SET_TCR(lp, lp->tcr_cur_mode); - SMC_SET_RCR(lp, lp->rcr_cur_mode); - - SMC_SELECT_BANK(lp, 1); - SMC_SET_MAC_ADDR(lp, dev->dev_addr); - - /* now, enable interrupts */ - mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT; - if (lp->version >= (CHIP_91100 << 4)) - mask |= IM_MDINT; - SMC_SELECT_BANK(lp, 2); - SMC_SET_INT_MASK(lp, mask); - - /* - * From this point the register bank must _NOT_ be switched away - * to something else than bank 2 without proper locking against - * races with any tasklet or interrupt handlers until smc_shutdown() - * or smc_reset() is called. - */ -} - -/* - * this puts the device in an inactive state - */ -static void smc_shutdown(struct net_device *dev) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - struct sk_buff *pending_skb; - - DBG(2, "%s: %s\n", CARDNAME, __func__); - - /* no more interrupts for me */ - spin_lock_irq(&lp->lock); - SMC_SELECT_BANK(lp, 2); - SMC_SET_INT_MASK(lp, 0); - pending_skb = lp->pending_tx_skb; - lp->pending_tx_skb = NULL; - spin_unlock_irq(&lp->lock); - if (pending_skb) - dev_kfree_skb(pending_skb); - - /* and tell the card to stay away from that nasty outside world */ - SMC_SELECT_BANK(lp, 0); - SMC_SET_RCR(lp, RCR_CLEAR); - SMC_SET_TCR(lp, TCR_CLEAR); - -#ifdef POWER_DOWN - /* finally, shut the chip down */ - SMC_SELECT_BANK(lp, 1); - SMC_SET_CONFIG(lp, SMC_GET_CONFIG(lp) & ~CONFIG_EPH_POWER_EN); -#endif -} - -/* - * This is the procedure to handle the receipt of a packet. - */ -static inline void smc_rcv(struct net_device *dev) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - unsigned int packet_number, status, packet_len; - - DBG(3, "%s: %s\n", dev->name, __func__); - - packet_number = SMC_GET_RXFIFO(lp); - if (unlikely(packet_number & RXFIFO_REMPTY)) { - PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name); - return; - } - - /* read from start of packet */ - SMC_SET_PTR(lp, PTR_READ | PTR_RCV | PTR_AUTOINC); - - /* First two words are status and packet length */ - SMC_GET_PKT_HDR(lp, status, packet_len); - packet_len &= 0x07ff; /* mask off top bits */ - DBG(2, "%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n", - dev->name, packet_number, status, - packet_len, packet_len); - - back: - if (unlikely(packet_len < 6 || status & RS_ERRORS)) { - if (status & RS_TOOLONG && packet_len <= (1514 + 4 + 6)) { - /* accept VLAN packets */ - status &= ~RS_TOOLONG; - goto back; - } - if (packet_len < 6) { - /* bloody hardware */ - printk(KERN_ERR "%s: fubar (rxlen %u status %x\n", - dev->name, packet_len, status); - status |= RS_TOOSHORT; - } - SMC_WAIT_MMU_BUSY(lp); - SMC_SET_MMU_CMD(lp, MC_RELEASE); - dev->stats.rx_errors++; - if (status & RS_ALGNERR) - dev->stats.rx_frame_errors++; - if (status & (RS_TOOSHORT | RS_TOOLONG)) - dev->stats.rx_length_errors++; - if (status & RS_BADCRC) - dev->stats.rx_crc_errors++; - } else { - struct sk_buff *skb; - unsigned char *data; - unsigned int data_len; - - /* set multicast stats */ - if (status & RS_MULTICAST) - dev->stats.multicast++; - - /* - * Actual payload is packet_len - 6 (or 5 if odd byte). - * We want skb_reserve(2) and the final ctrl word - * (2 bytes, possibly containing the payload odd byte). - * Furthermore, we add 2 bytes to allow rounding up to - * multiple of 4 bytes on 32 bit buses. - * Hence packet_len - 6 + 2 + 2 + 2. - */ - skb = dev_alloc_skb(packet_len); - if (unlikely(skb == NULL)) { - printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", - dev->name); - SMC_WAIT_MMU_BUSY(lp); - SMC_SET_MMU_CMD(lp, MC_RELEASE); - dev->stats.rx_dropped++; - return; - } - - /* Align IP header to 32 bits */ - skb_reserve(skb, 2); - - /* BUG: the LAN91C111 rev A never sets this bit. Force it. */ - if (lp->version == 0x90) - status |= RS_ODDFRAME; - - /* - * If odd length: packet_len - 5, - * otherwise packet_len - 6. - * With the trailing ctrl byte it's packet_len - 4. - */ - data_len = packet_len - ((status & RS_ODDFRAME) ? 5 : 6); - data = skb_put(skb, data_len); - SMC_PULL_DATA(lp, data, packet_len - 4); - - SMC_WAIT_MMU_BUSY(lp); - SMC_SET_MMU_CMD(lp, MC_RELEASE); - - PRINT_PKT(data, packet_len - 4); - - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += data_len; - } -} - -#ifdef CONFIG_SMP -/* - * On SMP we have the following problem: - * - * A = smc_hardware_send_pkt() - * B = smc_hard_start_xmit() - * C = smc_interrupt() - * - * A and B can never be executed simultaneously. However, at least on UP, - * it is possible (and even desirable) for C to interrupt execution of - * A or B in order to have better RX reliability and avoid overruns. - * C, just like A and B, must have exclusive access to the chip and - * each of them must lock against any other concurrent access. - * Unfortunately this is not possible to have C suspend execution of A or - * B taking place on another CPU. On UP this is no an issue since A and B - * are run from softirq context and C from hard IRQ context, and there is - * no other CPU where concurrent access can happen. - * If ever there is a way to force at least B and C to always be executed - * on the same CPU then we could use read/write locks to protect against - * any other concurrent access and C would always interrupt B. But life - * isn't that easy in a SMP world... - */ -#define smc_special_trylock(lock, flags) \ -({ \ - int __ret; \ - local_irq_save(flags); \ - __ret = spin_trylock(lock); \ - if (!__ret) \ - local_irq_restore(flags); \ - __ret; \ -}) -#define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags) -#define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags) -#else -#define smc_special_trylock(lock, flags) (flags == flags) -#define smc_special_lock(lock, flags) do { flags = 0; } while (0) -#define smc_special_unlock(lock, flags) do { flags = 0; } while (0) -#endif - -/* - * This is called to actually send a packet to the chip. - */ -static void smc_hardware_send_pkt(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - struct sk_buff *skb; - unsigned int packet_no, len; - unsigned char *buf; - unsigned long flags; - - DBG(3, "%s: %s\n", dev->name, __func__); - - if (!smc_special_trylock(&lp->lock, flags)) { - netif_stop_queue(dev); - tasklet_schedule(&lp->tx_task); - return; - } - - skb = lp->pending_tx_skb; - if (unlikely(!skb)) { - smc_special_unlock(&lp->lock, flags); - return; - } - lp->pending_tx_skb = NULL; - - packet_no = SMC_GET_AR(lp); - if (unlikely(packet_no & AR_FAILED)) { - printk("%s: Memory allocation failed.\n", dev->name); - dev->stats.tx_errors++; - dev->stats.tx_fifo_errors++; - smc_special_unlock(&lp->lock, flags); - goto done; - } - - /* point to the beginning of the packet */ - SMC_SET_PN(lp, packet_no); - SMC_SET_PTR(lp, PTR_AUTOINC); - - buf = skb->data; - len = skb->len; - DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n", - dev->name, packet_no, len, len, buf); - PRINT_PKT(buf, len); - - /* - * Send the packet length (+6 for status words, length, and ctl. - * The card will pad to 64 bytes with zeroes if packet is too small. - */ - SMC_PUT_PKT_HDR(lp, 0, len + 6); - - /* send the actual data */ - SMC_PUSH_DATA(lp, buf, len & ~1); - - /* Send final ctl word with the last byte if there is one */ - SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp)); - - /* - * If THROTTLE_TX_PKTS is set, we stop the queue here. This will - * have the effect of having at most one packet queued for TX - * in the chip's memory at all time. - * - * If THROTTLE_TX_PKTS is not set then the queue is stopped only - * when memory allocation (MC_ALLOC) does not succeed right away. - */ - if (THROTTLE_TX_PKTS) - netif_stop_queue(dev); - - /* queue the packet for TX */ - SMC_SET_MMU_CMD(lp, MC_ENQUEUE); - smc_special_unlock(&lp->lock, flags); - - dev->trans_start = jiffies; - dev->stats.tx_packets++; - dev->stats.tx_bytes += len; - - SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT); - -done: if (!THROTTLE_TX_PKTS) - netif_wake_queue(dev); - - dev_kfree_skb(skb); -} - -/* - * Since I am not sure if I will have enough room in the chip's ram - * to store the packet, I call this routine which either sends it - * now, or set the card to generates an interrupt when ready - * for the packet. - */ -static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - unsigned int numPages, poll_count, status; - unsigned long flags; - - DBG(3, "%s: %s\n", dev->name, __func__); - - BUG_ON(lp->pending_tx_skb != NULL); - - /* - * The MMU wants the number of pages to be the number of 256 bytes - * 'pages', minus 1 (since a packet can't ever have 0 pages :)) - * - * The 91C111 ignores the size bits, but earlier models don't. - * - * Pkt size for allocating is data length +6 (for additional status - * words, length and ctl) - * - * If odd size then last byte is included in ctl word. - */ - numPages = ((skb->len & ~1) + (6 - 1)) >> 8; - if (unlikely(numPages > 7)) { - printk("%s: Far too big packet error.\n", dev->name); - dev->stats.tx_errors++; - dev->stats.tx_dropped++; - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - smc_special_lock(&lp->lock, flags); - - /* now, try to allocate the memory */ - SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages); - - /* - * Poll the chip for a short amount of time in case the - * allocation succeeds quickly. - */ - poll_count = MEMORY_WAIT_TIME; - do { - status = SMC_GET_INT(lp); - if (status & IM_ALLOC_INT) { - SMC_ACK_INT(lp, IM_ALLOC_INT); - break; - } - } while (--poll_count); - - smc_special_unlock(&lp->lock, flags); - - lp->pending_tx_skb = skb; - if (!poll_count) { - /* oh well, wait until the chip finds memory later */ - netif_stop_queue(dev); - DBG(2, "%s: TX memory allocation deferred.\n", dev->name); - SMC_ENABLE_INT(lp, IM_ALLOC_INT); - } else { - /* - * Allocation succeeded: push packet to the chip's own memory - * immediately. - */ - smc_hardware_send_pkt((unsigned long)dev); - } - - return NETDEV_TX_OK; -} - -/* - * This handles a TX interrupt, which is only called when: - * - a TX error occurred, or - * - CTL_AUTO_RELEASE is not set and TX of a packet completed. - */ -static void smc_tx(struct net_device *dev) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - unsigned int saved_packet, packet_no, tx_status, pkt_len; - - DBG(3, "%s: %s\n", dev->name, __func__); - - /* If the TX FIFO is empty then nothing to do */ - packet_no = SMC_GET_TXFIFO(lp); - if (unlikely(packet_no & TXFIFO_TEMPTY)) { - PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name); - return; - } - - /* select packet to read from */ - saved_packet = SMC_GET_PN(lp); - SMC_SET_PN(lp, packet_no); - - /* read the first word (status word) from this packet */ - SMC_SET_PTR(lp, PTR_AUTOINC | PTR_READ); - SMC_GET_PKT_HDR(lp, tx_status, pkt_len); - DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n", - dev->name, tx_status, packet_no); - - if (!(tx_status & ES_TX_SUC)) - dev->stats.tx_errors++; - - if (tx_status & ES_LOSTCARR) - dev->stats.tx_carrier_errors++; - - if (tx_status & (ES_LATCOL | ES_16COL)) { - PRINTK("%s: %s occurred on last xmit\n", dev->name, - (tx_status & ES_LATCOL) ? - "late collision" : "too many collisions"); - dev->stats.tx_window_errors++; - if (!(dev->stats.tx_window_errors & 63) && net_ratelimit()) { - printk(KERN_INFO "%s: unexpectedly large number of " - "bad collisions. Please check duplex " - "setting.\n", dev->name); - } - } - - /* kill the packet */ - SMC_WAIT_MMU_BUSY(lp); - SMC_SET_MMU_CMD(lp, MC_FREEPKT); - - /* Don't restore Packet Number Reg until busy bit is cleared */ - SMC_WAIT_MMU_BUSY(lp); - SMC_SET_PN(lp, saved_packet); - - /* re-enable transmit */ - SMC_SELECT_BANK(lp, 0); - SMC_SET_TCR(lp, lp->tcr_cur_mode); - SMC_SELECT_BANK(lp, 2); -} - - -/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ - -static void smc_mii_out(struct net_device *dev, unsigned int val, int bits) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - unsigned int mii_reg, mask; - - mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO); - mii_reg |= MII_MDOE; - - for (mask = 1 << (bits - 1); mask; mask >>= 1) { - if (val & mask) - mii_reg |= MII_MDO; - else - mii_reg &= ~MII_MDO; - - SMC_SET_MII(lp, mii_reg); - udelay(MII_DELAY); - SMC_SET_MII(lp, mii_reg | MII_MCLK); - udelay(MII_DELAY); - } -} - -static unsigned int smc_mii_in(struct net_device *dev, int bits) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - unsigned int mii_reg, mask, val; - - mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO); - SMC_SET_MII(lp, mii_reg); - - for (mask = 1 << (bits - 1), val = 0; mask; mask >>= 1) { - if (SMC_GET_MII(lp) & MII_MDI) - val |= mask; - - SMC_SET_MII(lp, mii_reg); - udelay(MII_DELAY); - SMC_SET_MII(lp, mii_reg | MII_MCLK); - udelay(MII_DELAY); - } - - return val; -} - -/* - * Reads a register from the MII Management serial interface - */ -static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - unsigned int phydata; - - SMC_SELECT_BANK(lp, 3); - - /* Idle - 32 ones */ - smc_mii_out(dev, 0xffffffff, 32); - - /* Start code (01) + read (10) + phyaddr + phyreg */ - smc_mii_out(dev, 6 << 10 | phyaddr << 5 | phyreg, 14); - - /* Turnaround (2bits) + phydata */ - phydata = smc_mii_in(dev, 18); - - /* Return to idle state */ - SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO)); - - DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", - __func__, phyaddr, phyreg, phydata); - - SMC_SELECT_BANK(lp, 2); - return phydata; -} - -/* - * Writes a register to the MII Management serial interface - */ -static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg, - int phydata) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - - SMC_SELECT_BANK(lp, 3); - - /* Idle - 32 ones */ - smc_mii_out(dev, 0xffffffff, 32); - - /* Start code (01) + write (01) + phyaddr + phyreg + turnaround + phydata */ - smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32); - - /* Return to idle state */ - SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO)); - - DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", - __func__, phyaddr, phyreg, phydata); - - SMC_SELECT_BANK(lp, 2); -} - -/* - * Finds and reports the PHY address - */ -static void smc_phy_detect(struct net_device *dev) -{ - struct smc_local *lp = netdev_priv(dev); - int phyaddr; - - DBG(2, "%s: %s\n", dev->name, __func__); - - lp->phy_type = 0; - - /* - * Scan all 32 PHY addresses if necessary, starting at - * PHY#1 to PHY#31, and then PHY#0 last. - */ - for (phyaddr = 1; phyaddr < 33; ++phyaddr) { - unsigned int id1, id2; - - /* Read the PHY identifiers */ - id1 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID1); - id2 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID2); - - DBG(3, "%s: phy_id1=0x%x, phy_id2=0x%x\n", - dev->name, id1, id2); - - /* Make sure it is a valid identifier */ - if (id1 != 0x0000 && id1 != 0xffff && id1 != 0x8000 && - id2 != 0x0000 && id2 != 0xffff && id2 != 0x8000) { - /* Save the PHY's address */ - lp->mii.phy_id = phyaddr & 31; - lp->phy_type = id1 << 16 | id2; - break; - } - } -} - -/* - * Sets the PHY to a configuration as determined by the user - */ -static int smc_phy_fixed(struct net_device *dev) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - int phyaddr = lp->mii.phy_id; - int bmcr, cfg1; - - DBG(3, "%s: %s\n", dev->name, __func__); - - /* Enter Link Disable state */ - cfg1 = smc_phy_read(dev, phyaddr, PHY_CFG1_REG); - cfg1 |= PHY_CFG1_LNKDIS; - smc_phy_write(dev, phyaddr, PHY_CFG1_REG, cfg1); - - /* - * Set our fixed capabilities - * Disable auto-negotiation - */ - bmcr = 0; - - if (lp->ctl_rfduplx) - bmcr |= BMCR_FULLDPLX; - - if (lp->ctl_rspeed == 100) - bmcr |= BMCR_SPEED100; - - /* Write our capabilities to the phy control register */ - smc_phy_write(dev, phyaddr, MII_BMCR, bmcr); - - /* Re-Configure the Receive/Phy Control register */ - SMC_SELECT_BANK(lp, 0); - SMC_SET_RPC(lp, lp->rpc_cur_mode); - SMC_SELECT_BANK(lp, 2); - - return 1; -} - -/* - * smc_phy_reset - reset the phy - * @dev: net device - * @phy: phy address - * - * Issue a software reset for the specified PHY and - * wait up to 100ms for the reset to complete. We should - * not access the PHY for 50ms after issuing the reset. - * - * The time to wait appears to be dependent on the PHY. - * - * Must be called with lp->lock locked. - */ -static int smc_phy_reset(struct net_device *dev, int phy) -{ - struct smc_local *lp = netdev_priv(dev); - unsigned int bmcr; - int timeout; - - smc_phy_write(dev, phy, MII_BMCR, BMCR_RESET); - - for (timeout = 2; timeout; timeout--) { - spin_unlock_irq(&lp->lock); - msleep(50); - spin_lock_irq(&lp->lock); - - bmcr = smc_phy_read(dev, phy, MII_BMCR); - if (!(bmcr & BMCR_RESET)) - break; - } - - return bmcr & BMCR_RESET; -} - -/* - * smc_phy_powerdown - powerdown phy - * @dev: net device - * - * Power down the specified PHY - */ -static void smc_phy_powerdown(struct net_device *dev) -{ - struct smc_local *lp = netdev_priv(dev); - unsigned int bmcr; - int phy = lp->mii.phy_id; - - if (lp->phy_type == 0) - return; - - /* We need to ensure that no calls to smc_phy_configure are - pending. - */ - cancel_work_sync(&lp->phy_configure); - - bmcr = smc_phy_read(dev, phy, MII_BMCR); - smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); -} - -/* - * smc_phy_check_media - check the media status and adjust TCR - * @dev: net device - * @init: set true for initialisation - * - * Select duplex mode depending on negotiation state. This - * also updates our carrier state. - */ -static void smc_phy_check_media(struct net_device *dev, int init) -{ - struct smc_local *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - - if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { - /* duplex state has changed */ - if (lp->mii.full_duplex) { - lp->tcr_cur_mode |= TCR_SWFDUP; - } else { - lp->tcr_cur_mode &= ~TCR_SWFDUP; - } - - SMC_SELECT_BANK(lp, 0); - SMC_SET_TCR(lp, lp->tcr_cur_mode); - } -} - -/* - * Configures the specified PHY through the MII management interface - * using Autonegotiation. - * Calls smc_phy_fixed() if the user has requested a certain config. - * If RPC ANEG bit is set, the media selection is dependent purely on - * the selection by the MII (either in the MII BMCR reg or the result - * of autonegotiation.) If the RPC ANEG bit is cleared, the selection - * is controlled by the RPC SPEED and RPC DPLX bits. - */ -static void smc_phy_configure(struct work_struct *work) -{ - struct smc_local *lp = - container_of(work, struct smc_local, phy_configure); - struct net_device *dev = lp->dev; - void __iomem *ioaddr = lp->base; - int phyaddr = lp->mii.phy_id; - int my_phy_caps; /* My PHY capabilities */ - int my_ad_caps; /* My Advertised capabilities */ - int status; - - DBG(3, "%s:smc_program_phy()\n", dev->name); - - spin_lock_irq(&lp->lock); - - /* - * We should not be called if phy_type is zero. - */ - if (lp->phy_type == 0) - goto smc_phy_configure_exit; - - if (smc_phy_reset(dev, phyaddr)) { - printk("%s: PHY reset timed out\n", dev->name); - goto smc_phy_configure_exit; - } - - /* - * Enable PHY Interrupts (for register 18) - * Interrupts listed here are disabled - */ - smc_phy_write(dev, phyaddr, PHY_MASK_REG, - PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD | - PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB | - PHY_INT_SPDDET | PHY_INT_DPLXDET); - - /* Configure the Receive/Phy Control register */ - SMC_SELECT_BANK(lp, 0); - SMC_SET_RPC(lp, lp->rpc_cur_mode); - - /* If the user requested no auto neg, then go set his request */ - if (lp->mii.force_media) { - smc_phy_fixed(dev); - goto smc_phy_configure_exit; - } - - /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */ - my_phy_caps = smc_phy_read(dev, phyaddr, MII_BMSR); - - if (!(my_phy_caps & BMSR_ANEGCAPABLE)) { - printk(KERN_INFO "Auto negotiation NOT supported\n"); - smc_phy_fixed(dev); - goto smc_phy_configure_exit; - } - - my_ad_caps = ADVERTISE_CSMA; /* I am CSMA capable */ - - if (my_phy_caps & BMSR_100BASE4) - my_ad_caps |= ADVERTISE_100BASE4; - if (my_phy_caps & BMSR_100FULL) - my_ad_caps |= ADVERTISE_100FULL; - if (my_phy_caps & BMSR_100HALF) - my_ad_caps |= ADVERTISE_100HALF; - if (my_phy_caps & BMSR_10FULL) - my_ad_caps |= ADVERTISE_10FULL; - if (my_phy_caps & BMSR_10HALF) - my_ad_caps |= ADVERTISE_10HALF; - - /* Disable capabilities not selected by our user */ - if (lp->ctl_rspeed != 100) - my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF); - - if (!lp->ctl_rfduplx) - my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL); - - /* Update our Auto-Neg Advertisement Register */ - smc_phy_write(dev, phyaddr, MII_ADVERTISE, my_ad_caps); - lp->mii.advertising = my_ad_caps; - - /* - * Read the register back. Without this, it appears that when - * auto-negotiation is restarted, sometimes it isn't ready and - * the link does not come up. - */ - status = smc_phy_read(dev, phyaddr, MII_ADVERTISE); - - DBG(2, "%s: phy caps=%x\n", dev->name, my_phy_caps); - DBG(2, "%s: phy advertised caps=%x\n", dev->name, my_ad_caps); - - /* Restart auto-negotiation process in order to advertise my caps */ - smc_phy_write(dev, phyaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - - smc_phy_check_media(dev, 1); - -smc_phy_configure_exit: - SMC_SELECT_BANK(lp, 2); - spin_unlock_irq(&lp->lock); -} - -/* - * smc_phy_interrupt - * - * Purpose: Handle interrupts relating to PHY register 18 |