lkml.org 
[lkml]   [2001]   [Sep]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: rtl8139 nic dies with load (2.4.10, kt266)
    New patch:
    * deadlock in error handling fixed.
    * error handling didn't restart the chip properly.

    Could you try it?
    It should now recover properly from the frame errors.

    --
    Manfred--- 2.4/drivers/net/8139too.c Sun Sep 23 21:20:35 2001
    +++ build-2.4/drivers/net/8139too.c Sun Sep 30 22:31:02 2001
    @@ -618,6 +618,7 @@
    static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
    static inline u32 ether_crc (int length, unsigned char *data);
    static void rtl8139_set_rx_mode (struct net_device *dev);
    +static void __set_rx_mode (struct net_device *dev);
    static void rtl8139_hw_start (struct net_device *dev);

    #ifdef USE_IO_OPS
    @@ -1844,8 +1845,8 @@
    struct rtl8139_private *tp, void *ioaddr)
    {
    u8 tmp8;
    - int tmp_work = 1000;
    -
    + int tmp_work;
    +
    DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",
    dev->name, rx_status);
    if (rx_status & RxTooLong) {
    @@ -1860,33 +1861,62 @@
    tp->stats.rx_length_errors++;
    if (rx_status & RxCRCErr)
    tp->stats.rx_crc_errors++;
    +
    /* Reset the receiver, based on RealTek recommendation. (Bug?) */
    - tp->cur_rx = 0;

    /* disable receive */
    - RTL_W8 (ChipCmd, CmdTxEnb);
    -
    - /* A.C.: Reset the multicast list. */
    - rtl8139_set_rx_mode (dev);
    -
    - /* XXX potentially temporary hack to
    - * restart hung receiver */
    + RTL_W8_F (ChipCmd, CmdTxEnb);
    + tmp_work = 200;
    while (--tmp_work > 0) {
    - barrier();
    + udelay(1);
    + tmp8 = RTL_R8 (ChipCmd);
    + if (!(tmp8 & CmdRxEnb))
    + break;
    + }
    + if (tmp_work <= 0)
    + printk (KERN_WARNING PFX "rx stop wait too long\n");
    + /* restart receive */
    + tmp_work = 200;
    + while (--tmp_work > 0) {
    + RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb);
    + udelay(1);
    tmp8 = RTL_R8 (ChipCmd);
    if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))
    break;
    - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
    }
    -
    - /* G.S.: Re-enable receiver */
    - /* XXX temporary hack to work around receiver hang */
    - rtl8139_set_rx_mode (dev);
    -
    if (tmp_work <= 0)
    printk (KERN_WARNING PFX "tx/rx enable wait too long\n");
    -}

    + /* and reinitialize all rx related registers */
    + { /* I have no idea what I'm doing, just copied
    + * from rtl8139_hw_start.
    + * Manfred Spraul
    + */
    + RTL_W8_F (Cfg9346, Cfg9346_Unlock);
    + /* Must enable Tx/Rx before setting transfer thresholds! */
    + RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
    +
    + tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
    + RTL_W32 (RxConfig, tp->rx_config);
    + tp->cur_rx = 0;
    +
    + if (tp->chipset >= CH_8139B) {
    + /* disable magic packet scanning, which is enabled
    + * when PM is enabled in Config1 */
    + RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5));
    + }
    +
    + DPRINTK("init buffer addresses\n");
    +
    + /* Lock Config[01234] and BMCR register writes */
    + RTL_W8 (Cfg9346, Cfg9346_Lock);
    +
    + /* init Rx ring buffer DMA address */
    + RTL_W32_F (RxBuf, tp->rx_ring_dma);
    + }
    + /* A.C.: Reset the multicast list. */
    + __set_rx_mode (dev);
    +}

    static void rtl8139_rx_interrupt (struct net_device *dev,
    struct rtl8139_private *tp, void *ioaddr)
    @@ -2309,11 +2339,10 @@
    }


    -static void rtl8139_set_rx_mode (struct net_device *dev)
    +static void __set_rx_mode (struct net_device *dev)
    {
    struct rtl8139_private *tp = dev->priv;
    void *ioaddr = tp->mmio_addr;
    - unsigned long flags;
    u32 mc_filter[2]; /* Multicast hash filter */
    int i, rx_mode;
    u32 tmp;
    @@ -2350,22 +2379,28 @@
    }
    }

    - spin_lock_irqsave (&tp->lock, flags);
    -
    /* We can safely update without stopping the chip. */
    tmp = rtl8139_rx_config | rx_mode;
    if (tp->rx_config != tmp) {
    - RTL_W32 (RxConfig, tmp);
    + RTL_W32_F (RxConfig, tmp);
    tp->rx_config = tmp;
    }
    RTL_W32_F (MAR0 + 0, mc_filter[0]);
    RTL_W32_F (MAR0 + 4, mc_filter[1]);

    - spin_unlock_irqrestore (&tp->lock, flags);

    DPRINTK ("EXIT\n");
    }

    +static void rtl8139_set_rx_mode (struct net_device *dev)
    +{
    + unsigned long flags;
    + struct rtl8139_private *tp = dev->priv;
    +
    + spin_lock_irqsave (&tp->lock, flags);
    + __set_rx_mode(dev);
    + spin_unlock_irqrestore (&tp->lock, flags);
    +}

    #ifdef CONFIG_PM
    \
     
     \ /
      Last update: 2005-03-22 13:03    [W:0.031 / U:61.648 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site