[U-Boot-Users] RTL-8169/8167 issues

Hi, I'm trying to get a recent u-boot running properly on a QNAP TurboStation TS-101/TS-201, and I'm having problems with the network driver. When powered on, the device refuses to send anything to the network on the first attempt (eg. first ping fails). The second and subsequent attempts however, works perfectly.
With debugging switched on, the driver outputs the expected init output, but on the first attempt appears to loop on "rtl_recv", outputting this hundreds of times. (I don't have a debug log handy right now, but the only difference is that instead of *one* rtl_recv, there are hundreds) On the second attempt, there's only one rtl_recv.
Anyone got a clue as to what is going on? I'm using the attached patch to correct endianness issues and add device IDs.
Regards, Øyvind Repvik
--- u-boot-1.3.1.orig/drivers/net/rtl8169.c 2007-12-06 10:21:19.000000000 +0100 +++ u-boot-1.3.1.ts/drivers/net/rtl8169.c 2008-02-24 17:48:40.000000000 +0100 @@ -48,7 +48,10 @@ * * Indent Options: indent -kr -i8 ***************************************************************************/ - +/* + * 26 August 2006 Mihai Georgian u-boot@linuxnotincluded.org.uk + * Modified to use le32_to_cpu and cpu_to_le32 properly + */ #include <common.h> #include <malloc.h> #include <net.h> @@ -68,12 +71,7 @@ static u32 ioaddr;
/* Condensed operations for readability. */ -#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) -#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) - #define currticks() get_timer(0) -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a)
/* media options */ #define MAX_UNITS 8 @@ -102,7 +100,7 @@ #define RTL_MIN_IO_SIZE 0x80 #define TX_TIMEOUT (6*HZ)
-/* write/read MMIO register */ +/* write/read MMIO register. Notice: {read,write}[wl] do the necessary swapping */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) #define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) #define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) @@ -218,7 +216,7 @@ PHY_Enable_Auto_Nego = 0x1000,
/* PHY_STAT_REG = 1; */ - PHY_Auto_Neco_Comp = 0x0020, + PHY_Auto_Nego_Comp = 0x0020,
/* PHY_AUTO_NEGO_REG = 4; */ PHY_Cap_10_Half = 0x0020, @@ -249,6 +247,16 @@ } rtl_chip_info[] = { {"RTL-8169", 0x00, 0xff7e1880,}, {"RTL-8169", 0x04, 0xff7e1880,}, + {"RTL8169", 0x00, 0xff7e1880,}, + {"RTL8169s/8110s", 0x02, 0xff7e1880,}, + {"RTL8169s/8110s", 0x04, 0xff7e1880,}, + {"RTL8169sb/8110sb", 0x10, 0xff7e1880,}, + {"RTL8169sc/8110sc", 0x18, 0xff7e1880,}, + {"RTL8168b/8111sb", 0x30, 0xff7e1880,}, + {"RTL8168b/8111sb", 0x38, 0xff7e1880,}, + {"RTL8101e", 0x34, 0xff7e1880,}, + {"RTL8100e", 0x32, 0xff7e1880,}, + };
enum _DescStatusBit { @@ -315,7 +323,7 @@
static struct pci_device_id supported[] = { {PCI_VENDOR_ID_REALTEK, 0x8169}, - {} + {PCI_VENDOR_ID_REALTEK, 0x8167} };
void mdio_write(int RegAddr, int value) @@ -413,23 +421,23 @@ ioaddr = dev->iobase;
cur_rx = tpc->cur_rx; - if ((tpc->RxDescArray[cur_rx].status & OWNbit) == 0) { - if (!(tpc->RxDescArray[cur_rx].status & RxRES)) { + if ((le32_to_cpu(tpc->RxDescArray[cur_rx].status) & OWNbit) == 0) { + if (!(le32_to_cpu(tpc->RxDescArray[cur_rx].status) & RxRES)) { unsigned char rxdata[RX_BUF_LEN]; - length = (int) (tpc->RxDescArray[cur_rx]. - status & 0x00001FFF) - 4; + length = (int) (le32_to_cpu(tpc->RxDescArray[cur_rx]. + status) & 0x00001FFF) - 4;
memcpy(rxdata, tpc->RxBufferRing[cur_rx], length); NetReceive(rxdata, length);
if (cur_rx == NUM_RX_DESC - 1) tpc->RxDescArray[cur_rx].status = - (OWNbit | EORbit) + RX_BUF_SIZE; + cpu_to_le32((OWNbit | EORbit) + RX_BUF_SIZE); else tpc->RxDescArray[cur_rx].status = - OWNbit + RX_BUF_SIZE; + cpu_to_le32(OWNbit + RX_BUF_SIZE); tpc->RxDescArray[cur_rx].buf_addr = - virt_to_bus(tpc->RxBufferRing[cur_rx]); + cpu_to_le32(tpc->RxBufferRing[cur_rx]); } else { puts("Error Rx"); } @@ -454,6 +462,7 @@ u8 *ptxb; int entry = tpc->cur_tx % NUM_TX_DESC; u32 len = length; + int ret;
#ifdef DEBUG_RTL8169_TX int stime = currticks(); @@ -470,34 +479,38 @@ while (len < ETH_ZLEN) ptxb[len++] = '\0';
- tpc->TxDescArray[entry].buf_addr = virt_to_bus(ptxb); + tpc->TxDescArray[entry].buf_addr = cpu_to_le32(ptxb); if (entry != (NUM_TX_DESC - 1)) { tpc->TxDescArray[entry].status = - (OWNbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? - len : ETH_ZLEN); + cpu_to_le32((OWNbit | FSbit | LSbit) | + ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } else { tpc->TxDescArray[entry].status = - (OWNbit | EORbit | FSbit | LSbit) | - ((len > ETH_ZLEN) ? length : ETH_ZLEN); + cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) | + ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } RTL_W8(TxPoll, 0x40); /* set polling bit */
tpc->cur_tx++; to = currticks() + TX_TIMEOUT; - while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ + while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit) + && (currticks() < to)); /* wait */
if (currticks() >= to) { #ifdef DEBUG_RTL8169_TX puts ("tx timeout/error\n"); printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); #endif - return 0; + ret = 0; } else { #ifdef DEBUG_RTL8169_TX puts("tx done\n"); #endif - return length; + ret = length; } + /* Delay to make net console (nc) work properly */ + udelay(20); + return ret; }
static void rtl8169_set_rx_mode(struct eth_device *dev) @@ -564,8 +577,8 @@
tpc->cur_rx = 0;
- RTL_W32(TxDescStartAddr, virt_to_le32desc(tpc->TxDescArray)); - RTL_W32(RxDescStartAddr, virt_to_le32desc(tpc->RxDescArray)); + RTL_W32(TxDescStartAddr, tpc->TxDescArray); + RTL_W32(RxDescStartAddr, tpc->RxDescArray); RTL_W8(Cfg9346, Cfg9346_Lock); udelay(10);
@@ -603,13 +616,14 @@ for (i = 0; i < NUM_RX_DESC; i++) { if (i == (NUM_RX_DESC - 1)) tpc->RxDescArray[i].status = - (OWNbit | EORbit) + RX_BUF_SIZE; + cpu_to_le32((OWNbit | EORbit) + RX_BUF_SIZE); else - tpc->RxDescArray[i].status = OWNbit + RX_BUF_SIZE; + tpc->RxDescArray[i].status = + cpu_to_le32(OWNbit + RX_BUF_SIZE);
tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; tpc->RxDescArray[i].buf_addr = - virt_to_bus(tpc->RxBufferRing[i]); + cpu_to_le32(tpc->RxBufferRing[i]); }
#ifdef DEBUG_RTL8169 @@ -623,8 +637,6 @@ static void rtl_reset(struct eth_device *dev, bd_t *bis) { int i; - u8 diff; - u32 TxPhyAddr, RxPhyAddr;
#ifdef DEBUG_RTL8169 int stime = currticks(); @@ -632,25 +644,14 @@ #endif
tpc->TxDescArrays = tx_ring; - if (tpc->TxDescArrays == 0) - puts("Allot Error"); /* Tx Desscriptor needs 256 bytes alignment; */ - TxPhyAddr = virt_to_bus(tpc->TxDescArrays); - diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8)); - TxPhyAddr += diff; - tpc->TxDescArray = (struct TxDesc *) (tpc->TxDescArrays + diff); + tpc->TxDescArray = (struct TxDesc *) ((unsigned long)(tpc->TxDescArrays + + 255) & ~255);
tpc->RxDescArrays = rx_ring; /* Rx Desscriptor needs 256 bytes alignment; */ - RxPhyAddr = virt_to_bus(tpc->RxDescArrays); - diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8)); - RxPhyAddr += diff; - tpc->RxDescArray = (struct RxDesc *) (tpc->RxDescArrays + diff); - - if (tpc->TxDescArrays == NULL || tpc->RxDescArrays == NULL) { - puts("Allocate RxDescArray or TxDescArray failed\n"); - return; - } + tpc->RxDescArray = (struct RxDesc *) ((unsigned long)(tpc->RxDescArrays + + 255) & ~255);
rtl8169_init_ring(dev); rtl8169_hw_start(dev); @@ -733,7 +734,7 @@
/* Get MAC address. FIXME: read EEPROM */ for (i = 0; i < MAC_ADDR_LEN; i++) - dev->enetaddr[i] = RTL_R8(MAC0 + i); + bis->bi_enetaddr[i] = dev->enetaddr[i] = RTL_R8(MAC0 + i);
#ifdef DEBUG_RTL8169 printf("MAC Address"); @@ -808,7 +809,7 @@ /* wait for auto-negotiation process */ for (i = 10000; i > 0; i--) { /* check if auto-negotiation complete */ - if (mdio_read(PHY_STAT_REG) & PHY_Auto_Neco_Comp) { + if (mdio_read(PHY_STAT_REG) & PHY_Auto_Nego_Comp) { udelay(100); option = RTL_R8(PHYstatus); if (option & _1000bpsF) { @@ -818,13 +819,12 @@ #endif } else { #ifdef DEBUG_RTL8169 - printf - ("%s: %sMbps %s-duplex operation.\n", - dev->name, - (option & _100bps) ? "100" : - "10", - (option & FullDup) ? "Full" : - "Half"); + printf("%s: %sMbps %s-duplex operation.\n", + dev->name, + (option & _100bps) ? "100" : + "10", + (option & FullDup) ? "Full" : + "Half"); #endif } break; @@ -869,7 +869,7 @@ sprintf (dev->name, "RTL8169#%d", card_number);
dev->priv = (void *) devno; - dev->iobase = (int)bus_to_phys(iobase); + dev->iobase = (int)pci_mem_to_phys(devno, iobase);
dev->init = rtl_reset; dev->halt = rtl_halt;

Hi, Øyvind.
2008/3/5, Øyvind Repvik repvik@kynisk.com:
Hi, I'm trying to get a recent u-boot running properly on a QNAP TurboStation TS-101/TS-201, and I'm having problems with the network driver. When powered on, the device refuses to send anything to the network on the first attempt (eg. first ping fails). The second and subsequent attempts however, works perfectly.
With debugging switched on, the driver outputs the expected init output, but on the first attempt appears to loop on "rtl_recv", outputting this hundreds of times. (I don't have a debug log handy right now, but the only difference is that instead of *one* rtl_recv, there are hundreds) On the second attempt, there's only one rtl_recv.
Anyone got a clue as to what is going on? I'm using the attached patch to correct endianness issues and add device IDs.
The patch that you wrote already exists in U-boot. Please check latest source code.
regards, Nobuhiro
participants (2)
-
Nobuhiro Iwamatsu
-
Øyvind Repvik