Ignore:
Timestamp:
2011-08-04T19:36:31+02:00 (5 years ago)
Author:
nbd
Message:

ar71xx: fix ethernet FIFO state corruption on ar7240

When starting/stopping DMA sometimes the FIFO state gets corrupted,
leading to wildly fluctuating latencies or packet data corruption.
Fix this by issuing a fast MAC reset as soon as the link is detected
as up. Fixes #9689, #9405

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c

    r27895 r27896  
    426426static void ag71xx_hw_stop(struct ag71xx *ag) 
    427427{ 
    428         /* disable all interrupts and stop the rx engine */ 
     428        /* disable all interrupts and stop the rx/tx engine */ 
    429429        ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, 0); 
    430430        ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0); 
    431 } 
    432  
    433 static void ag71xx_hw_init(struct ag71xx *ag) 
     431        ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0); 
     432} 
     433 
     434static void ag71xx_hw_setup(struct ag71xx *ag) 
    434435{ 
    435436        struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); 
    436         u32 reset_mask = pdata->reset_bit; 
    437  
    438         ag71xx_hw_stop(ag); 
    439  
    440         if (pdata->is_ar724x) { 
    441                 u32 reset_phy = reset_mask; 
    442  
    443                 reset_phy &= RESET_MODULE_GE0_PHY | RESET_MODULE_GE1_PHY; 
    444                 reset_mask &= ~(RESET_MODULE_GE0_PHY | RESET_MODULE_GE1_PHY); 
    445  
    446                 ar71xx_device_stop(reset_phy); 
    447                 mdelay(50); 
    448                 ar71xx_device_start(reset_phy); 
    449                 mdelay(200); 
    450         } 
    451  
    452         ag71xx_sb(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_SR); 
    453         udelay(20); 
    454  
    455         ar71xx_device_stop(reset_mask); 
    456         mdelay(100); 
    457         ar71xx_device_start(reset_mask); 
    458         mdelay(200); 
    459437 
    460438        /* setup MAC configuration registers */ 
     
    481459        ag71xx_wr(ag, AG71XX_REG_FIFO_CFG4, FIFO_CFG4_INIT); 
    482460        ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, FIFO_CFG5_INIT); 
     461} 
     462 
     463static void ag71xx_hw_init(struct ag71xx *ag) 
     464{ 
     465        struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); 
     466        u32 reset_mask = pdata->reset_bit; 
     467 
     468        ag71xx_hw_stop(ag); 
     469 
     470        if (pdata->is_ar724x) { 
     471                u32 reset_phy = reset_mask; 
     472 
     473                reset_phy &= RESET_MODULE_GE0_PHY | RESET_MODULE_GE1_PHY; 
     474                reset_mask &= ~(RESET_MODULE_GE0_PHY | RESET_MODULE_GE1_PHY); 
     475 
     476                ar71xx_device_stop(reset_phy); 
     477                mdelay(50); 
     478                ar71xx_device_start(reset_phy); 
     479                mdelay(200); 
     480        } 
     481 
     482        ag71xx_sb(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_SR); 
     483        udelay(20); 
     484 
     485        ar71xx_device_stop(reset_mask); 
     486        mdelay(100); 
     487        ar71xx_device_start(reset_mask); 
     488        mdelay(200); 
     489 
     490        ag71xx_hw_setup(ag); 
    483491 
    484492        ag71xx_dma_reset(ag); 
     493} 
     494 
     495static void ag71xx_fast_reset(struct ag71xx *ag) 
     496{ 
     497        struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); 
     498        struct net_device *dev = ag->dev; 
     499        u32 reset_mask = pdata->reset_bit; 
     500        u32 rx_ds, tx_ds; 
     501        u32 mii_reg; 
     502 
     503        reset_mask &= RESET_MODULE_GE0_MAC | RESET_MODULE_GE1_MAC; 
     504 
     505        mii_reg = ag71xx_rr(ag, AG71XX_REG_MII_CFG); 
     506        rx_ds = ag71xx_rr(ag, AG71XX_REG_RX_DESC); 
     507        tx_ds = ag71xx_rr(ag, AG71XX_REG_TX_DESC); 
     508 
     509        ar71xx_device_stop(reset_mask); 
     510        udelay(10); 
     511        ar71xx_device_start(reset_mask); 
     512        udelay(10); 
     513 
     514        ag71xx_dma_reset(ag); 
     515        ag71xx_hw_setup(ag); 
     516 
     517        ag71xx_wr(ag, AG71XX_REG_RX_DESC, rx_ds); 
     518        ag71xx_wr(ag, AG71XX_REG_TX_DESC, tx_ds); 
     519        ag71xx_wr(ag, AG71XX_REG_MII_CFG, mii_reg); 
     520 
     521        ag71xx_hw_set_macaddr(ag, dev->dev_addr); 
    485522} 
    486523 
     
    509546                return; 
    510547        } 
     548 
     549        if (pdata->is_ar724x) 
     550                ag71xx_fast_reset(ag); 
    511551 
    512552        cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2); 
Note: See TracChangeset for help on using the changeset viewer.