Changeset 13890


Ignore:
Timestamp:
02/11/10 03:52:11 (3 years ago)
Author:
BrainSlayer
Message:

addition code for mac hanging bug on realtek switch + hydra

Location:
src/linux/pb42/linux-2.6.23/drivers/net
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/linux/pb42/linux-2.6.23/drivers/net/ag7100/ag7100.c

    r13863 r13890  
    3434#endif //CONFIG_BUFFALO // 
    3535 
     36unsigned int rx_hang_detect_pkt_cnt_all[2], rx_hang_detect_pkt_cnt_valid[2],rx_hang_detected[2]; 
     37int set_mac_from_link_flag = 0; 
    3638static ag7100_mac_t *ag7100_macs[2]; 
    3739static void ag7100_hw_setup(ag7100_mac_t *mac); 
     
    3941static void ag7100_oom_timer(unsigned long data); 
    4042static int  ag7100_check_link(ag7100_mac_t *mac); 
     43static int  check_for_dma_hang(ag7100_mac_t *mac); 
    4144static int  ag7100_tx_alloc(ag7100_mac_t *mac); 
    4245static int  ag7100_rx_alloc(ag7100_mac_t *mac); 
     
    5659#endif 
    5760static void ag7100_buffer_free(struct sk_buff *skb); 
    58 //#ifdef CONFIG_AR9100 
    5961void ag7100_dma_reset(ag7100_mac_t *mac); 
    6062int board_version; 
    61 //#endif 
    6263int  ag7100_recv_packets(struct net_device *dev, ag7100_mac_t *mac, 
    6364    int max_work, int *work_done); 
     
    272273    * phy link mgmt 
    273274    */ 
     275    rx_hang_detect_pkt_cnt_all[mac->mac_unit] = ag7100_get_rx_count(mac);            
     276    rx_hang_detect_pkt_cnt_valid[mac->mac_unit] = mac->net_rx_packets; 
     277    rx_hang_detected[mac->mac_unit] = 0; 
     278 
    274279    init_timer(&mac->mac_phy_timer); 
    275280    mac->mac_phy_timer.data     = (unsigned long)mac; 
     
    763768#endif 
    764769 
    765     printk(MODULE_NAME ": cfg_1: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_1)); 
    766     printk(MODULE_NAME ": cfg_2: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_2)); 
    767     printk(MODULE_NAME ": cfg_3: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_3)); 
    768     printk(MODULE_NAME ": cfg_4: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_4)); 
    769     printk(MODULE_NAME ": cfg_5: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_5)); 
    770 } 
     770    printk(MODULE_NAME ": CPU PhaseLockLoop      : %#x\n", *(volatile int *) 0xb8050000);  //set CPU PhaseLockLoop configuration 
     771    printk(MODULE_NAME ": Secondary PhaseLockLoop: %#x\n", *(volatile int *) 0xb8050004);  //set secondary PhaseLockLoop configuration 
     772    printk(MODULE_NAME ": Ethernet Internal Clock Control: %#x\n", *(volatile int *) 0xb8050010);  //set Ethernet Internal Clock Control 
     773    printk(MODULE_NAME ": mii: %#x\n", ar7100_reg_rd(mii_reg(mac))); 
     774    printk(MODULE_NAME ": cfg1: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_CFG1)); 
     775    printk(MODULE_NAME ": cfg2: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_CFG2));         
     776    printk(MODULE_NAME ": fcfg_0: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_0)); 
     777    printk(MODULE_NAME ": fcfg_1: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_1)); 
     778    printk(MODULE_NAME ": fcfg_2: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_2)); 
     779    printk(MODULE_NAME ": fcfg_3: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_3)); 
     780    printk(MODULE_NAME ": fcfg_4: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_4)); 
     781    printk(MODULE_NAME ": fcfg_5: %#x\n", ag7100_reg_rd(mac, AG7100_MAC_FIFO_CFG_5)); 
     782} 
     783 
     784static void copy_txdescs(ag7100_mac_t *mac, int start, int end) 
     785{ 
     786    ag7100_ring_t      *r   = &mac->mac_txring; 
     787    ag7100_ring_t      *tr   = &mac->mac_txring_cache; 
     788    ag7100_desc_t      *tds, *fds; 
     789 
     790    if (end >= r->ring_nelem) end -= r->ring_nelem; 
     791    while (start != end) 
     792    { 
     793        fds = &r->ring_desc[start]; 
     794        tds = &tr->ring_desc[start]; 
     795        memcpy(tds, fds, 8); /* just the first two words of the desc */ 
     796        ag7100_ring_incr(start); 
     797    } 
     798} 
     799 
     800static int check_for_dma_hang(ag7100_mac_t *mac) { 
     801 
     802    ag7100_ring_t   *r     = &mac->mac_txring; 
     803    int              head  = r->ring_head, tail = r->ring_tail; 
     804    ag7100_desc_t   *ds; 
     805#if 1//DMA tx hang 
     806    ag7100_buffer_t *bf; 
     807#endif 
     808    ag7100_buffer_t *bp; 
     809 
     810    ar7100_flush_ge(mac->mac_unit); 
     811 
     812    while (tail != head) 
     813    { 
     814        ds   = &r->ring_desc[tail]; 
     815        bp   =  &r->ring_buffer[tail]; 
     816 
     817        if(ag7100_tx_owned_by_dma(ds)) { 
     818                        if ((jiffies - bp->trans_start) > (1 * HZ)) { 
     819                printk(MODULE_NAME ": Tx Dma status : %s\n", 
     820                ag7100_tx_stopped(mac) ? "inactive" : "active"); 
     821#if 0 
     822                printk(MODULE_NAME ": timestamp:%u jiffies:%u diff:%d\n",bp->trans_start,jiffies, 
     823                             (jiffies - bp->trans_start)); 
     824#endif 
     825               ag7100_dma_reset(mac); 
     826                           return 1; 
     827           } 
     828        } 
     829        ag7100_ring_incr(tail); 
     830    } 
     831    return 0; 
     832} 
     833 
    771834 
    772835/* 
     
    780843    ag7100_phy_speed_t  speed; 
    781844    int                 rc; 
     845 
     846    /* workaround for dma hang, seen on DIR-825 */ 
     847    if(check_for_dma_hang(mac)) 
     848        goto done; 
    782849 
    783850    /* The vitesse switch uses an indirect method to communicate phy status 
     
    848915#endif         
    849916    mod_timer(&mac->mac_phy_timer, jiffies + AG7100_PHY_POLL_SECONDS*HZ); 
     917 
     918/* "Hydra WAN + RealTek PHY with a specific NetGear Hub" Rx hang workaround */ 
     919#if 1//DMA mac hang 
     920     { 
     921        unsigned int perf_cnt = ag7100_get_rx_count(mac); 
     922        if (perf_cnt == 0xffffffff) { 
     923            /* we have saturated the counter. let it overflow to 0 */ 
     924            if (mac->mac_unit == 0) { 
     925                ar7100_reg_wr(AR7100_PERF0_COUNTER, 0); 
     926            } 
     927            else { 
     928                ar7100_reg_wr(AR7100_PERF1_COUNTER, 0); 
     929            } 
     930        } 
     931                int status; 
     932                status = ag7100_reg_rd(mac, AG7100_DMA_RX_STATUS); 
     933        /* perf_cnt increments on every rx pkt including runts. 
     934         * so, the rx hang occurred when perf_cnt incremented, but 
     935         * valid rx pkts didn't get incremented. this could result 
     936         * in a false positive but the likelihood that over a 2sec 
     937         * period all pkts received were runts appears to me 
     938         * to be very low -JK. 
     939         */ 
     940         
     941                if ((perf_cnt > rx_hang_detect_pkt_cnt_all[mac->mac_unit]) && 
     942            (mac->net_rx_packets == rx_hang_detect_pkt_cnt_valid[mac->mac_unit]) && 
     943            (!(status & AG7100_RX_STATUS_PKT_RCVD)) && 
     944            (!((status & AG7100_RX_STATUS_PKTCNT_MASK )>>16))) { 
     945                rx_hang_detected[mac->mac_unit] += 1; 
     946                if ( mac->mac_unit == 1 )             
     947                printk(MODULE_NAME ": WAN Rx Hang Detected %d times!\n",rx_hang_detected[mac->mac_unit]); 
     948                 else 
     949                                printk(MODULE_NAME ": LAN Rx Hang Detected %d times!\n",rx_hang_detected[mac->mac_unit]); 
     950            rx_hang_detect_pkt_cnt_all[mac->mac_unit] = perf_cnt; 
     951                rx_hang_detect_pkt_cnt_valid[mac->mac_unit] = mac->net_rx_packets; 
     952 
     953                if (rx_hang_detected[mac->mac_unit] >= 2) 
     954                        ag7100_dma_reset(mac); 
     955        } 
     956        else { 
     957            rx_hang_detect_pkt_cnt_all[mac->mac_unit] = perf_cnt; 
     958            rx_hang_detect_pkt_cnt_valid[mac->mac_unit] = mac->net_rx_packets; 
     959                rx_hang_detected[mac->mac_unit] = 0; 
     960        } 
     961    } 
     962#endif 
    850963 
    851964    return 0; 
     
    9581071    int                len_this_ds; 
    9591072    ag7100_ring_t      *r   = &mac->mac_txring; 
     1073    ag7100_buffer_t    *bp; 
    9601074 
    9611075    /* force extra pkt if remainder less than 4 bytes */ 
     
    9721086    ag7100_trc_new(ds,"ds addr"); 
    9731087    ag7100_trc_new(ds,"ds len"); 
    974 //#ifdef CONFIG_AR9100 
    9751088    if(ag7100_tx_owned_by_dma(ds)) 
    9761089        ag7100_dma_reset(mac); 
    977 //#else 
    978 //    assert(!ag7100_tx_owned_by_dma(ds)); 
    979 //#endif 
    9801090 
    9811091    ds->pkt_size       = len_this_ds; 
     
    9851095    *len   -= len_this_ds; 
    9861096    *start += len_this_ds; 
     1097 
     1098     bp = &r->ring_buffer[r->ring_head]; 
     1099     bp->trans_start = jiffies; /*Time stamp each packet */ 
    9871100 
    9881101    ag7100_ring_incr(r->ring_head); 
     
    12841397    } 
    12851398#endif 
    1286 #if 1//def CONFIG_AR9100 
    12871399    if(ret == AG7100_RX_DMA_HANG) 
    12881400    { 
     
    12901402        ag7100_dma_reset(mac); 
    12911403    } 
    1292 #endif 
    12931404 
    12941405    if (likely(ret == AG7100_RX_STATUS_NOT_DONE)) 
     
    13791490        if (ag7100_rx_owned_by_dma(ds)) 
    13801491        { 
    1381 #if 1//def CONFIG_AR9100 
    13821492            if(quota == iquota) 
    13831493            { 
     
    13851495                return AG7100_RX_DMA_HANG; 
    13861496            } 
    1387 #else 
    1388             assert(quota != iquota); /* WCL */ 
    1389 #endif 
    13901497            break; 
    13911498        } 
     
    14931600    } 
    14941601 
    1495     assert(iquota != quota); 
     1602    if(quota == iquota) 
     1603    { 
     1604        *work_done = quota = 0; 
     1605        return AG7100_RX_DMA_HANG; 
     1606    } 
     1607 
    14961608    r->ring_head   =  head; 
    14971609 
    14981610    rep = ag7100_rx_replenish(mac); 
    1499 //#ifdef CONFIG_AR9100 
    15001611    if(rep < 0) 
    15011612    { 
     
    15031614        return AG7100_RX_DMA_HANG; 
    15041615    } 
    1505 //#endif 
    15061616    /* 
    15071617    * let's see what changed while we were slogging. 
     
    15851695 
    15861696        ag7100_trc(ds,"ds"); 
    1587 #if 1// CONFIG_AR9100 
    15881697 
    15891698        if(ag7100_rx_owned_by_dma(ds)) 
     
    15911700            return -1; 
    15921701        } 
    1593 #else            
    1594         assert(!ag7100_rx_owned_by_dma(ds)); 
    1595 #endif 
    15961702        assert(!bf->buf_pkt); 
    15971703 
  • src/linux/pb42/linux-2.6.23/drivers/net/ag7100/ag7100.h

    r13863 r13890  
    3535    int             buf_nds;        /*no. of desc for this skb*/ 
    3636    ag7100_desc_t  *buf_lastds;     /*the last desc. (for convenience)*/ 
     37    unsigned long   trans_start;    /*  descriptor time stamp */ 
    3738}ag7100_buffer_t; 
    3839 
     
    8586    int                     mac_fdx; 
    8687    struct timer_list       mac_phy_timer; 
     88    struct timer_list       mac_dbg_timer; 
     89    ag7100_ring_t           mac_txring_cache; 
    8790#if defined(CONFIG_AR9100) && defined(CONFIG_AG7100_GE1_RMII) 
    8891    int                     speed_10t; 
  • src/linux/pb42/linux-2.6.23/drivers/net/ag7240/ag7240.c

    r13879 r13890  
    624624                if (cnt == 0) { 
    625625                #ifdef CONFIG_DIR615E 
    626                     ar7100_set_gpio(13+i,1); 
     626                    ar7100_set_gpio(13+i,0); 
    627627                #endif 
    628628                    s26_wr_phy(i,0x19,(s26_rd_phy(i,0x19) | (0x3c0))); 
     
    635635                    if (cnt <= bRateTab->rate) { 
    636636                #ifdef CONFIG_DIR615E 
    637                         ar7100_set_gpio(13+i,0); 
     637                        ar7100_set_gpio(13+i,1); 
    638638                #endif 
    639639                        s26_wr_phy(i,0x18,((bRateTab->timeOn << 12)|(bRateTab->timeOff << 8))); 
     
    665665            if (ag7240_get_diff(pkt_count,cnt) == 0) { 
    666666                #ifdef CONFIG_DIR615E 
    667                 ar7100_set_gpio(17,1);                 
     667                ar7100_set_gpio(17,0);                 
    668668                #endif 
    669669                s26_wr_phy(4,0x19,(s26_rd_phy(4,0x19) | (0x3c0))); 
     
    676676                if (ag7240_get_diff(pkt_count,cnt) <= bRateTab->rate) { 
    677677                #ifdef CONFIG_DIR615E 
    678                     ar7100_set_gpio(17,0); 
     678                    ar7100_set_gpio(17,1); 
    679679                #endif 
    680680                    s26_wr_phy(4,0x18,((bRateTab->timeOn << 12)|(bRateTab->timeOff << 8))); 
Note: See TracChangeset for help on using the changeset viewer.