From 2465665b73ac2f688af945b1ed510752afa816a4 Mon Sep 17 00:00:00 2001 From: David Saada Date: Tue, 15 Jan 2008 10:40:24 +0200 Subject: QE UEC: Extend number of supported UECs to 4 This patch extends the number of supported UECs to 4. Note that the problem of QE thread resources exhaustion is resolved by setting the correct number of QE threads according to Ethernet type (GBE or FE). Signed-off-by: David Saada Signed-off-by: Ben Warren diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index 6cb25bf..9094643 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -40,8 +40,13 @@ static uec_info_t eth1_uec_info = { .tx_clock = CFG_UEC1_TX_CLK, .eth_type = CFG_UEC1_ETH_TYPE, }, +#if (CFG_UEC1_ETH_TYPE == FAST_ETH) + .num_threads_tx = UEC_NUM_OF_THREADS_1, + .num_threads_rx = UEC_NUM_OF_THREADS_1, +#else .num_threads_tx = UEC_NUM_OF_THREADS_4, .num_threads_rx = UEC_NUM_OF_THREADS_4, +#endif .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .tx_bd_ring_len = 16, @@ -58,8 +63,13 @@ static uec_info_t eth2_uec_info = { .tx_clock = CFG_UEC2_TX_CLK, .eth_type = CFG_UEC2_ETH_TYPE, }, +#if (CFG_UEC2_ETH_TYPE == FAST_ETH) + .num_threads_tx = UEC_NUM_OF_THREADS_1, + .num_threads_rx = UEC_NUM_OF_THREADS_1, +#else .num_threads_tx = UEC_NUM_OF_THREADS_4, .num_threads_rx = UEC_NUM_OF_THREADS_4, +#endif .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .tx_bd_ring_len = 16, @@ -68,7 +78,6 @@ static uec_info_t eth2_uec_info = { .enet_interface = CFG_UEC2_INTERFACE_MODE, }; #endif - #ifdef CONFIG_UEC_ETH3 static uec_info_t eth3_uec_info = { .uf_info = { @@ -77,8 +86,13 @@ static uec_info_t eth3_uec_info = { .tx_clock = CFG_UEC3_TX_CLK, .eth_type = CFG_UEC3_ETH_TYPE, }, +#if (CFG_UEC3_ETH_TYPE == FAST_ETH) + .num_threads_tx = UEC_NUM_OF_THREADS_1, + .num_threads_rx = UEC_NUM_OF_THREADS_1, +#else .num_threads_tx = UEC_NUM_OF_THREADS_4, .num_threads_rx = UEC_NUM_OF_THREADS_4, +#endif .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .tx_bd_ring_len = 16, @@ -87,6 +101,29 @@ static uec_info_t eth3_uec_info = { .enet_interface = CFG_UEC3_INTERFACE_MODE, }; #endif +#ifdef CONFIG_UEC_ETH4 +static uec_info_t eth4_uec_info = { + .uf_info = { + .ucc_num = CFG_UEC4_UCC_NUM, + .rx_clock = CFG_UEC4_RX_CLK, + .tx_clock = CFG_UEC4_TX_CLK, + .eth_type = CFG_UEC4_ETH_TYPE, + }, +#if (CFG_UEC4_ETH_TYPE == FAST_ETH) + .num_threads_tx = UEC_NUM_OF_THREADS_1, + .num_threads_rx = UEC_NUM_OF_THREADS_1, +#else + .num_threads_tx = UEC_NUM_OF_THREADS_4, + .num_threads_rx = UEC_NUM_OF_THREADS_4, +#endif + .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, + .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, + .tx_bd_ring_len = 16, + .rx_bd_ring_len = 16, + .phy_address = CFG_UEC4_PHY_ADDR, + .enet_interface = CFG_UEC4_INTERFACE_MODE, +}; +#endif static int uec_mac_enable(uec_private_t *uec, comm_dir_e mode) { @@ -1262,6 +1299,10 @@ int uec_initialize(int index) #ifdef CONFIG_UEC_ETH3 uec_info = ð3_uec_info; #endif + } else if (index == 3) { +#ifdef CONFIG_UEC_ETH4 + uec_info = ð4_uec_info; +#endif } else { printf("%s: index is illegal.\n", __FUNCTION__); return -EINVAL; diff --git a/net/eth.c b/net/eth.c index 5d9e9c1..63a4cb6 100644 --- a/net/eth.c +++ b/net/eth.c @@ -217,6 +217,9 @@ int eth_initialize(bd_t *bis) #if defined(CONFIG_UEC_ETH3) uec_initialize(2); #endif +#if defined(CONFIG_UEC_ETH4) + uec_initialize(3); +#endif #if defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FCC) fec_initialize(bis); -- cgit v0.10.2 From 55fe7c57a8b99a130925052dcdbb77f053dc50e3 Mon Sep 17 00:00:00 2001 From: "michael.firth@bt.com" Date: Wed, 16 Jan 2008 11:40:51 +0000 Subject: TSEC driver: Change MDIO support to allow access to any PHYs on the MDIO bus The current TSEC driver limits MDIO access to the devices that have been configured as attached to a TSEC MAC. This patch allows access to any PHY device on the MDIO bus through the 'mii' commands. Signed-off-by: Michael Firth Acked-by: Andy Fleming Signed-off-by: Ben Warren diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 25392f6..504f3e5 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -241,10 +241,9 @@ int tsec_init(struct eth_device *dev, bd_t * bd) * It will wait for the write to be done (or for a timeout to * expire) before exiting */ -void write_phy_reg(struct tsec_private *priv, uint regnum, uint value) +void write_any_phy_reg(struct tsec_private *priv, uint phyid, uint regnum, uint value) { volatile tsec_t *regbase = priv->phyregs; - uint phyid = priv->phyaddr; int timeout = 1000000; regbase->miimadd = (phyid << 8) | regnum; @@ -255,17 +254,19 @@ void write_phy_reg(struct tsec_private *priv, uint regnum, uint value) while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ; } +/* #define to provide old write_phy_reg functionality without duplicating code */ +#define write_phy_reg(priv, regnum, value) write_any_phy_reg(priv,priv->phyaddr,regnum,value) + /* Reads register regnum on the device's PHY through the * registers specified in priv. It lowers and raises the read * command, and waits for the data to become valid (miimind * notvalid bit cleared), and the bus to cease activity (miimind * busy bit cleared), and then returns the value */ -uint read_phy_reg(struct tsec_private *priv, uint regnum) +uint read_any_phy_reg(struct tsec_private *priv, uint phyid, uint regnum) { uint value; volatile tsec_t *regbase = priv->phyregs; - uint phyid = priv->phyaddr; /* Put the address of the phy, and the register * number into MIIMADD */ @@ -288,6 +289,9 @@ uint read_phy_reg(struct tsec_private *priv, uint regnum) return value; } +/* #define to provide old read_phy_reg functionality without duplicating code */ +#define read_phy_reg(priv,regnum) read_any_phy_reg(priv,priv->phyaddr,regnum) + /* Discover which PHY is attached to the device, and configure it * properly. If the PHY is not recognized, then return 0 * (failure). Otherwise, return 1 @@ -1497,18 +1501,6 @@ static void relocate_cmds(void) #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ && !defined(BITBANGMII) -struct tsec_private *get_priv_for_phy(unsigned char phyaddr) -{ - int i; - - for (i = 0; i < MAXCONTROLLERS; i++) { - if (privlist[i]->phyaddr == phyaddr) - return privlist[i]; - } - - return NULL; -} - /* * Read a MII PHY register. * @@ -1519,14 +1511,14 @@ static int tsec_miiphy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value) { unsigned short ret; - struct tsec_private *priv = get_priv_for_phy(addr); + struct tsec_private *priv = privlist[0]; if (NULL == priv) { printf("Can't read PHY at address %d\n", addr); return -1; } - ret = (unsigned short)read_phy_reg(priv, reg); + ret = (unsigned short)read_any_phy_reg(priv, addr, reg); *value = ret; return 0; @@ -1541,14 +1533,14 @@ static int tsec_miiphy_read(char *devname, unsigned char addr, static int tsec_miiphy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value) { - struct tsec_private *priv = get_priv_for_phy(addr); + struct tsec_private *priv = privlist[0]; if (NULL == priv) { printf("Can't write PHY at address %d\n", addr); return -1; } - write_phy_reg(priv, reg, value); + write_any_phy_reg(priv, addr, reg, value); return 0; } -- cgit v0.10.2 From ee62ed3286f83b98b7785e0318dc6379e78f7ff6 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Tue, 15 Jan 2008 14:11:00 -0600 Subject: net: reduce boot latency on QE UEC based boards actually polling for PHY autonegotiation to finish enables us to remove the 5 second boot prompt latency present on QE based boards. call to qe_set_mii_clk_src in init_phy, and mv call to init_phy from uec_initialize to uec_init by Joakim Tjernlund; autonegotiation wait code shamelessly stolen from tsec driver. also rm unused CONFIG_RMII_MODE code. Signed-off-by: Kim Phillips Signed-off-by: Joakim Tjernlund Signed-off-by: Ben Warren diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index 9094643..55f37cb 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -512,6 +512,8 @@ static int init_phy(struct eth_device *dev) uec->mii_info = mii_info; + qe_set_mii_clk_src(uec->uec_info->uf_info.ucc_num); + if (init_mii_management_configuration(umii_regs)) { printf("%s: The MII Bus is stuck!", dev->name); err = -1; @@ -618,21 +620,12 @@ static void adjust_link(struct eth_device *dev) static void phy_change(struct eth_device *dev) { uec_private_t *uec = (uec_private_t *)dev->priv; - uec_t *uec_regs; - int result = 0; - - uec_regs = uec->uec_regs; - - /* Delay 5s to give the PHY a chance to change the register state */ - udelay(5000000); /* Update the link, speed, duplex */ - result = uec->mii_info->phyinfo->read_status(uec->mii_info); + uec->mii_info->phyinfo->read_status(uec->mii_info); /* Adjust the interface according to speed */ - if ((0 == result) || (uec->mii_info->link == 0)) { - adjust_link(dev); - } + adjust_link(dev); } static int uec_set_mac_address(uec_private_t *uec, u8 *mac_addr) @@ -1157,27 +1150,59 @@ static int uec_startup(uec_private_t *uec) static int uec_init(struct eth_device* dev, bd_t *bd) { uec_private_t *uec; - int err; + int err, i; + struct phy_info *curphy; uec = (uec_private_t *)dev->priv; if (uec->the_first_run == 0) { - /* Set up the MAC address */ - if (dev->enetaddr[0] & 0x01) { - printf("%s: MacAddress is multcast address\n", - __FUNCTION__); - return -1; + err = init_phy(dev); + if (err) { + printf("%s: Cannot initialize PHY, aborting.\n", + dev->name); + return err; } - uec_set_mac_address(uec, dev->enetaddr); + + curphy = uec->mii_info->phyinfo; + + if (curphy->config_aneg) { + err = curphy->config_aneg(uec->mii_info); + if (err) { + printf("%s: Can't negotiate PHY\n", dev->name); + return err; + } + } + + /* Give PHYs up to 5 sec to report a link */ + i = 50; + do { + err = curphy->read_status(uec->mii_info); + udelay(100000); + } while (((i-- > 0) && !uec->mii_info->link) || err); + + if (err || i <= 0) + printf("warning: %s: timeout on PHY link\n", dev->name); + uec->the_first_run = 1; } + /* Set up the MAC address */ + if (dev->enetaddr[0] & 0x01) { + printf("%s: MacAddress is multcast address\n", + __FUNCTION__); + return -1; + } + uec_set_mac_address(uec, dev->enetaddr); + + err = uec_open(uec, COMM_DIR_RX_AND_TX); if (err) { printf("%s: cannot enable UEC device\n", dev->name); return -1; } + phy_change(dev); + return (uec->mii_info->link ? 0 : -1); } @@ -1330,14 +1355,6 @@ int uec_initialize(int index) return err; } - err = init_phy(dev); - if (err) { - printf("%s: Cannot initialize PHY, aborting.\n", dev->name); - return err; - } - - phy_change(dev); - return 1; } #endif /* CONFIG_QE */ diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c index ca6faa6..f890d4f 100644 --- a/drivers/qe/uec_phy.c +++ b/drivers/qe/uec_phy.c @@ -77,11 +77,10 @@ void uec_write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int valu /* Setting up the MII Mangement Control Register with the value */ out_be32 (&ug_regs->miimcon, (u32) value); + sync(); /* Wait till MII management write is complete */ while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY); - - udelay (100000); } /* Reads from register regnum in the PHY for device dev, */ @@ -101,16 +100,17 @@ int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum) tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg; out_be32 (&ug_regs->miimadd, tmp_reg); - /* Perform an MII management read cycle */ + /* clear MII management command cycle */ out_be32 (&ug_regs->miimcom, 0); + sync(); + + /* Perform an MII management read cycle */ out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE); /* Wait till MII management write is complete */ while ((in_be32 (&ug_regs->miimind)) & (MIIMIND_NOT_VALID | MIIMIND_BUSY)); - udelay (100000); - /* Read MII management status */ value = (u16) in_be32 (&ug_regs->miimstat); if (value == 0xffff) @@ -270,20 +270,38 @@ static int genmii_update_link (struct uec_mii_info *mii_info) { u16 status; - /* Do a fake read */ + /* Status is read once to clear old link state */ phy_read (mii_info, PHY_BMSR); - /* Read link and autonegotiation status */ - status = phy_read (mii_info, PHY_BMSR); - if ((status & PHY_BMSR_LS) == 0) - mii_info->link = 0; - else + /* + * Wait if the link is up, and autonegotiation is in progress + * (ie - we're capable and it's not done) + */ + status = phy_read(mii_info, PHY_BMSR); + if ((status & PHY_BMSR_LS) && (status & PHY_BMSR_AUTN_ABLE) + && !(status & PHY_BMSR_AUTN_COMP)) { + int i = 0; + + while (!(status & PHY_BMSR_AUTN_COMP)) { + /* + * Timeout reached ? + */ + if (i > UGETH_AN_TIMEOUT) { + mii_info->link = 0; + return 0; + } + + udelay(1000); /* 1 ms */ + status = phy_read(mii_info, PHY_BMSR); + } mii_info->link = 1; - - /* If we are autonegotiating, and not done, - * return an error */ - if (mii_info->autoneg && !(status & PHY_BMSR_AUTN_COMP)) - return -EAGAIN; + udelay(500000); /* another 500 ms (results in faster booting) */ + } else { + if (status & PHY_BMSR_LS) + mii_info->link = 1; + else + mii_info->link = 0; + } return 0; } @@ -389,16 +407,12 @@ static int dm9161_init (struct uec_mii_info *mii_info) /* PHY and MAC connect */ phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) & ~PHY_BMCR_ISO); -#ifdef CONFIG_RMII_MODE - phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_RMII_INIT); -#else + phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT); -#endif + config_genmii_advert (mii_info); /* Start/restart aneg */ genmii_config_aneg (mii_info); - /* Delay to wait the aneg compeleted */ - udelay (3000000); return 0; } -- cgit v0.10.2 From 84a3047b72b70e862b0b7a8e2058077457f89a32 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Wed, 16 Jan 2008 09:40:41 +0100 Subject: Remove annoying debug printout for PHY less boards. PHY less board prints out lots of "read wrong ...": read wrong value : mii_id 3,mii_reg 2, base e0102320 read wrong value : mii_id 3,mii_reg 3, base e0102320 UEC: PHY is Generic MII (ffffffff) read wrong value : mii_id 3,mii_reg 4, base e0102320 read wrong value : mii_id 3,mii_reg 0, base e0102320 read wrong value : mii_id 3,mii_reg 1, base e0102320 read wrong value : mii_id 3,mii_reg 1, base e0102320 read wrong value : mii_id 3,mii_reg 5, base e0102320 read wrong value : mii_id 3,mii_reg 1, base e0102320 read wrong value : mii_id 3,mii_reg 1, base e0102320 read wrong value : mii_id 3,mii_reg 5, base e0102320 FSL UEC0: Full Duplex FSL UEC0: Speed 100BT FSL UEC0: Link is up Using FSL UEC0 device Make this printout depend on UEC_VERBOSE_DEBUG and remove its definition in uec_phy.c Signed-off-by: Joakim Tjernlund Signed-off-by: Ben Warren diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c index f890d4f..c549b6b 100644 --- a/drivers/qe/uec_phy.c +++ b/drivers/qe/uec_phy.c @@ -28,7 +28,6 @@ #if defined(CONFIG_QE) -#define UEC_VERBOSE_DEBUG #define ugphy_printk(format, arg...) \ printf(format "\n", ## arg) @@ -114,7 +113,7 @@ int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum) /* Read MII management status */ value = (u16) in_be32 (&ug_regs->miimstat); if (value == 0xffff) - ugphy_warn + ugphy_vdbg ("read wrong value : mii_id %d,mii_reg %d, base %08x", mii_id, mii_reg, (u32) & (ug_regs->miimcfg)); -- cgit v0.10.2 From 18ee320ff63edbf7b27bbeb05f0e12a52302c68a Mon Sep 17 00:00:00 2001 From: Dave Liu Date: Fri, 11 Jan 2008 18:45:28 +0800 Subject: TSEC: Add the support for RealTek RTL8211B PHY Add the support of RealTek RTL8211B PHY, the RTL8211B PHY only supports RGMII and MII mode. Signed-off-by: Dave Liu Signed-off-by: Ben Warren diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 504f3e5..e91d9ea 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -575,6 +575,63 @@ uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv) return 0; } +/* Parse the RTL8211B's status register for speed and duplex + * information + */ +uint mii_parse_RTL8211B_sr(uint mii_reg, struct tsec_private * priv) +{ + uint speed; + + mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS); + if ((mii_reg & MIIM_RTL8211B_PHYSTAT_LINK) && + !(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { + int i = 0; + + puts("Waiting for PHY realtime link"); + while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { + /* Timeout reached ? */ + if (i > PHY_AUTONEGOTIATE_TIMEOUT) { + puts(" TIMEOUT !\n"); + priv->link = 0; + break; + } + + if ((i++ % 1000) == 0) { + putc('.'); + } + udelay(1000); /* 1 ms */ + mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS); + } + puts(" done\n"); + udelay(500000); /* another 500 ms (results in faster booting) */ + } else { + if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK) + priv->link = 1; + else + priv->link = 0; + } + + if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX) + priv->duplexity = 1; + else + priv->duplexity = 0; + + speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED); + + switch (speed) { + case MIIM_RTL8211B_PHYSTAT_GBIT: + priv->speed = 1000; + break; + case MIIM_RTL8211B_PHYSTAT_100: + priv->speed = 100; + break; + default: + priv->speed = 10; + } + + return 0; +} + /* Parse the cis8201's status register for speed and duplex * information */ @@ -1365,6 +1422,33 @@ struct phy_info phy_info_dp83865 = { }, }; +struct phy_info phy_info_rtl8211b = { + 0x001cc91, + "RealTek RTL8211B", + 4, + (struct phy_cmd[]){ /* config */ + /* Reset and configure the PHY */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, + {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_RTL8211B_PHY_STATUS, miim_read, &mii_parse_RTL8211B_sr}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + struct phy_info *phy_info[] = { &phy_info_cis8204, &phy_info_cis8201, @@ -1378,6 +1462,7 @@ struct phy_info *phy_info[] = { &phy_info_lxt971, &phy_info_VSC8244, &phy_info_dp83865, + &phy_info_rtl8211b, &phy_info_generic, NULL }; diff --git a/drivers/net/tsec.h b/drivers/net/tsec.h index 2f0092a..d4dc15a 100644 --- a/drivers/net/tsec.h +++ b/drivers/net/tsec.h @@ -184,6 +184,14 @@ #define MIIM_88E1145_PHY_PAGE 29 #define MIIM_88E1145_PHY_CAL_OV 30 +/* RTL8211B PHY Status Register */ +#define MIIM_RTL8211B_PHY_STATUS 0x11 +#define MIIM_RTL8211B_PHYSTAT_SPEED 0xc000 +#define MIIM_RTL8211B_PHYSTAT_GBIT 0x8000 +#define MIIM_RTL8211B_PHYSTAT_100 0x4000 +#define MIIM_RTL8211B_PHYSTAT_DUPLEX 0x2000 +#define MIIM_RTL8211B_PHYSTAT_SPDDONE 0x0800 +#define MIIM_RTL8211B_PHYSTAT_LINK 0x0400 /* DM9161 Control register values */ #define MIIM_DM9161_CR_STOP 0x0400 -- cgit v0.10.2 From d1276c76c1e2b5035296689280ba1acb2c425104 Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Wed, 16 Jan 2008 16:11:14 +0900 Subject: drivers/net/rtl8139.c: Fix tx timeout "to = (currticks() + RTL_TIMEOUT)" has possibilities to wrap around. If it does, the condition "(currticks() < to)" becomes invalid and immediately leads to tx timeout error. This patch introduces the fine-graded udely(10) loops to ease the impact of wrapping around. Signed-off-by: Shinya Kuribayashi Cc: Masami Komiya Cc: Lucas Jin Signed-off-by: Ben Warren diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 4c24805..5d7ae74 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -80,10 +80,7 @@ #if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ defined(CONFIG_RTL8139) -#define TICKS_PER_SEC CFG_HZ -#define TICKS_PER_MS (TICKS_PER_SEC/1000) - -#define RTL_TIMEOUT (1*TICKS_PER_SEC) +#define RTL_TIMEOUT 100000 #define ETH_FRAME_LEN 1514 #define ETH_ALEN 6 @@ -414,9 +411,10 @@ static void rtl_reset(struct eth_device *dev) static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length) { - unsigned int status, to; + unsigned int status; unsigned long txstatus; unsigned int len = length; + int i = 0; ioaddr = dev->iobase; @@ -436,8 +434,6 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, ioaddr + TxStatus0 + cur_tx*4); - to = currticks() + RTL_TIMEOUT; - do { status = inw(ioaddr + IntrStatus); /* Only acknlowledge interrupt sources we can properly handle @@ -445,7 +441,8 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt * rtl_poll() function. */ outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus); if ((status & (TxOK | TxErr | PCIErr)) != 0) break; - } while (currticks() < to); + udelay(10); + } while (i++ < RTL_TIMEOUT); txstatus = inl(ioaddr + TxStatus0 + cur_tx*4); @@ -458,8 +455,8 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt return length; } else { #ifdef DEBUG_TX - printf("tx timeout/error (%d ticks), status %hX txstatus %X\n", - currticks()-to, status, txstatus); + printf("tx timeout/error (%d usecs), status %hX txstatus %X\n", + 10*i, status, txstatus); #endif rtl_reset(dev); -- cgit v0.10.2 From 96a236746fe6a7b84802afb4ed31536696d34812 Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Wed, 16 Jan 2008 16:12:26 +0900 Subject: drivers/net/rtl8139.c: Fix cache coherency issues Current driver is meant for cache coherent systems. This patch adds flush_cache() routines to support cache non-coherent systems. Signed-off-by: Shinya Kuribayashi Cc: Masami Komiya Cc: Lucas Jin Signed-off-by: Ben Warren diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 5d7ae74..014f3b4 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -389,6 +389,7 @@ static void rtl_reset(struct eth_device *dev) #ifdef DEBUG_RX printf("rx ring address is %X\n",(unsigned long)rx_ring); #endif + flush_cache((unsigned long)rx_ring, RX_BUF_LEN); outl(phys_to_bus((int)rx_ring), ioaddr + RxBuf); /* If we add multicast support, the MAR0 register would have to be @@ -430,6 +431,7 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt tx_buffer[len++] = '\0'; } + flush_cache((unsigned long)tx_buffer, length); outl(phys_to_bus((int)tx_buffer), ioaddr + TxAddr0 + cur_tx*4); outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, ioaddr + TxStatus0 + cur_tx*4); @@ -486,7 +488,8 @@ static int rtl_poll(struct eth_device *dev) #endif ring_offs = cur_rx % RX_BUF_LEN; - rx_status = *(unsigned int*)KSEG1ADDR((rx_ring + ring_offs)); + /* ring_offs is guaranteed being 4-byte aligned */ + rx_status = *(unsigned int *)(rx_ring + ring_offs); rx_size = rx_status >> 16; rx_status &= 0xffff; @@ -516,6 +519,7 @@ static int rtl_poll(struct eth_device *dev) printf("rx packet %d bytes", rx_size-4); #endif } + flush_cache((unsigned long)rx_ring, RX_BUF_LEN); cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; outw(cur_rx - 16, ioaddr + RxBufPtr); -- cgit v0.10.2 From c2f896b8fc4722e36915903e1942e138e68ce804 Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Wed, 16 Jan 2008 16:13:31 +0900 Subject: drivers/net/rtl8139.c: rx_status should be le32_to_cpu(rx_status). rx_status on the memory is basically in LE, but needs to be handled in CPU endian. le32_to_cpu() takes up this mission. Even if on the sane hardware, it'll work fine. Signed-off-by: Shinya Kuribayashi Cc: Masami Komiya Cc: Lucas Jin Signed-off-by: Ben Warren diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 014f3b4..097f684 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -489,7 +489,7 @@ static int rtl_poll(struct eth_device *dev) ring_offs = cur_rx % RX_BUF_LEN; /* ring_offs is guaranteed being 4-byte aligned */ - rx_status = *(unsigned int *)(rx_ring + ring_offs); + rx_status = le32_to_cpu(*(unsigned int *)(rx_ring + ring_offs)); rx_size = rx_status >> 16; rx_status &= 0xffff; -- cgit v0.10.2 From b8f4162a4f7a9bee5e9d0305c17f2d34de466a9b Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 10 Dec 2007 22:32:14 +0100 Subject: bf537-stamp: remove already defined is_zero_ether_addr and is_multicast_ether_addr and move is_valid_ether_addr board file Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Ben Warren diff --git a/board/bf537-stamp/bf537-stamp.c b/board/bf537-stamp/bf537-stamp.c index b3d8bda..6954b30 100644 --- a/board/bf537-stamp/bf537-stamp.c +++ b/board/bf537-stamp/bf537-stamp.c @@ -30,8 +30,25 @@ #include #include #include +#include #include "ether_bf537.h" +/** + * is_valid_ether_addr - Determine if the given Ethernet address is valid + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not + * a multicast address, and is not FF:FF:FF:FF:FF:FF. + * + * Return true if the address is valid. + */ +static inline int is_valid_ether_addr(const u8 * addr) +{ + /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to + * explicitly check for it here. */ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); +} + DECLARE_GLOBAL_DATA_PTR; #define POST_WORD_ADDR 0xFF903FFC diff --git a/board/bf537-stamp/ether_bf537.h b/board/bf537-stamp/ether_bf537.h index 64240ba..22fc392 100644 --- a/board/bf537-stamp/ether_bf537.h +++ b/board/bf537-stamp/ether_bf537.h @@ -69,42 +69,3 @@ void SoftResetPHY(void); void DumpPHYRegs(void); int SetupSystemRegs(int *opmode); - -/** - * is_zero_ether_addr - Determine if give Ethernet address is all zeros. - * @addr: Pointer to a six-byte array containing the Ethernet address - * - * Return true if the address is all zeroes. - */ -static inline int is_zero_ether_addr(const u8 * addr) -{ - return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); -} - -/** - * is_multicast_ether_addr - Determine if the Ethernet address is a multicast. - * @addr: Pointer to a six-byte array containing the Ethernet address - * - * Return true if the address is a multicast address. - * By definition the broadcast address is also a multicast address. - */ -static inline int is_multicast_ether_addr(const u8 * addr) -{ - return (0x01 & addr[0]); -} - -/** - * is_valid_ether_addr - Determine if the given Ethernet address is valid - * @addr: Pointer to a six-byte array containing the Ethernet address - * - * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not - * a multicast address, and is not FF:FF:FF:FF:FF:FF. - * - * Return true if the address is valid. - */ -static inline int is_valid_ether_addr(const u8 * addr) -{ - /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to - * explicitly check for it here. */ - return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); -} -- cgit v0.10.2 From 7f52fa3c2df59e49dc2badd7c084cf2d007c438f Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Fri, 11 Jan 2008 00:01:37 +0100 Subject: Fix nfs command help to reflect that the serverip is optional Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Ben Warren diff --git a/common/cmd_net.c b/common/cmd_net.c index 21682c0..56eb684 100644 --- a/common/cmd_net.c +++ b/common/cmd_net.c @@ -87,7 +87,7 @@ int do_nfs (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) U_BOOT_CMD( nfs, 3, 1, do_nfs, "nfs\t- boot image via network using NFS protocol\n", - "[loadAddress] [host ip addr:bootfilename]\n" + "[loadAddress] [[hostIPaddr:]bootfilename]\n" ); #endif -- cgit v0.10.2 From e16925773211291b562e77187061e9dd1d757217 Mon Sep 17 00:00:00 2001 From: Matthias Fuchs Date: Thu, 17 Jan 2008 07:45:05 +0100 Subject: net: add 'ethrotate' environment variable [PATCH] net: add 'ethrotate' environment variable This patch replaces the buildtime configuration option CONFIG_NET_DO_NOT_TRY_ANOTHER through the 'ethrotate' runtime configuration veriable. See README. Signed-off-by: Matthias Fuchs Signed-off-by: Ben Warren diff --git a/README b/README index f2a4914..d9c2ee2 100644 --- a/README +++ b/README @@ -2691,6 +2691,10 @@ Some configuration options can be set using Environment Variables: => setenv ethact SCC ETHERNET => ping 10.0.0.1 # traffic sent on SCC ETHERNET + ethrotate - When set to "no" U-Boot does not go through all + available network interfaces. + It just stays at the currently selected interface. + netretry - When set to "no" each network operation will either succeed or fail without retrying. When set to "once" the network operation will diff --git a/net/eth.c b/net/eth.c index 63a4cb6..316e817 100644 --- a/net/eth.c +++ b/net/eth.c @@ -525,6 +525,15 @@ int eth_receive(volatile void *packet, int length) void eth_try_another(int first_restart) { static struct eth_device *first_failed = NULL; + char *ethrotate; + + /* + * Do not rotate between network interfaces when + * 'ethrotate' variable is set to 'no'. + */ + if (((ethrotate = getenv ("ethrotate")) != NULL) && + (strcmp(ethrotate, "no") == 0)) + return; if (!eth_current) return; -- cgit v0.10.2