From bc46dfac2f21756642e549b05689e03db538639f Mon Sep 17 00:00:00 2001 From: Jayachandran Chandrasekharan Nair Date: Tue, 10 Jul 2012 11:48:54 +0530 Subject: net: tftp: fix type of block arg to store_block The block argument for store_block can be -1 when the tftp sequence number rolls over (i.e TftpBlock == 0), so the first argument to store_block has to be of type 'int' instead of 'unsigned'. In our environment (gcc 4.4.5 mips toolchain), this causes incorrect 'offset' to be generated for storing the block, and the tftp block with number 0 will be written elsewhere, resulting in a bad block in the downloaded file and a memory corruption. Signed-off-by: Jayachandran Chandrasekharan Nair --- net/tftp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tftp.c b/net/tftp.c index b2e08b4bfb3..59a8ebb3cf3 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -156,7 +156,7 @@ mcast_cleanup(void) #endif /* CONFIG_MCAST_TFTP */ static inline void -store_block(unsigned block, uchar *src, unsigned len) +store_block(int block, uchar *src, unsigned len) { ulong offset = block * TftpBlkSize + TftpBlockWrapOffset; ulong newsize = offset + len; -- cgit v1.2.3 From 6e5b9ac097689e96d53f638842823fb1d1bf4223 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 5 Jul 2012 10:33:18 +0000 Subject: phylib: phy_startup() should return an error code on failure phy_startup() calls the PHY driver's startup function, but it ignores the return code from that function, and so it never returns any failures. Signed-off-by: Timur Tabi --- drivers/net/phy/phy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 7d327f766a2..baef60f8274 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -723,10 +723,13 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr, return phydev; } +/* + * Start the PHY. Returns 0 on success, or a negative error code. + */ int phy_startup(struct phy_device *phydev) { if (phydev->drv->startup) - phydev->drv->startup(phydev); + return phydev->drv->startup(phydev); return 0; } -- cgit v1.2.3 From 11af8d65274df736deeb651d12e0763eec527ea5 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 9 Jul 2012 08:52:43 +0000 Subject: net: abort network initialization if the PHY driver fails Now that phy_startup() can return an actual error code, check for that error code and abort network initialization if the PHY fails. Signed-off-by: Timur Tabi Acked-by: Nobuhiro Iwamamatsu (sh_eth part) Acked-by: Stephan Linz (Xilinx part, xilinx_axi_emac and xilinx_ll_temac) Reviewed-by: Marek Vasut (FEC part) --- drivers/net/fec_mxc.c | 8 +++++++- drivers/net/fm/eth.c | 9 ++++++++- drivers/net/sh_eth.c | 6 +++++- drivers/net/tsec.c | 8 +++++++- drivers/net/xilinx_axi_emac.c | 6 +++++- drivers/net/xilinx_ll_temac.c | 8 +++++++- 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index eee41d7c8b7..57005521899 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -510,7 +510,13 @@ static int fec_open(struct eth_device *edev) fec_eth_phy_config(edev); if (fec->phydev) { /* Start up the PHY */ - phy_startup(fec->phydev); + int ret = phy_startup(fec->phydev); + + if (ret) { + printf("Could not initialize PHY %s\n", + fec->phydev->dev->name); + return ret; + } speed = fec->phydev->speed; } else { speed = _100BASET; diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index f34f4db6b60..2b616adb6e5 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -363,6 +363,9 @@ static int fm_eth_open(struct eth_device *dev, bd_t *bd) { struct fm_eth *fm_eth; struct fsl_enet_mac *mac; +#ifdef CONFIG_PHYLIB + int ret; +#endif fm_eth = (struct fm_eth *)dev->priv; mac = fm_eth->mac; @@ -384,7 +387,11 @@ static int fm_eth_open(struct eth_device *dev, bd_t *bd) fmc_tx_port_graceful_stop_disable(fm_eth); #ifdef CONFIG_PHYLIB - phy_startup(fm_eth->phydev); + ret = phy_startup(fm_eth->phydev); + if (ret) { + printf("%s: Could not initialize\n", fm_eth->phydev->dev->name); + return ret; + } #else fm_eth->phydev->speed = SPEED_1000; fm_eth->phydev->link = 1; diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index bb57e4d53a0..268d88428c0 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -415,7 +415,11 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) goto err_phy_cfg; } phy = port_info->phydev; - phy_startup(phy); + ret = phy_startup(phy); + if (ret) { + printf(SHETHER_NAME ": phy startup failure\n"); + return ret; + } val = 0; diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 3c1c8f0799c..f5e314b9ee0 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -480,6 +480,7 @@ static int tsec_init(struct eth_device *dev, bd_t * bd) int i; struct tsec_private *priv = (struct tsec_private *)dev->priv; tsec_t *regs = priv->regs; + int ret; /* Make sure the controller is stopped */ tsec_halt(dev); @@ -511,7 +512,12 @@ static int tsec_init(struct eth_device *dev, bd_t * bd) startup_tsec(dev); /* Start up the PHY */ - phy_startup(priv->phydev); + ret = phy_startup(priv->phydev); + if (ret) { + printf("Could not initialize PHY %s\n", + priv->phydev->dev->name); + return ret; + } adjust_link(priv, priv->phydev); diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index 7854a04cae1..d77714440ad 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -272,7 +272,11 @@ static int setup_phy(struct eth_device *dev) phydev->advertising = phydev->supported; priv->phydev = phydev; phy_config(phydev); - phy_startup(phydev); + if (phy_startup(phydev)) { + printf("axiemac: could not initialize PHY %s\n", + phydev->dev->name); + return 0; + } switch (phydev->speed) { case 1000: diff --git a/drivers/net/xilinx_ll_temac.c b/drivers/net/xilinx_ll_temac.c index 27dafc15c00..b67153bec89 100644 --- a/drivers/net/xilinx_ll_temac.c +++ b/drivers/net/xilinx_ll_temac.c @@ -232,6 +232,7 @@ static void ll_temac_halt(struct eth_device *dev) static int ll_temac_init(struct eth_device *dev, bd_t *bis) { struct ll_temac *ll_temac = dev->priv; + int ret; printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n", dev->name, dev->index, dev->iobase); @@ -240,7 +241,12 @@ static int ll_temac_init(struct eth_device *dev, bd_t *bis) return -1; /* Start up the PHY */ - phy_startup(ll_temac->phydev); + ret = phy_startup(ll_temac->phydev); + if (ret) { + printf("%s: Could not initialize PHY %s\n", + dev->name, ll_temac->phydev->dev->name); + return ret; + } if (!ll_temac_adjust_link(dev)) { ll_temac_halt(dev); -- cgit v1.2.3 From cc5f552283eceb08bc614dfb6cfbcdd155be35b0 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 28 Jun 2012 08:00:28 +0000 Subject: net: phy: micrel: make ksz9021 phy accessible Micrel accidentally used the same part number for the KS8721 and KSZ9021. So, both cannot be in the same build of u-boot. Add a config option to handle this. Signed-off-by: Troy Kisky Acked-by: Vladimir Zapolskiy --- drivers/net/phy/micrel.c | 15 +++++++++++++-- include/configs/mx6qsabrelite.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index e3043dfa207..30f32648974 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -35,6 +35,12 @@ static struct phy_driver KSZ804_driver = { .shutdown = &genphy_shutdown, }; +#ifndef CONFIG_PHY_MICREL_KSZ9021 +/* + * I can't believe Micrel used the exact same part number + * for the KSZ9021 + * Shame Micrel, Shame!!!!! + */ static struct phy_driver KS8721_driver = { .name = "Micrel KS8721BL", .uid = 0x221610, @@ -44,7 +50,9 @@ static struct phy_driver KS8721_driver = { .startup = &genphy_startup, .shutdown = &genphy_shutdown, }; +#endif +#ifdef CONFIG_PHY_MICREL_KSZ9021 /* ksz9021 PHY Registers */ #define MII_KSZ9021_EXTENDED_CTRL 0x0b #define MII_KSZ9021_EXTENDED_DATAW 0x0c @@ -127,12 +135,15 @@ static struct phy_driver ksz9021_driver = { .startup = &ksz9021_startup, .shutdown = &genphy_shutdown, }; +#endif int phy_micrel_init(void) { phy_register(&KSZ804_driver); - phy_register(&KS8721_driver); +#ifdef CONFIG_PHY_MICREL_KSZ9021 phy_register(&ksz9021_driver); - +#else + phy_register(&KS8721_driver); +#endif return 0; } diff --git a/include/configs/mx6qsabrelite.h b/include/configs/mx6qsabrelite.h index fd25fafeabd..c66229c8024 100644 --- a/include/configs/mx6qsabrelite.h +++ b/include/configs/mx6qsabrelite.h @@ -96,6 +96,7 @@ #define CONFIG_FEC_MXC_PHYADDR 6 #define CONFIG_PHYLIB #define CONFIG_PHY_MICREL +#define CONFIG_PHY_MICREL_KSZ9021 /* USB Configs */ #define CONFIG_CMD_USB -- cgit v1.2.3 From c59ab0921fcc99db87efa02022f4ca39dad975b2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 24 Jun 2012 14:17:56 +0000 Subject: CACHE: net: asix: Fix asix driver to work with data cache on The asix driver did not align buffers, therefore it didn't work with data cache enabled. Fix this. Signed-off-by: Marek Vasut Cc: Joe Hershberger Acked-by: Joe Hershberger --- drivers/usb/eth/asix.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c index a3bf51a64d7..8fb7fc8c90e 100644 --- a/drivers/usb/eth/asix.c +++ b/drivers/usb/eth/asix.c @@ -168,27 +168,28 @@ static inline int asix_set_hw_mii(struct ueth_data *dev) static int asix_mdio_read(struct ueth_data *dev, int phy_id, int loc) { - __le16 res; + ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1); asix_set_sw_mii(dev); - asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, &res); + asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, res); asix_set_hw_mii(dev); debug("asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", - phy_id, loc, le16_to_cpu(res)); + phy_id, loc, le16_to_cpu(*res)); - return le16_to_cpu(res); + return le16_to_cpu(*res); } static void asix_mdio_write(struct ueth_data *dev, int phy_id, int loc, int val) { - __le16 res = cpu_to_le16(val); + ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1); + *res = cpu_to_le16(val); debug("asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", phy_id, loc, val); asix_set_sw_mii(dev); - asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); + asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, res); asix_set_hw_mii(dev); } @@ -210,7 +211,8 @@ static int asix_sw_reset(struct ueth_data *dev, u8 flags) static inline int asix_get_phy_addr(struct ueth_data *dev) { - u8 buf[2]; + ALLOC_CACHE_ALIGN_BUFFER(u8, buf, 2); + int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf); debug("asix_get_phy_addr()\n"); @@ -242,13 +244,14 @@ static int asix_write_medium_mode(struct ueth_data *dev, u16 mode) static u16 asix_read_rx_ctl(struct ueth_data *dev) { - __le16 v; - int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v); + ALLOC_CACHE_ALIGN_BUFFER(__le16, v, 1); + + int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, v); if (ret < 0) debug("Error reading RX_CTL register: %02x\n", ret); else - ret = le16_to_cpu(v); + ret = le16_to_cpu(*v); return ret; } @@ -313,7 +316,7 @@ static int mii_nway_restart(struct ueth_data *dev) static int asix_init(struct eth_device *eth, bd_t *bd) { int embd_phy; - unsigned char buf[ETH_ALEN]; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN); u16 rx_ctl; struct ueth_data *dev = (struct ueth_data *)eth->priv; int timeout = 0; @@ -425,7 +428,8 @@ static int asix_send(struct eth_device *eth, void *packet, int length) int err; u32 packet_len; int actual_len; - unsigned char msg[PKTSIZE + sizeof(packet_len)]; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg, + PKTSIZE + sizeof(packet_len)); debug("** %s(), len %d\n", __func__, length); @@ -452,7 +456,7 @@ static int asix_send(struct eth_device *eth, void *packet, int length) static int asix_recv(struct eth_device *eth) { struct ueth_data *dev = (struct ueth_data *)eth->priv; - static unsigned char recv_buf[AX_RX_URB_SIZE]; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE); unsigned char *buf_ptr; int err; int actual_len; -- cgit v1.2.3 From 66f119e50cc854695a3709c67bf6a6c8ef60f6bc Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Fri, 8 Jun 2012 05:26:52 +0000 Subject: net/designware: Consecutive writes to the same register to be avoided This commit is an add-on to f6c4191f. There are a few registers where consecutive writes to the same location should be avoided or have a delay. According to Synopsys, here is a list of the registers and bit(s) where consecutive writes should be avoided or a delay is required: DMA Registers: Register 0 Bit 7 Register 6 All bits except for 24, 16-13, 2-1. GMAC Registers: Registers 0-3 All bits Registers 6-7 All bits Register 10 All bits Register 11 All bits except for 5-6. Registers 16-47 All bits Register 48 All bits except for 18-16, 14. Register 448 Bit 4. Register 459 Bits 0-3. Signed-off-by: Dinh Nguyen Reviewed-by: Matthew Gerlach Acked-by: Amit Virdi --- drivers/net/designware.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 326d550c1f2..bf21a08bdf4 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -171,8 +171,8 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis) writel(FIXEDBURST | PRIORXTX_41 | BURST_16, &dma_p->busmode); - writel(FLUSHTXFIFO | readl(&dma_p->opmode), &dma_p->opmode); - writel(STOREFORWARD | TXSECONDFRAME, &dma_p->opmode); + writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD | + TXSECONDFRAME, &dma_p->opmode); conf = FRAMEBURSTENABLE | DISABLERXOWN; -- cgit v1.2.3 From c88ef3c12dcf8596433d52a2631982d9d3a478dd Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sat, 14 Apr 2012 18:06:49 +0000 Subject: net: allow setting env enetaddr from net device setting If the net driver has setup a valid ethernet address and an ethernet address is not set in the environment already, then set the environment variables from the net driver setting. This enables pxe booting on boards which don't set ethaddr env variable. Signed-off-by: Rob Herring --- doc/README.enetaddr | 6 +++++- net/eth.c | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/README.enetaddr b/doc/README.enetaddr index 2d8e24f5cb4..1eaeaf9416e 100644 --- a/doc/README.enetaddr +++ b/doc/README.enetaddr @@ -32,7 +32,11 @@ Correct flow of setting up the MAC address (summarized): 1. Read from hardware in initialize() function 2. Read from environment in net/eth.c after initialize() -3. Give priority to the value in the environment if a conflict +3. The environment variable will be compared to the driver initialized + struct eth_device->enetaddr. If they differ, a warning is printed, and the + environment variable will be used unchanged. + If the environment variable is not set, it will be initialized from + eth_device->enetaddr, and a warning will be printed. 4. Program the address into hardware if the following conditions are met: a) The relevant driver has a 'write_addr' function b) The user hasn't set an 'ethmacskip' environment variable diff --git a/net/eth.c b/net/eth.c index d526264fa65..6290b332fd3 100644 --- a/net/eth.c +++ b/net/eth.c @@ -62,6 +62,15 @@ int eth_getenv_enetaddr_by_index(const char *base_name, int index, return eth_getenv_enetaddr(enetvar, enetaddr); } +int eth_setenv_enetaddr_by_index(const char *base_name, int index, + uchar *enetaddr) +{ + char enetvar[32]; + sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index); + return eth_setenv_enetaddr(enetvar, enetaddr); +} + + static int eth_mac_skip(int index) { char enetvar[15]; @@ -205,6 +214,11 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name, } memcpy(dev->enetaddr, env_enetaddr, 6); + } else if (is_valid_ether_addr(dev->enetaddr)) { + eth_setenv_enetaddr_by_index(base_name, eth_number, + dev->enetaddr); + printf("\nWarning: %s using MAC address from net device\n", + dev->name); } if (dev->write_hwaddr && -- cgit v1.2.3 From 154177e14a141468374f438ed3096ab097b79976 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 10 Jul 2012 16:23:22 -0500 Subject: net: Inline the new eth_setenv_enetaddr_by_index function This function is currently only used in one case. Inline for now. Signed-off-by: Joe Hershberger --- net/eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/eth.c b/net/eth.c index 6290b332fd3..1a11ce10277 100644 --- a/net/eth.c +++ b/net/eth.c @@ -62,7 +62,7 @@ int eth_getenv_enetaddr_by_index(const char *base_name, int index, return eth_getenv_enetaddr(enetvar, enetaddr); } -int eth_setenv_enetaddr_by_index(const char *base_name, int index, +static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index, uchar *enetaddr) { char enetvar[32]; -- cgit v1.2.3