From 72729910c38ca5b4736032c15dc3f9d48fe4f68a Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 27 Sep 2006 09:44:11 +0100 Subject: [ARM] 3865/1: AT91RM9200 header updates This is more preparation for adding support for the new Atmel AT91SAM9 processors. Changes include: - Replace AT91_BASE_* with AT91RM9200_BASE_* - Replace AT91_ID_* with AT91RM9200_ID_* - ROM, SRAM and UHP address definitions moved to at91rm9200.h. - The raw AT91_P[ABCD]_* definitions are now depreciated in favour of the GPIO API. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- drivers/net/arm/at91_ether.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 95b28aa01f4..3ecf2cc53a7 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -947,7 +947,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add return -ENOMEM; dev->base_addr = AT91_VA_BASE_EMAC; - dev->irq = AT91_ID_EMAC; + dev->irq = AT91RM9200_ID_EMAC; SET_MODULE_OWNER(dev); /* Install the interrupt handler */ -- cgit v1.2.3 From 83e331e2a492a134e491bcf50c984fd50c7fae03 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 25 Sep 2006 22:31:03 -0700 Subject: [IRDA] via-ircc: fix memory leak Fix memory leak. Coverity id# 653 patch location: http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=a1f34cb68b16807ed9d5ebb0f6a6ec5ff8a5fc78 Signed-off-by: Chuck Short Signed-off-by: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/irda/via-ircc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index 79b85f32750..d916e1257c4 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -1223,8 +1223,13 @@ static int upload_rxdata(struct via_ircc_cb *self, int iobase) IRDA_DEBUG(2, "%s(): len=%x\n", __FUNCTION__, len); + if ((len - 4) < 2) { + self->stats.rx_dropped++; + return FALSE; + } + skb = dev_alloc_skb(len + 1); - if ((skb == NULL) || ((len - 4) < 2)) { + if (skb == NULL) { self->stats.rx_dropped++; return FALSE; } -- cgit v1.2.3 From 1618cb0c9c2ac128beb94ff376e3367932ae6432 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 25 Sep 2006 23:11:21 -0700 Subject: [NETDEV] config: revert part of previous patch Net devices should depend on NETDEVICES, so revert part of Paolo's previous patch. See http://marc.theaimsgroup.com/?l=linux-kernel&m=115566326218740&w=2 for history. Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 63154774c25..ff8a8c0a26d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -24,6 +24,9 @@ config NETDEVICES If unsure, say Y. +# All the following symbols are dependent on NETDEVICES - do not repeat +# that for each of the symbols. +if NETDEVICES config IFB tristate "Intermediate Functional Block support" @@ -2852,6 +2855,8 @@ config NETCONSOLE If you want to log kernel messages over the network, enable this. See for details. +endif #NETDEVICES + config NETPOLL def_bool NETCONSOLE -- cgit v1.2.3 From 2a50f28c326d20ab4556be1b867ecddf6aefbb88 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 26 Sep 2006 21:22:08 -0700 Subject: [ATALK]: endianness annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/net/appletalk/ipddp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c index 7f7dd450226..b98592a8bac 100644 --- a/drivers/net/appletalk/ipddp.c +++ b/drivers/net/appletalk/ipddp.c @@ -145,9 +145,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) /* Create the Extended DDP header */ ddp = (struct ddpehdr *)skb->data; - ddp->deh_len = skb->len; - ddp->deh_hops = 1; - ddp->deh_pad = 0; + ddp->deh_len_hops = htons(skb->len + (1<<10)); ddp->deh_sum = 0; /* @@ -170,7 +168,6 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) ddp->deh_sport = 72; *((__u8 *)(ddp+1)) = 22; /* ddp type = IP */ - *((__u16 *)ddp)=ntohs(*((__u16 *)ddp)); /* fix up length field */ skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */ -- cgit v1.2.3 From a144ea4b7a13087081ab5402fa9ad0bcfd249e67 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 28 Sep 2006 18:00:55 -0700 Subject: [IPV4]: annotate struct in_ifaddr ifa_local, ifa_address, ifa_mask, ifa_broadcast and ifa_anycast are net-endian. Annotated them and variables that are inferred to be net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- drivers/net/wan/hdlc_cisco.c | 2 +- drivers/net/wan/syncppp.c | 2 +- drivers/net/wireless/strip.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 0fb5f653d3c..c0bbddae4ec 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2252,7 +2252,7 @@ static u32 bond_glean_dev_ip(struct net_device *dev) { struct in_device *idev; struct in_ifaddr *ifa; - u32 addr = 0; + __be32 addr = 0; if (!dev) return 0; diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 7ec2b2f9b7e..b0bc5ddcf1b 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -161,7 +161,7 @@ static int cisco_rx(struct sk_buff *skb) struct hdlc_header *data = (struct hdlc_header*)skb->data; struct cisco_packet *cisco_data; struct in_device *in_dev; - u32 addr, mask; + __be32 addr, mask; if (skb->len < sizeof(struct hdlc_header)) goto rx_error; diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c index c13b459a013..d1173089f33 100644 --- a/drivers/net/wan/syncppp.c +++ b/drivers/net/wan/syncppp.c @@ -763,7 +763,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) { struct in_device *in_dev; struct in_ifaddr *ifa; - u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ + __be32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ #ifdef CONFIG_INET rcu_read_lock(); if ((in_dev = __in_dev_get_rcu(dev)) != NULL) diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index ccaf28e8db0..337c692f6fd 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -1342,7 +1342,7 @@ static unsigned char *strip_make_packet(unsigned char *buffer, * 'broadcast hub' radio (First byte of address being 0xFF means broadcast) */ if (haddr.c[0] == 0xFF) { - u32 brd = 0; + __be32 brd = 0; struct in_device *in_dev; rcu_read_lock(); @@ -1406,7 +1406,7 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb) int doreset = (long) jiffies - strip_info->watchdog_doreset >= 0; int doprobe = (long) jiffies - strip_info->watchdog_doprobe >= 0 && !doreset; - u32 addr, brd; + __be32 addr, brd; /* * 1. If we have a packet, encapsulate it and put it in the buffer -- cgit v1.2.3 From 3d3ebe741b2c06fe3df67739d09f6ef0e25ee41a Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 27 Sep 2006 15:59:15 -0700 Subject: [TG3]: Improve 5704S autoneg. Improve 5704S autoneg logic by using a serdes_counter field to keep track of the transient states. This eliminates a 200 msec busy loop in the code. Autoneg will take its course without the driver busy waiting for it to finish. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 66 ++++++++++++++++++++++++++++++++++--------------------- drivers/net/tg3.h | 7 +++++- 2 files changed, 47 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index aaf45b907a7..4eef798fbb7 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2406,24 +2406,27 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) expected_sg_dig_ctrl |= (1 << 12); if (sg_dig_ctrl != expected_sg_dig_ctrl) { + if ((tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) && + tp->serdes_counter && + ((mac_status & (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_RCVD_CFG)) == + MAC_STATUS_PCS_SYNCED)) { + tp->serdes_counter--; + current_link_up = 1; + goto out; + } +restart_autoneg: if (workaround) tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000); tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30)); udelay(5); tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl); - tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; + tp->serdes_counter = SERDES_AN_TIMEOUT_5704S; + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; } else if (mac_status & (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DET)) { - int i; - - /* Giver time to negotiate (~200ms) */ - for (i = 0; i < 40000; i++) { - sg_dig_status = tr32(SG_DIG_STATUS); - if (sg_dig_status & (0x3)) - break; - udelay(5); - } + sg_dig_status = tr32(SG_DIG_STATUS); mac_status = tr32(MAC_STATUS); if ((sg_dig_status & (1 << 1)) && @@ -2439,10 +2442,11 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) tg3_setup_flow_control(tp, local_adv, remote_adv); current_link_up = 1; - tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + tp->serdes_counter = 0; + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; } else if (!(sg_dig_status & (1 << 1))) { - if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) - tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + if (tp->serdes_counter) + tp->serdes_counter--; else { if (workaround) { u32 val = serdes_cfg; @@ -2466,9 +2470,17 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) !(mac_status & MAC_STATUS_RCVD_CFG)) { tg3_setup_flow_control(tp, 0, 0); current_link_up = 1; - } + tp->tg3_flags2 |= + TG3_FLG2_PARALLEL_DETECT; + tp->serdes_counter = + SERDES_PARALLEL_DET_TIMEOUT; + } else + goto restart_autoneg; } } + } else { + tp->serdes_counter = SERDES_AN_TIMEOUT_5704S; + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; } out: @@ -2599,14 +2611,16 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) MAC_STATUS_CFG_CHANGED)); udelay(5); if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) + MAC_STATUS_CFG_CHANGED | + MAC_STATUS_LNKSTATE_CHANGED)) == 0) break; } mac_status = tr32(MAC_STATUS); if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) { current_link_up = 0; - if (tp->link_config.autoneg == AUTONEG_ENABLE) { + if (tp->link_config.autoneg == AUTONEG_ENABLE && + tp->serdes_counter == 0) { tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS)); udelay(1); @@ -2711,7 +2725,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) tg3_writephy(tp, MII_BMCR, bmcr); tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); - tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; + tp->serdes_counter = SERDES_AN_TIMEOUT_5714S; tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; return err; @@ -2816,9 +2830,9 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) static void tg3_serdes_parallel_detect(struct tg3 *tp) { - if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) { + if (tp->serdes_counter) { /* Give autoneg time to complete. */ - tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + tp->serdes_counter--; return; } if (!netif_carrier_ok(tp->dev) && @@ -6660,12 +6674,14 @@ static void tg3_timer(unsigned long __opaque) need_setup = 1; } if (need_setup) { - tw32_f(MAC_MODE, - (tp->mac_mode & - ~MAC_MODE_PORT_MODE_MASK)); - udelay(40); - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); + if (!tp->serdes_counter) { + tw32_f(MAC_MODE, + (tp->mac_mode & + ~MAC_MODE_PORT_MODE_MASK)); + udelay(40); + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); + } tg3_setup_phy(tp, 0); } } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 3ecf356cfb0..f9c81baca8d 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2203,7 +2203,6 @@ struct tg3 { #define TG3_FLG2_PCI_EXPRESS 0x00000200 #define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400 #define TG3_FLG2_HW_AUTONEG 0x00000800 -#define TG3_FLG2_PHY_JUST_INITTED 0x00001000 #define TG3_FLG2_PHY_SERDES 0x00002000 #define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000 #define TG3_FLG2_FLASH 0x00008000 @@ -2236,6 +2235,12 @@ struct tg3 { u16 asf_counter; u16 asf_multiplier; + /* 1 second counter for transient serdes link events */ + u32 serdes_counter; +#define SERDES_AN_TIMEOUT_5704S 2 +#define SERDES_PARALLEL_DET_TIMEOUT 1 +#define SERDES_AN_TIMEOUT_5714S 1 + struct tg3_link_config link_config; struct tg3_bufmgr_config bufmgr_config; -- cgit v1.2.3 From 130b8e4d0e4edadcecee9fdff2c32f33d77c4fe9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 27 Sep 2006 16:00:40 -0700 Subject: [TG3]: Improve ASF heartbeat. Change to a different ASF heartbeat message code to improve reliability. There were some reports of unintended resets on real time kernels where the timer may be slow and cause the heartbeat to be late. Netpoll will also have the same problem because the timer irq will be unavailable. Using the new heartbeat code, the ASF firmware will also check the ring condition before resetting the chip when the heartbeat is expiring. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 20 ++++++++++++++++++-- drivers/net/tg3.h | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4eef798fbb7..6af8ebcf35f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6690,13 +6690,29 @@ static void tg3_timer(unsigned long __opaque) tp->timer_counter = tp->timer_multiplier; } - /* Heartbeat is only sent once every 2 seconds. */ + /* Heartbeat is only sent once every 2 seconds. + * + * The heartbeat is to tell the ASF firmware that the host + * driver is still alive. In the event that the OS crashes, + * ASF needs to reset the hardware to free up the FIFO space + * that may be filled with rx packets destined for the host. + * If the FIFO is full, ASF will no longer function properly. + * + * Unintended resets have been reported on real time kernels + * where the timer doesn't run on time. Netpoll will also have + * same problem. + * + * The new FWCMD_NICDRV_ALIVE3 command tells the ASF firmware + * to check the ring condition when the heartbeat is expiring + * before doing the reset. This will prevent most unintended + * resets. + */ if (!--tp->asf_counter) { if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { u32 val; tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, - FWCMD_NICDRV_ALIVE2); + FWCMD_NICDRV_ALIVE3); tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); /* 5 seconds timeout */ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index f9c81baca8d..f7462c2ccc0 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1537,6 +1537,7 @@ #define FWCMD_NICDRV_FIX_DMAR 0x00000005 #define FWCMD_NICDRV_FIX_DMAW 0x00000006 #define FWCMD_NICDRV_ALIVE2 0x0000000d +#define FWCMD_NICDRV_ALIVE3 0x0000000e #define NIC_SRAM_FW_CMD_LEN_MBOX 0x00000b7c #define NIC_SRAM_FW_CMD_DATA_MBOX 0x00000b80 #define NIC_SRAM_FW_ASF_STATUS_MBOX 0x00000c00 -- cgit v1.2.3 From 3f7045c1f28bedd44389b9392b54c6fdb83ee5c6 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 27 Sep 2006 16:02:29 -0700 Subject: [TG3]: PHY fixes. Some PHY related fixes: 1. Fix Serdes WoL. 2. Fix loopback test on 10/100 only devices. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 6af8ebcf35f..14e96452496 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1117,6 +1117,12 @@ static void tg3_nvram_unlock(struct tg3 *); static void tg3_power_down_phy(struct tg3 *tp) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + return; + + tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF); + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); + /* The PHY should not be powered down on some chips because * of bugs. */ @@ -1223,7 +1229,10 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); udelay(40); - mac_mode = MAC_MODE_PORT_MODE_MII; + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + mac_mode = MAC_MODE_PORT_MODE_GMII; + else + mac_mode = MAC_MODE_PORT_MODE_MII; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 || !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB)) @@ -1301,15 +1310,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) && - !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { - /* Turn off the PHY */ - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { - tg3_writephy(tp, MII_TG3_EXT_CTRL, - MII_TG3_EXT_CTRL_FORCE_LED_OFF); - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); - tg3_power_down_phy(tp); - } - } + !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) + tg3_power_down_phy(tp); tg3_frob_aux_power(tp); @@ -7889,7 +7891,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; if ((wol->wolopts & WAKE_MAGIC) && - tp->tg3_flags2 & TG3_FLG2_PHY_SERDES && + tp->tg3_flags2 & TG3_FLG2_ANY_SERDES && !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) return -EINVAL; @@ -8573,12 +8575,22 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) return 0; mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | - MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY | - MAC_MODE_PORT_MODE_GMII; + MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY; + if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) + mac_mode |= MAC_MODE_PORT_MODE_MII; + else + mac_mode |= MAC_MODE_PORT_MODE_GMII; tw32(MAC_MODE, mac_mode); } else if (loopback_mode == TG3_PHY_LOOPBACK) { - tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX | - BMCR_SPEED1000); + u32 val; + + val = BMCR_LOOPBACK | BMCR_FULLDPLX; + if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) + val |= BMCR_SPEED100; + else + val |= BMCR_SPEED1000; + + tg3_writephy(tp, MII_BMCR, val); udelay(40); /* reset to prevent losing 1st rx packet intermittently */ if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { @@ -8587,7 +8599,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) tw32_f(MAC_RX_MODE, tp->rx_mode); } mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | - MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; + MAC_MODE_LINK_POLARITY; + if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) + mac_mode |= MAC_MODE_PORT_MODE_MII; + else + mac_mode |= MAC_MODE_PORT_MODE_GMII; if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { mac_mode &= ~MAC_MODE_LINK_POLARITY; tg3_writephy(tp, MII_TG3_EXT_CTRL, @@ -8636,7 +8652,8 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) udelay(10); - for (i = 0; i < 10; i++) { + /* 250 usec to allow enough time on some 10/100 Mbps devices. */ + for (i = 0; i < 25; i++) { tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW); -- cgit v1.2.3 From 126a336822a6594662f5898f1ddf33e6d048fcc7 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 27 Sep 2006 16:03:07 -0700 Subject: [TG3]: Add 5722 and 5756 support. Add IDs to support 5722 and 5756. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 3 +++ drivers/net/tg3.h | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 14e96452496..d443b737232 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -173,6 +173,7 @@ static struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)}, @@ -187,6 +188,7 @@ static struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)}, @@ -11273,6 +11275,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5780: return "5780"; case PHY_ID_BCM5755: return "5755"; case PHY_ID_BCM5787: return "5787"; + case PHY_ID_BCM5756: return "5722/5756"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index f7462c2ccc0..feed13dc871 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2282,6 +2282,7 @@ struct tg3 { #define PHY_ID_BCM5780 0x60008350 #define PHY_ID_BCM5755 0xbc050cc0 #define PHY_ID_BCM5787 0xbc050ce0 +#define PHY_ID_BCM5756 0xbc050ed0 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff #define PHY_ID_REV_MASK 0x0000000f @@ -2308,7 +2309,8 @@ struct tg3 { (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ - (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \ + (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; -- cgit v1.2.3 From 7a6f4369449a471a6e5718a87c53ac75a46960ba Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 27 Sep 2006 16:03:31 -0700 Subject: [TG3]: Add tg3_poll_fw(). Put the firmware polling logic into a separate function. This makes the code cleaner. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 54 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d443b737232..eafca2a0dd0 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4662,6 +4662,35 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind) } } +static int tg3_poll_fw(struct tg3 *tp) +{ + int i; + u32 val; + + /* Wait for firmware initialization to complete. */ + for (i = 0; i < 100000; i++) { + tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); + if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) + break; + udelay(10); + } + + /* Chip might not be fitted with firmware. Some Sun onboard + * parts are configured like that. So don't signal the timeout + * of the above loop as an error, but do report the lack of + * running firmware once. + */ + if (i >= 100000 && + !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) { + tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED; + + printk(KERN_INFO PFX "%s: No firmware running.\n", + tp->dev->name); + } + + return 0; +} + static void tg3_stop_fw(struct tg3 *); /* tp->lock is held. */ @@ -4669,7 +4698,7 @@ static int tg3_chip_reset(struct tg3 *tp) { u32 val; void (*write_op)(struct tg3 *, u32, u32); - int i; + int err; tg3_nvram_lock(tp); @@ -4829,26 +4858,9 @@ static int tg3_chip_reset(struct tg3 *tp) tw32_f(MAC_MODE, 0); udelay(40); - /* Wait for firmware initialization to complete. */ - for (i = 0; i < 100000; i++) { - tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); - if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) - break; - udelay(10); - } - - /* Chip might not be fitted with firmare. Some Sun onboard - * parts are configured like that. So don't signal the timeout - * of the above loop as an error, but do report the lack of - * running firmware once. - */ - if (i >= 100000 && - !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) { - tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED; - - printk(KERN_INFO PFX "%s: No firmware running.\n", - tp->dev->name); - } + err = tg3_poll_fw(tp); + if (err) + return err; if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) { -- cgit v1.2.3 From b5d3772ccbe0bc5ac8ffbb5356b74ca698aee28c Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 27 Sep 2006 16:06:21 -0700 Subject: [TG3]: Add basic 5906 support. Add support for the new 5709 device. This is a new 10/100 Mbps chip. The mailbox access and firmware interface are quite different from all other tg3 chips. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++----- drivers/net/tg3.h | 28 ++++++++++-- 2 files changed, 139 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index eafca2a0dd0..2b062d77651 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -199,6 +199,8 @@ static struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, @@ -426,6 +428,16 @@ static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) readl(mbox); } +static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off) +{ + return (readl(tp->regs + off + GRCMBOX_BASE)); +} + +static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val) +{ + writel(val, tp->regs + off + GRCMBOX_BASE); +} + #define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val) #define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val)) #define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val) @@ -441,6 +453,10 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) && + (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) + return; + spin_lock_irqsave(&tp->indirect_lock, flags); if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); @@ -462,6 +478,12 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) { unsigned long flags; + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) && + (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) { + *val = 0; + return; + } + spin_lock_irqsave(&tp->indirect_lock, flags); if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); @@ -491,6 +513,9 @@ static inline void tg3_cond_int(struct tg3 *tp) if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) && (tp->hw_status->status & SD_STATUS_UPDATED)) tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT); + else + tw32(HOSTCC_MODE, tp->coalesce_mode | + (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); } static void tg3_enable_ints(struct tg3 *tp) @@ -656,6 +681,10 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) unsigned int loops; int ret; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 && + (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL)) + return 0; + if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); @@ -1207,7 +1236,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) tg3_setup_phy(tp, 0); } - if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 val; + + val = tr32(GRC_VCPU_EXT_CTRL); + tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL); + } else if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { int i; u32 val; @@ -4667,6 +4701,15 @@ static int tg3_poll_fw(struct tg3 *tp) int i; u32 val; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + for (i = 0; i < 400; i++) { + if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE) + return 0; + udelay(10); + } + return -ENODEV; + } + /* Wait for firmware initialization to complete. */ for (i = 0; i < 100000; i++) { tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); @@ -4735,6 +4778,12 @@ static int tg3_chip_reset(struct tg3 *tp) } } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + tw32(VCPU_STATUS, tr32(VCPU_STATUS) | VCPU_STATUS_DRV_RESET); + tw32(GRC_VCPU_EXT_CTRL, + tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU); + } + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) val |= GRC_MISC_CFG_KEEP_GPHY_POWER; tw32(GRC_MISC_CFG, val); @@ -5066,6 +5115,12 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) BUG_ON(offset == TX_CPU_BASE && (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 val = tr32(GRC_VCPU_EXT_CTRL); + + tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU); + return 0; + } if (offset == RX_CPU_BASE) { for (i = 0; i < 10000; i++) { tw32(offset + CPU_STATE, 0xffffffff); @@ -6070,6 +6125,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) val = 1; else if (val > tp->rx_std_max_post) val = tp->rx_std_max_post; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1) + tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2); + + if (val > (TG3_RX_INTERNAL_RING_SZ_5906 / 2)) + val = TG3_RX_INTERNAL_RING_SZ_5906 / 2; + } tw32(RCVBDI_STD_THRESH, val); @@ -6984,9 +7046,10 @@ static int tg3_open(struct net_device *dev) if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) { - u32 val = tr32(0x7c04); + u32 val = tr32(PCIE_TRANSACTION_CFG); - tw32(0x7c04, val | (1 << 29)); + tw32(PCIE_TRANSACTION_CFG, + val | PCIE_TRANS_CFG_1SHOT_MSI); } } } @@ -7941,7 +8004,8 @@ static int tg3_set_tso(struct net_device *dev, u32 value) return -EINVAL; return 0; } - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) { + if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) { if (value) dev->features |= NETIF_F_TSO6; else @@ -9257,6 +9321,13 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) } } +static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp) +{ + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; +} + /* Chips other than 5700/5701 use the NVRAM for fetching info. */ static void __devinit tg3_nvram_init(struct tg3 *tp) { @@ -9293,6 +9364,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) tg3_get_5755_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tg3_get_5787_nvram_info(tp); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tg3_get_5906_nvram_info(tp); else tg3_get_nvram_info(tp); @@ -9766,6 +9839,12 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) /* Assume an onboard device by default. */ tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) + tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; + return; + } + tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg, led_cfg; @@ -10097,7 +10176,10 @@ static void __devinit tg3_read_partno(struct tg3 *tp) } out_not_found: - strcpy(tp->board_part_number, "none"); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + strcpy(tp->board_part_number, "BCM95906"); + else + strcpy(tp->board_part_number, "none"); } static void __devinit tg3_read_fw_ver(struct tg3 *tp) @@ -10299,6 +10381,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; @@ -10308,7 +10391,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; } else { @@ -10325,7 +10409,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) @@ -10455,6 +10540,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) pci_cmd &= ~PCI_COMMAND_MEMORY; pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + tp->read32_mbox = tg3_read32_mbox_5906; + tp->write32_mbox = tg3_write32_mbox_5906; + tp->write32_tx_mbox = tg3_write32_mbox_5906; + tp->write32_rx_mbox = tg3_write32_mbox_5906; + } if (tp->write32 == tg3_write_indirect_reg32 || ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) && @@ -10526,6 +10617,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) && (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) || (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED; @@ -10539,7 +10631,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG; - else + else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; } @@ -10629,7 +10721,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F))) + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->tg3_flags |= TG3_FLAG_10_100_ONLY; err = tg3_phy_probe(tp); @@ -10680,7 +10773,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * straddle the 4GB address boundary in some cases. */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->dev->hard_start_xmit = tg3_start_xmit; else tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug; @@ -10761,6 +10855,8 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) else tg3_nvram_unlock(tp); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + mac_offset = 0x10; /* First try to get it from MAC address mailbox. */ tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi); @@ -11244,6 +11340,12 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) DEFAULT_MB_MACRX_LOW_WATER_5705; tp->bufmgr_config.mbuf_high_water = DEFAULT_MB_HIGH_WATER_5705; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + tp->bufmgr_config.mbuf_mac_rx_low_water = + DEFAULT_MB_MACRX_LOW_WATER_5906; + tp->bufmgr_config.mbuf_high_water = + DEFAULT_MB_HIGH_WATER_5906; + } tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780; @@ -11288,6 +11390,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5755: return "5755"; case PHY_ID_BCM5787: return "5787"; case PHY_ID_BCM5756: return "5722/5756"; + case PHY_ID_BCM5906: return "5906"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; @@ -11590,7 +11693,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, */ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { dev->features |= NETIF_F_TSO; - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) + if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) dev->features |= NETIF_F_TSO6; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index feed13dc871..2f5e00c9601 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -24,6 +24,8 @@ #define RX_COPY_THRESHOLD 256 +#define TG3_RX_INTERNAL_RING_SZ_5906 32 + #define RX_STD_MAX_SIZE 1536 #define RX_STD_MAX_SIZE_5705 512 #define RX_JUMBO_MAX_SIZE 0xdeadbeef /* XXX */ @@ -129,6 +131,7 @@ #define CHIPREV_ID_5752_A0_HW 0x5000 #define CHIPREV_ID_5752_A0 0x6000 #define CHIPREV_ID_5752_A1 0x6001 +#define CHIPREV_ID_5906_A1 0xc001 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 @@ -141,6 +144,7 @@ #define ASIC_REV_5714 0x09 #define ASIC_REV_5755 0x0a #define ASIC_REV_5787 0x0b +#define ASIC_REV_5906 0x0c #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -646,7 +650,8 @@ #define SNDDATAI_SCTRL_FORCE_ZERO 0x00000010 #define SNDDATAI_STATSENAB 0x00000c0c #define SNDDATAI_STATSINCMASK 0x00000c10 -/* 0xc14 --> 0xc80 unused */ +#define ISO_PKT_TX 0x00000c20 +/* 0xc24 --> 0xc80 unused */ #define SNDDATAI_COS_CNT_0 0x00000c80 #define SNDDATAI_COS_CNT_1 0x00000c84 #define SNDDATAI_COS_CNT_2 0x00000c88 @@ -997,11 +1002,13 @@ #define BUFMGR_MB_MACRX_LOW_WATER 0x00004414 #define DEFAULT_MB_MACRX_LOW_WATER 0x00000020 #define DEFAULT_MB_MACRX_LOW_WATER_5705 0x00000010 +#define DEFAULT_MB_MACRX_LOW_WATER_5906 0x00000004 #define DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098 #define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b #define BUFMGR_MB_HIGH_WATER 0x00004418 #define DEFAULT_MB_HIGH_WATER 0x00000060 #define DEFAULT_MB_HIGH_WATER_5705 0x00000060 +#define DEFAULT_MB_HIGH_WATER_5906 0x00000010 #define DEFAULT_MB_HIGH_WATER_JUMBO 0x0000017c #define DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096 #define BUFMGR_RX_MB_ALLOC_REQ 0x0000441c @@ -1138,7 +1145,12 @@ #define TX_CPU_STATE 0x00005404 #define TX_CPU_PGMCTR 0x0000541c +#define VCPU_STATUS 0x00005100 +#define VCPU_STATUS_INIT_DONE 0x04000000 +#define VCPU_STATUS_DRV_RESET 0x08000000 + /* Mailboxes */ +#define GRCMBOX_BASE 0x00005600 #define GRCMBOX_INTERRUPT_0 0x00005800 /* 64-bit */ #define GRCMBOX_INTERRUPT_1 0x00005808 /* 64-bit */ #define GRCMBOX_INTERRUPT_2 0x00005810 /* 64-bit */ @@ -1398,7 +1410,10 @@ #define GRC_EEPROM_CTRL 0x00006840 #define GRC_MDI_CTRL 0x00006844 #define GRC_SEEPROM_DELAY 0x00006848 -/* 0x684c --> 0x6c00 unused */ +/* 0x684c --> 0x6890 unused */ +#define GRC_VCPU_EXT_CTRL 0x00006890 +#define GRC_VCPU_EXT_CTRL_HALT_CPU 0x00400000 +#define GRC_VCPU_EXT_CTRL_DISABLE_WOL 0x20000000 #define GRC_FASTBOOT_PC 0x00006894 /* 5752, 5755, 5787 */ /* 0x6c00 --> 0x7000 unused */ @@ -1485,7 +1500,11 @@ #define NVRAM_WRITE1 0x00007028 /* 0x702c --> 0x7400 unused */ -/* 0x7400 --> 0x8000 unused */ +/* 0x7400 --> 0x7c00 unused */ +#define PCIE_TRANSACTION_CFG 0x00007c04 +#define PCIE_TRANS_CFG_1SHOT_MSI 0x20000000 +#define PCIE_TRANS_CFG_LOM 0x00000020 + #define TG3_EEPROM_MAGIC 0x669955aa @@ -2283,6 +2302,7 @@ struct tg3 { #define PHY_ID_BCM5755 0xbc050cc0 #define PHY_ID_BCM5787 0xbc050ce0 #define PHY_ID_BCM5756 0xbc050ed0 +#define PHY_ID_BCM5906 0xdc00ac40 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff #define PHY_ID_REV_MASK 0x0000000f @@ -2310,7 +2330,7 @@ struct tg3 { (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \ - (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; -- cgit v1.2.3 From 715116a12610b67c1d301a9b845ce95f7247dad3 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 27 Sep 2006 16:09:25 -0700 Subject: [TG3]: Add 5709 PHY support. Add support for the 5709 10/100 PHY. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 37 +++++++++++++++++++++++++++++++++---- drivers/net/tg3.h | 6 ++++++ 2 files changed, 39 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 2b062d77651..23f5744bdff 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1035,6 +1035,24 @@ out: phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 phy_reg; + + /* adjust output voltage */ + tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12); + + if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) { + u32 phy_reg2; + + tg3_writephy(tp, MII_TG3_EPHY_TEST, + phy_reg | MII_TG3_EPHY_SHADOW_EN); + /* Enable auto-MDIX */ + if (!tg3_readphy(tp, 0x10, &phy_reg2)) + tg3_writephy(tp, 0x10, phy_reg2 | 0x4000); + tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg); + } + } + tg3_phy_set_wirespeed(tp); return 0; } @@ -1151,8 +1169,11 @@ static void tg3_power_down_phy(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) return; - tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF); - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) { + tg3_writephy(tp, MII_TG3_EXT_CTRL, + MII_TG3_EXT_CTRL_FORCE_LED_OFF); + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); + } /* The PHY should not be powered down on some chips because * of bugs. @@ -1505,6 +1526,13 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 break; default: + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 : + SPEED_10; + *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL : + DUPLEX_HALF; + break; + } *speed = SPEED_INVALID; *duplex = DUPLEX_INVALID; break; @@ -1787,7 +1815,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG); - else + else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) tg3_writephy(tp, MII_TG3_IMASK, ~0); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || @@ -6552,7 +6580,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (err) return err; - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) { u32 tmp; /* Clear CRC stats. */ diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 2f5e00c9601..9259d12fabd 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1624,6 +1624,7 @@ #define MII_TG3_DSP_RW_PORT 0x15 /* DSP coefficient read/write port */ #define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */ +#define MII_TG3_EPHY_PTEST 0x17 /* 5906 PHY register */ #define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */ @@ -1637,6 +1638,8 @@ #define MII_TG3_AUX_STAT_100FULL 0x0500 #define MII_TG3_AUX_STAT_1000HALF 0x0600 #define MII_TG3_AUX_STAT_1000FULL 0x0700 +#define MII_TG3_AUX_STAT_100 0x0008 +#define MII_TG3_AUX_STAT_FULL 0x0001 #define MII_TG3_ISTAT 0x1a /* IRQ status register */ #define MII_TG3_IMASK 0x1b /* IRQ mask register */ @@ -1647,6 +1650,9 @@ #define MII_TG3_INT_DUPLEXCHG 0x0008 #define MII_TG3_INT_ANEG_PAGE_RX 0x0400 +#define MII_TG3_EPHY_TEST 0x1f /* 5906 PHY register */ +#define MII_TG3_EPHY_SHADOW_EN 0x80 + /* There are two ways to manage the TX descriptors on the tigon3. * Either the descriptors are in host DMA'able memory, or they * exist only in the cards on-chip SRAM. All 16 send bds are under -- cgit v1.2.3 From b16250e3d1c55820f08f0296624a423122ea9805 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 27 Sep 2006 16:10:14 -0700 Subject: [TG3]: Add 5709 self-test support. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++------- drivers/net/tg3.h | 4 ++ 2 files changed, 111 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 23f5744bdff..21843de4a88 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3615,8 +3615,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, if ((sblk->status & SD_STATUS_UPDATED) || !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000001); + tg3_disable_ints(tp); return IRQ_RETVAL(1); } return IRQ_RETVAL(0); @@ -6860,8 +6859,7 @@ static int tg3_request_irq(struct tg3 *tp) static int tg3_test_interrupt(struct tg3 *tp) { struct net_device *dev = tp->dev; - int err, i; - u32 int_mbox = 0; + int err, i, intr_ok = 0; if (!netif_running(dev)) return -ENODEV; @@ -6882,10 +6880,18 @@ static int tg3_test_interrupt(struct tg3 *tp) HOSTCC_MODE_NOW); for (i = 0; i < 5; i++) { + u32 int_mbox, misc_host_ctrl; + int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); - if (int_mbox != 0) + misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL); + + if ((int_mbox != 0) || + (misc_host_ctrl & MISC_HOST_CTRL_MASK_PCI_INT)) { + intr_ok = 1; break; + } + msleep(10); } @@ -6898,7 +6904,7 @@ static int tg3_test_interrupt(struct tg3 *tp) if (err) return err; - if (int_mbox != 0) + if (intr_ok) return 0; return -EIO; @@ -8288,6 +8294,8 @@ static void tg3_get_ethtool_stats (struct net_device *dev, #define NVRAM_TEST_SIZE 0x100 #define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14 +#define NVRAM_SELFBOOT_HW_SIZE 0x20 +#define NVRAM_SELFBOOT_DATA_SIZE 0x1c static int tg3_test_nvram(struct tg3 *tp) { @@ -8299,12 +8307,14 @@ static int tg3_test_nvram(struct tg3 *tp) if (magic == TG3_EEPROM_MAGIC) size = NVRAM_TEST_SIZE; - else if ((magic & 0xff000000) == 0xa5000000) { + else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) { if ((magic & 0xe00000) == 0x200000) size = NVRAM_SELFBOOT_FORMAT1_SIZE; else return 0; - } else + } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) + size = NVRAM_SELFBOOT_HW_SIZE; + else return -EIO; buf = kmalloc(size, GFP_KERNEL); @@ -8323,7 +8333,8 @@ static int tg3_test_nvram(struct tg3 *tp) goto out; /* Selfboot format */ - if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) { + if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) == + TG3_EEPROM_MAGIC_FW) { u8 *buf8 = (u8 *) buf, csum8 = 0; for (i = 0; i < size; i++) @@ -8338,6 +8349,51 @@ static int tg3_test_nvram(struct tg3 *tp) goto out; } + if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) == + TG3_EEPROM_MAGIC_HW) { + u8 data[NVRAM_SELFBOOT_DATA_SIZE]; + u8 parity[NVRAM_SELFBOOT_DATA_SIZE]; + u8 *buf8 = (u8 *) buf; + int j, k; + + /* Separate the parity bits and the data bytes. */ + for (i = 0, j = 0, k = 0; i < NVRAM_SELFBOOT_HW_SIZE; i++) { + if ((i == 0) || (i == 8)) { + int l; + u8 msk; + + for (l = 0, msk = 0x80; l < 7; l++, msk >>= 1) + parity[k++] = buf8[i] & msk; + i++; + } + else if (i == 16) { + int l; + u8 msk; + + for (l = 0, msk = 0x20; l < 6; l++, msk >>= 1) + parity[k++] = buf8[i] & msk; + i++; + + for (l = 0, msk = 0x80; l < 8; l++, msk >>= 1) + parity[k++] = buf8[i] & msk; + i++; + } + data[j++] = buf8[i]; + } + + err = -EIO; + for (i = 0; i < NVRAM_SELFBOOT_DATA_SIZE; i++) { + u8 hw8 = hweight8(data[i]); + + if ((hw8 & 0x1) && parity[i]) + goto out; + else if (!(hw8 & 0x1) && !parity[i]) + goto out; + } + err = 0; + goto out; + } + /* Bootstrap checksum at offset 0x10 */ csum = calc_crc((unsigned char *) buf, 0x10); if(csum != cpu_to_le32(buf[0x10/4])) @@ -8384,7 +8440,7 @@ static int tg3_test_link(struct tg3 *tp) /* Only test the commonly used registers */ static int tg3_test_registers(struct tg3 *tp) { - int i, is_5705; + int i, is_5705, is_5750; u32 offset, read_mask, write_mask, val, save_val, read_val; static struct { u16 offset; @@ -8392,6 +8448,7 @@ static int tg3_test_registers(struct tg3 *tp) #define TG3_FL_5705 0x1 #define TG3_FL_NOT_5705 0x2 #define TG3_FL_NOT_5788 0x4 +#define TG3_FL_NOT_5750 0x8 u32 read_mask; u32 write_mask; } reg_tbl[] = { @@ -8502,9 +8559,9 @@ static int tg3_test_registers(struct tg3 *tp) 0xffffffff, 0x00000000 }, /* Buffer Manager Control Registers. */ - { BUFMGR_MB_POOL_ADDR, 0x0000, + { BUFMGR_MB_POOL_ADDR, TG3_FL_NOT_5750, 0x00000000, 0x007fff80 }, - { BUFMGR_MB_POOL_SIZE, 0x0000, + { BUFMGR_MB_POOL_SIZE, TG3_FL_NOT_5750, 0x00000000, 0x007fffff }, { BUFMGR_MB_RDMA_LOW_WATER, 0x0000, 0x00000000, 0x0000003f }, @@ -8530,10 +8587,12 @@ static int tg3_test_registers(struct tg3 *tp) { 0xffff, 0x0000, 0x00000000, 0x00000000 }, }; - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + is_5705 = is_5750 = 0; + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { is_5705 = 1; - else - is_5705 = 0; + if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) + is_5750 = 1; + } for (i = 0; reg_tbl[i].offset != 0xffff; i++) { if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705)) @@ -8546,6 +8605,9 @@ static int tg3_test_registers(struct tg3 *tp) (reg_tbl[i].flags & TG3_FL_NOT_5788)) continue; + if (is_5750 && (reg_tbl[i].flags & TG3_FL_NOT_5750)) + continue; + offset = (u32) reg_tbl[i].offset; read_mask = reg_tbl[i].read_mask; write_mask = reg_tbl[i].write_mask; @@ -8637,6 +8699,13 @@ static int tg3_test_memory(struct tg3 *tp) { 0x00008000, 0x02000}, { 0x00010000, 0x0c000}, { 0xffffffff, 0x00000} + }, mem_tbl_5906[] = { + { 0x00000200, 0x00008}, + { 0x00004000, 0x00400}, + { 0x00006000, 0x00400}, + { 0x00008000, 0x01000}, + { 0x00010000, 0x01000}, + { 0xffffffff, 0x00000} }; struct mem_entry *mem_tbl; int err = 0; @@ -8646,6 +8715,8 @@ static int tg3_test_memory(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) mem_tbl = mem_tbl_5755; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + mem_tbl = mem_tbl_5906; else mem_tbl = mem_tbl_5705; } else @@ -8691,6 +8762,21 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) } else if (loopback_mode == TG3_PHY_LOOPBACK) { u32 val; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 phytest; + + if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phytest)) { + u32 phy; + + tg3_writephy(tp, MII_TG3_EPHY_TEST, + phytest | MII_TG3_EPHY_SHADOW_EN); + if (!tg3_readphy(tp, 0x1b, &phy)) + tg3_writephy(tp, 0x1b, phy & ~0x20); + if (!tg3_readphy(tp, 0x10, &phy)) + tg3_writephy(tp, 0x10, phy & ~0x4000); + tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest); + } + } val = BMCR_LOOPBACK | BMCR_FULLDPLX; if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) val |= BMCR_SPEED100; @@ -8699,6 +8785,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) tg3_writephy(tp, MII_BMCR, val); udelay(40); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800); + /* reset to prevent losing 1st rx packet intermittently */ if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { tw32_f(MAC_RX_MODE, RX_MODE_RESET); @@ -9112,7 +9201,9 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp) if (tg3_nvram_read_swab(tp, 0, &magic) != 0) return; - if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000)) + if ((magic != TG3_EEPROM_MAGIC) && + ((magic & TG3_EEPROM_MAGIC_FW_MSK) != TG3_EEPROM_MAGIC_FW) && + ((magic & TG3_EEPROM_MAGIC_HW_MSK) != TG3_EEPROM_MAGIC_HW)) return; /* diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 9259d12fabd..92f53000bce 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1507,6 +1507,10 @@ #define TG3_EEPROM_MAGIC 0x669955aa +#define TG3_EEPROM_MAGIC_FW 0xa5000000 +#define TG3_EEPROM_MAGIC_FW_MSK 0xff000000 +#define TG3_EEPROM_MAGIC_HW 0xabcd +#define TG3_EEPROM_MAGIC_HW_MSK 0xffff /* 32K Window into NIC internal memory */ #define NIC_SRAM_WIN_BASE 0x00008000 -- cgit v1.2.3 From 1533d382155ee888d9621391c108ffb7a68bb25d Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 27 Sep 2006 16:10:35 -0700 Subject: [TG3]: Update version and reldate. Update version to 3.66. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 21843de4a88..c25ba273b74 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.65" -#define DRV_MODULE_RELDATE "August 07, 2006" +#define DRV_MODULE_VERSION "3.66" +#define DRV_MODULE_RELDATE "September 23, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3 From c9aa6895371b2a257401f59d3393c9f7ac5a8698 Mon Sep 17 00:00:00 2001 From: Michal Ostrowski Date: Wed, 27 Sep 2006 16:11:25 -0700 Subject: [PPPOE]: Advertise PPPoE MTU PPPoE must advertise the underlying device's MTU via the ppp channel descriptor structure, as multilink functionality depends on it. Signed-off-by: Michal Ostrowski Acked-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/pppoe.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 5666ed99814..0adee733b76 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -600,6 +600,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.hdrlen = (sizeof(struct pppoe_hdr) + dev->hard_header_len); + po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr); po->chan.private = sk; po->chan.ops = &pppoe_chan_ops; -- cgit v1.2.3 From 778e6398d32590eaf2333706318cbcd04dbe50b7 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 27 Sep 2006 20:06:16 -0700 Subject: [IrDA]: irda-usb needs firmware loader With the inclusion of the stir421x code, we now need to select FW_LOADER whenever we try to build the irda-usb code. Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index e9e6d99a9ad..7c8ccc09b60 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -287,6 +287,7 @@ comment "FIR device drivers" config USB_IRDA tristate "IrDA USB dongles" depends on IRDA && USB + select FW_LOADER ---help--- Say Y here if you want to build support for the USB IrDA FIR Dongle device driver. To compile it as a module, choose M here: the module -- cgit v1.2.3 From 7fa6b06689085a3e2237cf810f5e0c114e00a2da Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 27 Sep 2006 20:33:34 -0700 Subject: [NET] loopback: minor statistics optimization The loopback device status structure is a singleton and doesn't need to be allocated. Add ethtool_ops hooks to show checksum always on, and make ethtool_ops const. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/loopback.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index f429b19bf62..4178b4b1d2d 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -161,15 +161,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) return(0); } +static struct net_device_stats loopback_stats; + static struct net_device_stats *get_stats(struct net_device *dev) { - struct net_device_stats *stats = dev->priv; + struct net_device_stats *stats = &loopback_stats; int i; - if (!stats) { - return NULL; - } - memset(stats, 0, sizeof(struct net_device_stats)); for_each_possible_cpu(i) { @@ -185,19 +183,28 @@ static struct net_device_stats *get_stats(struct net_device *dev) return stats; } -static u32 loopback_get_link(struct net_device *dev) +static u32 always_on(struct net_device *dev) { return 1; } static const struct ethtool_ops loopback_ethtool_ops = { - .get_link = loopback_get_link, + .get_link = always_on, .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, + .get_tx_csum = always_on, + .get_sg = always_on, + .get_rx_csum = always_on, }; +/* + * The loopback device is special. There is only one instance and + * it is statically allocated. Don't do this for other devices. + */ struct net_device loopback_dev = { .name = "lo", + .get_stats = &get_stats, + .priv = &loopback_stats, .mtu = (16 * 1024) + 20 + 20 + 12, .hard_start_xmit = loopback_xmit, .hard_header = eth_header, @@ -221,16 +228,6 @@ struct net_device loopback_dev = { /* Setup and register the loopback device. */ int __init loopback_init(void) { - struct net_device_stats *stats; - - /* Can survive without statistics */ - stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); - if (stats) { - memset(stats, 0, sizeof(struct net_device_stats)); - loopback_dev.priv = stats; - loopback_dev.get_stats = &get_stats; - } - return register_netdev(&loopback_dev); }; -- cgit v1.2.3 From 2fd19a687c256fa4c4750465b9856e2c80660ec8 Mon Sep 17 00:00:00 2001 From: Lamarque Vieira Souza Date: Wed, 27 Sep 2006 22:48:36 -0700 Subject: [IrDA] nsc-ircc: Configuration base address for PC87383 According to NatSemi datasheet, the configuration base address for the PC8738x family is 0x2e or 0x164. 0x0 doesn't appear in any datasheet. Patch from Lamarque Vieira Souza Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/nsc-ircc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index cb62f2a9676..7185a4ee3c1 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -110,7 +110,7 @@ static nsc_chip_t chips[] = { { "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf8, nsc_ircc_probe_338, nsc_ircc_init_338 }, /* Contributed by Steffen Pingel - IBM X40 */ - { "PC8738x", { 0x164e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff, + { "PC8738x", { 0x164e, 0x4e, 0x2e }, 0x20, 0xf4, 0xff, nsc_ircc_probe_39x, nsc_ircc_init_39x }, /* Contributed by Jan Frey - IBM A30/A31 */ { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, -- cgit v1.2.3 From 895de090d4302a02a77cdf366fc6e54fc2001857 Mon Sep 17 00:00:00 2001 From: "Linus Walleij (LD/EAB" Date: Wed, 27 Sep 2006 22:49:23 -0700 Subject: [IrDA] smsc-ircc: More laptops detected This patch detects the smsc-ircc chipset on the nx1000 (including nx7000 and nx7010) and the nx5000 HP/Compaq laptop series. Patch from "Linus Walleij (LD/EAB)" Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/smsc-ircc2.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 2eff45bedc7..22358ff68c4 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -2354,6 +2354,26 @@ static int __init smsc_superio_lpc(unsigned short cfg_base) #define PCIID_VENDOR_INTEL 0x8086 #define PCIID_VENDOR_ALI 0x10b9 static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __initdata = { + /* + * Subsystems needing entries: + * 0x10b9:0x1533 0x103c:0x0850 HP nx9010 family + * 0x10b9:0x1533 0x0e11:0x005a Compaq nc4000 family + * 0x8086:0x24cc 0x0e11:0x002a HP nx9000 family + */ + { + /* Guessed entry */ + .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ + .device = 0x24cc, + .subvendor = 0x103c, + .subdevice = 0x08bc, + .sir_io = 0x02f8, + .fir_io = 0x0130, + .fir_irq = 0x05, + .fir_dma = 0x03, + .cfg_base = 0x004e, + .preconfigure = preconfigure_through_82801, + .name = "HP nx5000 family", + }, { .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ .device = 0x24cc, @@ -2366,7 +2386,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini .fir_dma = 0x03, .cfg_base = 0x004e, .preconfigure = preconfigure_through_82801, - .name = "HP nc8000", + .name = "HP nc8000 family", }, { .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ @@ -2379,7 +2399,21 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini .fir_dma = 0x03, .cfg_base = 0x004e, .preconfigure = preconfigure_through_82801, - .name = "HP nc6000", + .name = "HP nc6000 family", + }, + { + .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ + .device = 0x24cc, + .subvendor = 0x0e11, + .subdevice = 0x0860, + /* I assume these are the same for x1000 as for the others */ + .sir_io = 0x02e8, + .fir_io = 0x02f8, + .fir_irq = 0x07, + .fir_dma = 0x03, + .cfg_base = 0x002e, + .preconfigure = preconfigure_through_82801, + .name = "Compaq x1000 family", }, { /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */ -- cgit v1.2.3 From febac9b93724f3ee293e7e5450043ae28e61531a Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 27 Sep 2006 22:50:06 -0700 Subject: [IrDA] stir4200: removing undocumented bits handling FIFOCTL_RXERR and FIFOCTL_TXERR are undocumented bits, according to the Sigmatel datasheet. We should thus not take any assumption on their values and semantics. Problem spotted by andrzej zaborowski Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/stir4200.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c index d61b208b52a..12103c93f7e 100644 --- a/drivers/net/irda/stir4200.c +++ b/drivers/net/irda/stir4200.c @@ -149,8 +149,6 @@ enum StirFifoCtlMask { FIFOCTL_DIR = 0x10, FIFOCTL_CLR = 0x08, FIFOCTL_EMPTY = 0x04, - FIFOCTL_RXERR = 0x02, - FIFOCTL_TXERR = 0x01, }; enum StirDiagMask { @@ -615,19 +613,6 @@ static int fifo_txwait(struct stir_cb *stir, int space) pr_debug("fifo status 0x%lx count %lu\n", status, count); - /* error when receive/transmit fifo gets confused */ - if (status & FIFOCTL_RXERR) { - stir->stats.rx_fifo_errors++; - stir->stats.rx_errors++; - break; - } - - if (status & FIFOCTL_TXERR) { - stir->stats.tx_fifo_errors++; - stir->stats.tx_errors++; - break; - } - /* is fifo receiving already, or empty */ if (!(status & FIFOCTL_DIR) || (status & FIFOCTL_EMPTY)) -- cgit v1.2.3 From f1b7c5f459b21feba80f96415429ff2570d63e4d Mon Sep 17 00:00:00 2001 From: Komal Shah Date: Fri, 29 Sep 2006 01:59:15 -0700 Subject: [PATCH] OMAP: Add smc91x support for TI OMAP2420 H4 board Add smc91x support for TI OMAP2420 H4 EVM board. Cc: Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/smc91x.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index c660e33f43a..fedd1a37bc3 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -195,6 +195,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_IRQ_FLAGS (( \ machine_is_omap_h2() \ || machine_is_omap_h3() \ + || machine_is_omap_h4() \ || (machine_is_omap_innovator() && !cpu_is_omap1510()) \ ) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING) -- cgit v1.2.3 From d6bd3a39f7c6ebad49c261c3d458df974c880758 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Fri, 29 Sep 2006 01:59:48 -0700 Subject: [PATCH] Move valid_dma_direction() from x86_64 to generic code As suggested by Muli Ben-Yehuda this function is moved to generic code as may be useful for all archs. [akpm@osdl.org: fix] Signed-off-by: Rolf Eike Beer Cc: Muli Ben-Yehuda Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/fec_8xx/fec_main.c | 2 +- drivers/net/fs_enet/fs_enet.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c index 22ac2df1aeb..e17a1449ee1 100644 --- a/drivers/net/fec_8xx/fec_main.c +++ b/drivers/net/fec_8xx/fec_main.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -37,7 +38,6 @@ #include #include #include -#include #include "fec_8xx.h" diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index 95022c005f7..92590d8fc24 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h @@ -6,11 +6,10 @@ #include #include #include +#include #include -#include - #ifdef CONFIG_CPM1 #include -- cgit v1.2.3 From e8106b941ceab68cc5ff713df7b1276484554584 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 29 Sep 2006 02:01:08 -0700 Subject: [PATCH] lockdep: core, add enable/disable_irq_irqsave/irqrestore() APIs Introduce the disable_irq_nosync_lockdep_irqsave() and enable_irq_lockdep_irqrestore() APIs. These are needed for NE2000; basically NE2000 calls disable_irq and enable_irq as locking against the IRQ handler, but both in cases where interrupts are on and off. This means that lockdep needs to track the old state of the virtual irq flags on disable_irq, and restore these at enable_irq time. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/8390.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/8390.c b/drivers/net/8390.c index 5b6b05ed8f3..9d34056147a 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -299,7 +299,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) * Slow phase with lock held. */ - disable_irq_nosync_lockdep(dev->irq); + disable_irq_nosync_lockdep_irqsave(dev->irq, &flags); spin_lock(&ei_local->page_lock); @@ -338,7 +338,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); outb_p(ENISR_ALL, e8390_base + EN0_IMR); spin_unlock(&ei_local->page_lock); - enable_irq_lockdep(dev->irq); + enable_irq_lockdep_irqrestore(dev->irq, &flags); ei_local->stat.tx_errors++; return 1; } @@ -379,7 +379,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) outb_p(ENISR_ALL, e8390_base + EN0_IMR); spin_unlock(&ei_local->page_lock); - enable_irq_lockdep(dev->irq); + enable_irq_lockdep_irqrestore(dev->irq, &flags); dev_kfree_skb (skb); ei_local->stat.tx_bytes += send_length; -- cgit v1.2.3 From 8c6ba51bdad0de0dc2a2e2415d4dac2d0db6c1a1 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 29 Sep 2006 02:01:32 -0700 Subject: [PATCH] Uninitialized variable in drivers/net/wan/syncppp.c For len equal to 4, we never call sppp_lcp_conf_parse_options(), therefore rmagic does not get initialized. Signed-off-by: Eric Sesterhenn Acked-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/wan/syncppp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c index d1173089f33..218f7b574ab 100644 --- a/drivers/net/wan/syncppp.c +++ b/drivers/net/wan/syncppp.c @@ -469,7 +469,7 @@ static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb) struct net_device *dev = sp->pp_if; int len = skb->len; u8 *p, opt[6]; - u32 rmagic; + u32 rmagic = 0; if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { if (sp->pp_flags & PP_DEBUG) -- cgit v1.2.3 From f9317a40c4e09e20ef01601fc9f5de9e6acb5b96 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 29 Sep 2006 17:06:23 -0700 Subject: [BNX2]: Disable MSI on 5706 if AMD 8132 bridge is present. MSI is defined to be 32-bit write. The 5706 does 64-bit MSI writes with byte enables disabled on the unused 32-bit word. This is legal but causes problems on the AMD 8132 which will eventually stop responding after a while. Without this patch, the MSI test done by the driver during open will pass, but MSI will eventually stop working after a few MSIs are written by the device. AMD believes this incompatibility is unique to the 5706, and prefers to locally disable MSI rather than globally disabling it using pci_msi_quirk. Update version to 1.4.45. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 7fcf015021e..6b4edb63c4c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -56,8 +56,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.44" -#define DRV_MODULE_RELDATE "August 10, 2006" +#define DRV_MODULE_VERSION "1.4.45" +#define DRV_MODULE_RELDATE "September 29, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -5805,6 +5805,34 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->cmd_ticks_int = bp->cmd_ticks; } + /* Disable MSI on 5706 if AMD 8132 bridge is found. + * + * MSI is defined to be 32-bit write. The 5706 does 64-bit MSI writes + * with byte enables disabled on the unused 32-bit word. This is legal + * but causes problems on the AMD 8132 which will eventually stop + * responding after a while. + * + * AMD believes this incompatibility is unique to the 5706, and + * prefers to locally disable MSI rather than globally disabling it + * using pci_msi_quirk. + */ + if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) { + struct pci_dev *amd_8132 = NULL; + + while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_8132_BRIDGE, + amd_8132))) { + u8 rev; + + pci_read_config_byte(amd_8132, PCI_REVISION_ID, &rev); + if (rev >= 0x10 && rev <= 0x13) { + disable_msi = 1; + pci_dev_put(amd_8132); + break; + } + } + } + bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; bp->req_line_speed = 0; if (bp->phy_flags & PHY_SERDES_FLAG) { -- cgit v1.2.3