JS20 kernel
Jake Moilanen
moilanen at austin.ibm.com
Fri Aug 13 05:56:26 EST 2004
>
> Should I expect mainline 2.6 to work on an IBM JS20? Should I start
> with pSeries_defconfig?
>
The mainline should work w/ everything except the broadcom adapter. It
seems that the tg3 driver got regressed somewhere in the following
patch. Brian Rzycki is working on getting the correct fix.
Thanks,
Jake
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.1722.162.1 -> 1.1722.162.2
# drivers/net/tg3.h 1.42 -> 1.43
# drivers/net/tg3.c 1.184 -> 1.185
#
# --------------------------------------------
# 04/07/02 davem at nuts.davemloft.net 1.1722.162.2
# [TG3]: Fibre PHY fixes from Sun.
#
# - Support HW autoneg on 5704.
# - On serdes, no MII reg ioctl support.
# --------------------------------------------
#
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c Mon Jul 19 11:05:33 2004
+++ b/drivers/net/tg3.c Mon Jul 19 11:05:33 2004
@@ -1,8 +1,9 @@
/*
* tg3.c: Broadcom Tigon3 ethernet driver.
*
- * Copyright (C) 2001, 2002, 2003 David S. Miller (davem at redhat.com)
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem at redhat.com)
* Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik at pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
*/
#include <linux/config.h>
@@ -1961,6 +1962,67 @@
return ret;
}
+static int fiber_autoneg(struct tg3 *tp, u32 *flags)
+{
+ int res = 0;
+
+ if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
+ u32 dig_status;
+
+ dig_status = tr32(SG_DIG_STATUS);
+ *flags = 0;
+ if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
+ *flags |= MR_LP_ADV_ASYM_PAUSE;
+ if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
+ *flags |= MR_LP_ADV_SYM_PAUSE;
+
+ if ((dig_status & SG_DIG_AUTONEG_COMPLETE) &&
+ !(dig_status & (SG_DIG_AUTONEG_ERROR |
+ SG_DIG_PARTNER_FAULT_MASK)))
+ res = 1;
+ } else {
+ struct tg3_fiber_aneginfo aninfo;
+ int status = ANEG_FAILED;
+ unsigned int tick;
+ u32 tmp;
+
+ tw32_f(MAC_TX_AUTO_NEG, 0);
+
+ tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
+ tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
+ udelay(40);
+
+ tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
+ udelay(40);
+
+ memset(&aninfo, 0, sizeof(aninfo));
+ aninfo.flags |= MR_AN_ENABLE;
+ aninfo.state = ANEG_STATE_UNKNOWN;
+ aninfo.cur_time = 0;
+ tick = 0;
+ while (++tick < 195000) {
+ status = tg3_fiber_aneg_smachine(tp, &aninfo);
+ if (status == ANEG_DONE || status == ANEG_FAILED)
+ break;
+
+ udelay(1);
+ }
+
+ tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
+ tw32_f(MAC_MODE, tp->mac_mode);
+ udelay(40);
+
+ *flags = aninfo.flags;
+
+ if (status == ANEG_DONE &&
+ (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
+ MR_LP_ADV_FULL_DUPLEX)))
+ res = 1;
+ }
+
+ return res;
+}
+
static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
{
u32 orig_pause_cfg;
@@ -1980,6 +2042,20 @@
tw32_f(MAC_MODE, tp->mac_mode);
udelay(40);
+ if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
+ /* Allow time for the hardware to auto-negotiate (195ms) */
+ unsigned int tick = 0;
+
+ while (++tick < 195000) {
+ if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE)
+ break;
+ udelay(1);
+ }
+ if (tick >= 195000)
+ printk(KERN_INFO PFX "%s: HW autoneg failed !\n",
+ tp->dev->name);
+ }
+
/* Reset when initting first time or we have a link. */
if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
(tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
@@ -2031,53 +2107,18 @@
udelay(40);
current_link_up = 0;
- if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
- if (tp->link_config.autoneg == AUTONEG_ENABLE &&
- !(tp->tg3_flags & TG3_FLAG_GOT_SERDES_FLOWCTL)) {
- struct tg3_fiber_aneginfo aninfo;
- int status = ANEG_FAILED;
- unsigned int tick;
- u32 tmp;
-
- memset(&aninfo, 0, sizeof(aninfo));
- aninfo.flags |= (MR_AN_ENABLE);
-
- tw32(MAC_TX_AUTO_NEG, 0);
-
- tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
- tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
- udelay(40);
-
- tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
- udelay(40);
-
- aninfo.state = ANEG_STATE_UNKNOWN;
- aninfo.cur_time = 0;
- tick = 0;
- while (++tick < 195000) {
- status = tg3_fiber_aneg_smachine(tp, &aninfo);
- if (status == ANEG_DONE ||
- status == ANEG_FAILED)
- break;
-
- udelay(1);
- }
-
- tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- if (status == ANEG_DONE &&
- (aninfo.flags &
- (MR_AN_COMPLETE | MR_LINK_OK |
- MR_LP_ADV_FULL_DUPLEX))) {
+ if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
+ if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+ u32 flags;
+
+ if (fiber_autoneg(tp, &flags)) {
u32 local_adv, remote_adv;
local_adv = ADVERTISE_PAUSE_CAP;
remote_adv = 0;
- if (aninfo.flags & MR_LP_ADV_SYM_PAUSE)
- remote_adv |= LPA_PAUSE_CAP;
- if (aninfo.flags & MR_LP_ADV_ASYM_PAUSE)
+ if (flags & MR_LP_ADV_SYM_PAUSE)
+ remote_adv |= LPA_PAUSE_CAP;
+ if (flags & MR_LP_ADV_ASYM_PAUSE)
remote_adv |= LPA_PAUSE_ASYM;
tg3_setup_flow_control(tp, local_adv, remote_adv);
@@ -2104,8 +2145,10 @@
} else {
/* Forcing 1000FD link up. */
current_link_up = 1;
+ tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
}
- }
+ } else
+ tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
tw32_f(MAC_MODE, tp->mac_mode);
@@ -5203,6 +5246,26 @@
*/
tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+ tp->phy_id == PHY_ID_SERDES) {
+ /* Enable hardware link auto-negotiation */
+ u32 digctrl, txctrl;
+
+ digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N |
+ SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS |
+ (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE |
+ SG_DIG_GBIC_ENABLE;
+
+ txctrl = tr32(MAC_SERDES_CFG);
+ tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT);
+ tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET);
+ tr32(SG_DIG_CTRL);
+ udelay(5);
+ tw32_f(SG_DIG_CTRL, digctrl);
+
+ tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
+ }
+
err = tg3_setup_phy(tp, 1);
if (err)
return err;
@@ -6536,6 +6599,9 @@
case SIOCGMIIREG: {
u32 mii_regval;
+ if (tp->phy_id == PHY_ID_SERDES)
+ break; /* We have no PHY */
+
spin_lock_irq(&tp->lock);
err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval);
spin_unlock_irq(&tp->lock);
@@ -6546,6 +6612,9 @@
}
case SIOCSMIIREG:
+ if (tp->phy_id == PHY_ID_SERDES)
+ break; /* We have no PHY */
+
if (!capable(CAP_NET_ADMIN))
return -EPERM;
diff -Nru a/drivers/net/tg3.h b/drivers/net/tg3.h
--- a/drivers/net/tg3.h Mon Jul 19 11:05:33 2004
+++ b/drivers/net/tg3.h Mon Jul 19 11:05:33 2004
@@ -1,8 +1,9 @@
/* $Id: tg3.h,v 1.37.2.32 2002/03/11 12:18:18 davem Exp $
* tg3.h: Definitions for Broadcom Tigon3 ethernet driver.
*
- * Copyright (C) 2001, 2002 David S. Miller (davem at redhat.com)
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem at redhat.com)
* Copyright (C) 2001 Jeff Garzik (jgarzik at pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
*/
#ifndef _T3_H
@@ -116,6 +117,7 @@
#define CHIPREV_ID_5704_A0 0x2000
#define CHIPREV_ID_5704_A1 0x2001
#define CHIPREV_ID_5704_A2 0x2002
+#define CHIPREV_ID_5704_A3 0x2003
#define CHIPREV_ID_5705_A0 0x3000
#define CHIPREV_ID_5705_A1 0x3001
#define CHIPREV_ID_5705_A2 0x3002
@@ -518,8 +520,50 @@
#define MAC_EXTADDR_11_HIGH 0x00000588
#define MAC_EXTADDR_11_LOW 0x0000058c
#define MAC_SERDES_CFG 0x00000590
+#define MAC_SERDES_CFG_EDGE_SELECT 0x00001000
#define MAC_SERDES_STAT 0x00000594
-/* 0x598 --> 0x600 unused */
+/* 0x598 --> 0x5b0 unused */
+#define SG_DIG_CTRL 0x000005b0
+#define SG_DIG_USING_HW_AUTONEG 0x80000000
+#define SG_DIG_SOFT_RESET 0x40000000
+#define SG_DIG_DISABLE_LINKRDY 0x20000000
+#define SG_DIG_CRC16_CLEAR_N 0x01000000
+#define SG_DIG_EN10B 0x00800000
+#define SG_DIG_CLEAR_STATUS 0x00400000
+#define SG_DIG_LOCAL_DUPLEX_STATUS 0x00200000
+#define SG_DIG_LOCAL_LINK_STATUS 0x00100000
+#define SG_DIG_SPEED_STATUS_MASK 0x000c0000
+#define SG_DIG_SPEED_STATUS_SHIFT 18
+#define SG_DIG_JUMBO_PACKET_DISABLE 0x00020000
+#define SG_DIG_RESTART_AUTONEG 0x00010000
+#define SG_DIG_FIBER_MODE 0x00008000
+#define SG_DIG_REMOTE_FAULT_MASK 0x00006000
+#define SG_DIG_PAUSE_MASK 0x00001800
+#define SG_DIG_GBIC_ENABLE 0x00000400
+#define SG_DIG_CHECK_END_ENABLE 0x00000200
+#define SG_DIG_SGMII_AUTONEG_TIMER 0x00000100
+#define SG_DIG_CLOCK_PHASE_SELECT 0x00000080
+#define SG_DIG_GMII_INPUT_SELECT 0x00000040
+#define SG_DIG_MRADV_CRC16_SELECT 0x00000020
+#define SG_DIG_COMMA_DETECT_ENABLE 0x00000010
+#define SG_DIG_AUTONEG_TIMER_REDUCE 0x00000008
+#define SG_DIG_AUTONEG_LOW_ENABLE 0x00000004
+#define SG_DIG_REMOTE_LOOPBACK 0x00000002
+#define SG_DIG_LOOPBACK 0x00000001
+#define SG_DIG_STATUS 0x000005b4
+#define SG_DIG_CRC16_BUS_MASK 0xffff0000
+#define SG_DIG_PARTNER_FAULT_MASK 0x00600000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_ASYM_PAUSE 0x00100000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_PAUSE_CAPABLE 0x00080000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_HALF_DUPLEX 0x00040000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_FULL_DUPLEX 0x00020000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_NEXT_PAGE 0x00010000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_AUTONEG_STATE_MASK 0x00000ff0
+#define SG_DIG_COMMA_DETECTOR 0x00000008
+#define SG_DIG_MAC_ACK_STATUS 0x00000004
+#define SG_DIG_AUTONEG_COMPLETE 0x00000002
+#define SG_DIG_AUTONEG_ERROR 0x00000001
+/* 0x5b8 --> 0x600 unused */
#define MAC_TX_MAC_STATE_BASE 0x00000600 /* 16 bytes */
#define MAC_RX_MAC_STATE_BASE 0x00000610 /* 20 bytes */
/* 0x624 --> 0x800 unused */
@@ -2044,6 +2088,7 @@
#define TG3_FLG2_PHY_BER_BUG 0x00000100
#define TG3_FLG2_PCI_EXPRESS 0x00000200
#define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400
+#define TG3_FLG2_HW_AUTONEG 0x00000800
u32 split_mode_max_reqs;
#define SPLIT_MODE_5704_MAX_REQ 3
** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc64-dev
mailing list