diff options
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r-- | drivers/net/skge.c | 197 |
1 files changed, 85 insertions, 112 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 35b28f42d20..98ec614c569 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -44,12 +44,13 @@ #include <linux/mii.h> #include <linux/slab.h> #include <linux/dmi.h> +#include <linux/prefetch.h> #include <asm/irq.h> #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.13" +#define DRV_VERSION "1.14" #define DEFAULT_TX_RING_SIZE 128 #define DEFAULT_RX_RING_SIZE 512 @@ -82,17 +83,20 @@ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); static DEFINE_PCI_DEVICE_TABLE(skge_id_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940) }, - { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) }, - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T) }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* DGE-530T */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ - { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) }, - { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 }, + { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x1700) }, /* 3Com 3C940 */ + { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x80EB) }, /* 3Com 3C940B */ +#ifdef CONFIG_SKGE_GENESIS + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4300) }, /* SK-9xx */ +#endif + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4320) }, /* SK-98xx V2.0 */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* D-Link DGE-530T (rev.B) */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4c00) }, /* D-Link DGE-530T */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302) }, /* D-Link DGE-530T Rev C1 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, /* Marvell Yukon 88E8001/8003/8010 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ + { PCI_DEVICE(PCI_VENDOR_ID_CNET, 0x434E) }, /* CNet PowerG-2000 */ + { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, 0x1064) }, /* Linksys EG1064 v2 */ + { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 }, /* Linksys EG1032 v2 */ { 0 } }; MODULE_DEVICE_TABLE(pci, skge_id_table); @@ -118,6 +122,15 @@ static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F }; static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 }; +static inline bool is_genesis(const struct skge_hw *hw) +{ +#ifdef CONFIG_SKGE_GENESIS + return hw->chip_id == CHIP_ID_GENESIS; +#else + return false; +#endif +} + static int skge_get_regs_len(struct net_device *dev) { return 0x4000; @@ -145,7 +158,7 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, /* Wake on Lan only supported on Yukon chips with rev 1 or above */ static u32 wol_supported(const struct skge_hw *hw) { - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) return 0; if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0) @@ -269,7 +282,7 @@ static u32 skge_supported_modes(const struct skge_hw *hw) SUPPORTED_Autoneg | SUPPORTED_TP); - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) supported &= ~(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -303,7 +316,7 @@ static int skge_get_settings(struct net_device *dev, ecmd->advertising = skge->advertising; ecmd->autoneg = skge->autoneg; - ecmd->speed = skge->speed; + ethtool_cmd_speed_set(ecmd, skge->speed); ecmd->duplex = skge->duplex; return 0; } @@ -321,8 +334,9 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) skge->speed = -1; } else { u32 setting; + u32 speed = ethtool_cmd_speed(ecmd); - switch (ecmd->speed) { + switch (speed) { case SPEED_1000: if (ecmd->duplex == DUPLEX_FULL) setting = SUPPORTED_1000baseT_Full; @@ -355,7 +369,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) if ((setting & supported) == 0) return -EINVAL; - skge->speed = ecmd->speed; + skge->speed = speed; skge->duplex = ecmd->duplex; } @@ -431,7 +445,7 @@ static void skge_get_ethtool_stats(struct net_device *dev, { struct skge_port *skge = netdev_priv(dev); - if (skge->hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(skge->hw)) genesis_get_stats(skge, data); else yukon_get_stats(skge, data); @@ -446,7 +460,7 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); u64 data[ARRAY_SIZE(skge_stats)]; - if (skge->hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(skge->hw)) genesis_get_stats(skge, data); else yukon_get_stats(skge, data); @@ -537,46 +551,6 @@ static int skge_nway_reset(struct net_device *dev) return 0; } -static int skge_set_sg(struct net_device *dev, u32 data) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - - if (hw->chip_id == CHIP_ID_GENESIS && data) - return -EOPNOTSUPP; - return ethtool_op_set_sg(dev, data); -} - -static int skge_set_tx_csum(struct net_device *dev, u32 data) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - - if (hw->chip_id == CHIP_ID_GENESIS && data) - return -EOPNOTSUPP; - - return ethtool_op_set_tx_csum(dev, data); -} - -static u32 skge_get_rx_csum(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - return skge->rx_csum; -} - -/* Only Yukon supports checksum offload. */ -static int skge_set_rx_csum(struct net_device *dev, u32 data) -{ - struct skge_port *skge = netdev_priv(dev); - - if (skge->hw->chip_id == CHIP_ID_GENESIS && data) - return -EOPNOTSUPP; - - skge->rx_csum = data; - return 0; -} - static void skge_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *ecmd) { @@ -627,7 +601,7 @@ static int skge_set_pauseparam(struct net_device *dev, /* Chip internal frequency for clock calculations */ static inline u32 hwkhz(const struct skge_hw *hw) { - return (hw->chip_id == CHIP_ID_GENESIS) ? 53125 : 78125; + return is_genesis(hw) ? 53125 : 78125; } /* Chip HZ to microseconds */ @@ -712,7 +686,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) int port = skge->port; spin_lock_bh(&hw->phy_lock); - if (hw->chip_id == CHIP_ID_GENESIS) { + if (is_genesis(hw)) { switch (mode) { case LED_MODE_OFF: if (hw->phy_type == SK_PHY_BCOM) @@ -786,28 +760,27 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) } /* blink LED's for finding board */ -static int skge_phys_id(struct net_device *dev, u32 data) +static int skge_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) { struct skge_port *skge = netdev_priv(dev); - unsigned long ms; - enum led_mode mode = LED_MODE_TST; - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000; - else - ms = data * 1000; + switch (state) { + case ETHTOOL_ID_ACTIVE: + return 2; /* cycle on/off twice per second */ - while (ms > 0) { - skge_led(skge, mode); - mode ^= LED_MODE_TST; + case ETHTOOL_ID_ON: + skge_led(skge, LED_MODE_TST); + break; - if (msleep_interruptible(BLINK_MS)) - break; - ms -= BLINK_MS; - } + case ETHTOOL_ID_OFF: + skge_led(skge, LED_MODE_OFF); + break; - /* back to regular LED state */ - skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); + case ETHTOOL_ID_INACTIVE: + /* back to regular LED state */ + skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); + } return 0; } @@ -925,12 +898,8 @@ static const struct ethtool_ops skge_ethtool_ops = { .set_pauseparam = skge_set_pauseparam, .get_coalesce = skge_get_coalesce, .set_coalesce = skge_set_coalesce, - .set_sg = skge_set_sg, - .set_tx_csum = skge_set_tx_csum, - .get_rx_csum = skge_get_rx_csum, - .set_rx_csum = skge_set_rx_csum, .get_strings = skge_get_strings, - .phys_id = skge_phys_id, + .set_phys_id = skge_set_phys_id, .get_sset_count = skge_get_sset_count, .get_ethtool_stats = skge_get_ethtool_stats, }; @@ -1096,7 +1065,6 @@ static void skge_link_down(struct skge_port *skge) netif_info(skge, link, skge->netdev, "Link is down\n"); } - static void xm_link_down(struct skge_hw *hw, int port) { struct net_device *dev = hw->dev[port]; @@ -1215,7 +1183,6 @@ static void genesis_reset(struct skge_hw *hw, int port) xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF); } - /* Convert mode to MII values */ static const u16 phy_pause_map[] = { [FLOW_MODE_NONE] = 0, @@ -2448,7 +2415,7 @@ static void skge_phy_reset(struct skge_port *skge) netif_carrier_off(skge->netdev); spin_lock_bh(&hw->phy_lock); - if (hw->chip_id == CHIP_ID_GENESIS) { + if (is_genesis(hw)) { genesis_reset(hw, port); genesis_mac_init(hw, port); } else { @@ -2479,7 +2446,8 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: { u16 val = 0; spin_lock_bh(&hw->phy_lock); - if (hw->chip_id == CHIP_ID_GENESIS) + + if (is_genesis(hw)) err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); else err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); @@ -2490,7 +2458,7 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCSMIIREG: spin_lock_bh(&hw->phy_lock); - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, data->val_in); else @@ -2602,7 +2570,7 @@ static int skge_up(struct net_device *dev) /* Initialize MAC */ spin_lock_bh(&hw->phy_lock); - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) genesis_mac_init(hw, port); else yukon_mac_init(hw, port); @@ -2664,7 +2632,7 @@ static int skge_down(struct net_device *dev) netif_tx_disable(dev); - if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) + if (is_genesis(hw) && hw->phy_type == SK_PHY_XMAC) del_timer_sync(&skge->link_timer); napi_disable(&skge->napi); @@ -2676,7 +2644,7 @@ static int skge_down(struct net_device *dev) spin_unlock_irq(&hw->hw_lock); skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) genesis_stop(skge); else yukon_stop(skge); @@ -2704,7 +2672,7 @@ static int skge_down(struct net_device *dev) skge_rx_stop(hw, port); - if (hw->chip_id == CHIP_ID_GENESIS) { + if (is_genesis(hw)) { skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); } else { @@ -3000,7 +2968,7 @@ static void yukon_set_multicast(struct net_device *dev) static inline u16 phy_length(const struct skge_hw *hw, u32 status) { - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) return status >> XMR_FS_LEN_SHIFT; else return status >> GMR_FS_LEN_SHIFT; @@ -3008,7 +2976,7 @@ static inline u16 phy_length(const struct skge_hw *hw, u32 status) static inline int bad_phy_status(const struct skge_hw *hw, u32 status) { - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) return (status & (XMR_FS_ERR | XMR_FS_2L_VLAN)) != 0; else return (status & GMR_FS_ANY_ERR) || @@ -3018,9 +2986,8 @@ static inline int bad_phy_status(const struct skge_hw *hw, u32 status) static void skge_set_multicast(struct net_device *dev) { struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(skge->hw)) genesis_set_multicast(dev); else yukon_set_multicast(dev); @@ -3085,7 +3052,8 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, } skb_put(skb, len); - if (skge->rx_csum) { + + if (dev->features & NETIF_F_RXCSUM) { skb->csum = csum; skb->ip_summed = CHECKSUM_COMPLETE; } @@ -3099,7 +3067,7 @@ error: "rx err, slot %td control 0x%x status 0x%x\n", e - skge->rx_ring.start, control, status); - if (skge->hw->chip_id == CHIP_ID_GENESIS) { + if (is_genesis(skge->hw)) { if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) dev->stats.rx_length_errors++; if (status & XMR_FS_FRA_ERR) @@ -3213,7 +3181,7 @@ static void skge_mac_parity(struct skge_hw *hw, int port) ++dev->stats.tx_heartbeat_errors; - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_PERR); else @@ -3225,7 +3193,7 @@ static void skge_mac_parity(struct skge_hw *hw, int port) static void skge_mac_intr(struct skge_hw *hw, int port) { - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) genesis_mac_intr(hw, port); else yukon_mac_intr(hw, port); @@ -3237,7 +3205,7 @@ static void skge_error_irq(struct skge_hw *hw) struct pci_dev *pdev = hw->pdev; u32 hwstatus = skge_read32(hw, B0_HWE_ISRC); - if (hw->chip_id == CHIP_ID_GENESIS) { + if (is_genesis(hw)) { /* clear xmac errors */ if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1)) skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT); @@ -3320,7 +3288,7 @@ static void skge_extirq(unsigned long arg) struct skge_port *skge = netdev_priv(dev); spin_lock(&hw->phy_lock); - if (hw->chip_id != CHIP_ID_GENESIS) + if (!is_genesis(hw)) yukon_phy_intr(skge); else if (hw->phy_type == SK_PHY_BCOM) bcom_phy_intr(skge); @@ -3439,7 +3407,7 @@ static int skge_set_mac_address(struct net_device *dev, void *p) memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) xm_outaddr(hw, port, XM_SA, dev->dev_addr); else { gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); @@ -3515,6 +3483,7 @@ static int skge_reset(struct skge_hw *hw) switch (hw->chip_id) { case CHIP_ID_GENESIS: +#ifdef CONFIG_SKGE_GENESIS switch (hw->phy_type) { case SK_PHY_XMAC: hw->phy_addr = PHY_ADDR_XMAC; @@ -3528,6 +3497,10 @@ static int skge_reset(struct skge_hw *hw) return -EOPNOTSUPP; } break; +#else + dev_err(&hw->pdev->dev, "Genesis chip detected but not configured\n"); + return -EOPNOTSUPP; +#endif case CHIP_ID_YUKON: case CHIP_ID_YUKON_LITE: @@ -3550,7 +3523,7 @@ static int skge_reset(struct skge_hw *hw) /* read the adapters RAM size */ t8 = skge_read8(hw, B2_E_0); - if (hw->chip_id == CHIP_ID_GENESIS) { + if (is_genesis(hw)) { if (t8 == 3) { /* special case: 4 x 64k x 36, offset = 0x80000 */ hw->ram_size = 0x100000; @@ -3565,10 +3538,10 @@ static int skge_reset(struct skge_hw *hw) hw->intr_mask = IS_HW_ERR; /* Use PHY IRQ for all but fiber based Genesis board */ - if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)) + if (!(is_genesis(hw) && hw->phy_type == SK_PHY_XMAC)) hw->intr_mask |= IS_EXT_REG; - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) genesis_init(hw); else { /* switch power to VCC (WA for VAUX problem) */ @@ -3633,7 +3606,7 @@ static int skge_reset(struct skge_hw *hw) skge_write32(hw, B0_IMSK, hw->intr_mask); for (i = 0; i < hw->ports; i++) { - if (hw->chip_id == CHIP_ID_GENESIS) + if (is_genesis(hw)) genesis_reset(hw, i); else yukon_reset(hw, i); @@ -3844,13 +3817,13 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->port = port; /* Only used for Genesis XMAC */ - setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge); - - if (hw->chip_id != CHIP_ID_GENESIS) { - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; - skge->rx_csum = 1; + if (is_genesis(hw)) + setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge); + else { + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | + NETIF_F_RXCSUM; + dev->features |= dev->hw_features; } - dev->features |= NETIF_F_GRO; /* read the mac address */ memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN); |