Index: linux-2.6.23.17/drivers/net/sl351x_gmac.c =================================================================== --- linux-2.6.23.17.orig/drivers/net/sl351x_gmac.c +++ linux-2.6.23.17/drivers/net/sl351x_gmac.c @@ -127,6 +127,7 @@ static char _debug_prefetch_buf[_DEBUG_P static int gmac_initialized = 0; TOE_INFO_T toe_private_data; static int do_again = 0; +static int rx_poll_enabled; spinlock_t gmac_fq_lock; unsigned int FLAG_SWITCH; @@ -1065,7 +1066,8 @@ static void toe_init_gmac(struct net_dev tp->intr3_enabled = 0xffffffff; tp->intr4_selected = GMAC0_INT_BITS | CLASS_RX_FULL_INT_BITS | HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT; - tp->intr4_enabled = GMAC0_INT_BITS | SWFQ_EMPTY_INT_BIT; + tp->intr4_enabled = GMAC0_INT_BITS | SWFQ_EMPTY_INT_BIT| GMAC0_RX_OVERRUN_INT_BIT; + // GMAC0_TX_PAUSE_OFF_INT_BIT| GMAC0_MIB_INT_BIT; data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) & ~tp->intr0_selected; writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG); @@ -1115,7 +1117,7 @@ static void toe_init_gmac(struct net_dev tp->intr3_enabled |= 0xffffffff; tp->intr4_selected |= CLASS_RX_FULL_INT_BITS | HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT; - tp->intr4_enabled |= SWFQ_EMPTY_INT_BIT; + tp->intr4_enabled |= SWFQ_EMPTY_INT_BIT | GMAC1_RX_OVERRUN_INT_BIT; } data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) | tp->intr0_selected; writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG); @@ -2408,7 +2410,7 @@ static inline void toe_gmac_fill_free_q( // unsigned short max_cnt=TOE_SW_FREEQ_DESC_NUM>>1; fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG); - spin_lock_irqsave(&gmac_fq_lock, flags); + // spin_lock_irqsave(&gmac_fq_lock, flags); //while ((max_cnt--) && (unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, // TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) { while ((unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, @@ -2428,10 +2430,47 @@ static inline void toe_gmac_fill_free_q( SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr); toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32; } - spin_unlock_irqrestore(&gmac_fq_lock, flags); + // spin_unlock_irqrestore(&gmac_fq_lock, flags); } // EXPORT_SYMBOL(toe_gmac_fill_free_q); +static void gmac_registers(const char *message) +{ + unsigned int status0; + unsigned int status1; + unsigned int status2; + unsigned int status3; + unsigned int status4; + + printk("%s\n", message); + + status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG); + status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG); + status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG); + status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG); + status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG); + + printk("status: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n", + status0, status1, status2, status3, status4); + + status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_0_REG); + status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); + status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_2_REG); + status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_3_REG); + status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG); + + printk("mask : s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n", + status0, status1, status2, status3, status4); + + status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG); + status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG); + status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG); + status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG); + status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG); + + printk("select: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n", + status0, status1, status2, status3, status4); +} /*---------------------------------------------------------------------- * toe_gmac_interrupt *----------------------------------------------------------------------*/ @@ -2492,6 +2531,7 @@ if (1) writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG); if (status4) writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG); + #if 0 /* handle freeq interrupt first */ if (status4 & tp->intr4_enabled) { @@ -2536,10 +2576,31 @@ if (1) } if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT)) { - if (likely(netif_rx_schedule_prep(dev))) + if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev))) { - // unsigned int data32; - // disable GMAC-0 rx interrupt + unsigned int data32; + + if (rx_poll_enabled) + gmac_registers("check #1"); + + BUG_ON(rx_poll_enabled == 1); + +#if 0 + /* Masks GMAC-0 rx interrupt */ + data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); + data32 &= ~(DEFAULT_Q0_INT_BIT); + writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); + + /* Masks GMAC-0 queue empty interrupt */ + data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG); + data32 &= ~DEFAULT_Q0_INT_BIT; + writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG); + + data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG); + data32 &= ~DEFAULT_Q0_INT_BIT; + writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG); +#endif + // class-Q & TOE-Q are implemented in future //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); //data32 &= ~DEFAULT_Q0_INT_BIT; @@ -2549,7 +2610,8 @@ if (1) //tp->total_q_cnt_napi=0; //rx_time = jiffies; //rx_old_bytes = isPtr->rx_bytes; - __netif_rx_schedule(dev); + __netif_rx_schedule(dev); + rx_poll_enabled = 1; } } } @@ -2569,9 +2631,31 @@ if (1) if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT)) { - if (likely(netif_rx_schedule_prep(dev))) + if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev))) { - // unsigned int data32; + unsigned int data32; + + if (rx_poll_enabled) + gmac_registers("check #2"); + + BUG_ON(rx_poll_enabled == 1); + +#if 0 + /* Masks GMAC-1 rx interrupt */ + data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); + data32 &= ~(DEFAULT_Q1_INT_BIT); + writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); + + /* Masks GMAC-1 queue empty interrupt */ + data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG); + data32 &= ~DEFAULT_Q1_INT_BIT; + writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG); + + data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG); + data32 &= ~DEFAULT_Q1_INT_BIT; + writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG); +#endif + // disable GMAC-0 rx interrupt // class-Q & TOE-Q are implemented in future //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); @@ -2583,9 +2667,13 @@ if (1) //rx_time = jiffies; //rx_old_bytes = isPtr->rx_bytes; __netif_rx_schedule(dev); + rx_poll_enabled = 1; } } } + } else { + + gmac_registers("check #3"); } // Interrupt Status 0 @@ -3306,8 +3394,10 @@ next_rx: SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr); tp->rx_rwptr.bits32 = rwptr.bits32; - toe_gmac_fill_free_q(); } + + /* Handles first available packets only then refill the queue. */ + toe_gmac_fill_free_q(); } /*---------------------------------------------------------------------- @@ -4217,6 +4307,7 @@ static int gmac_rx_poll(struct net_devic GMAC_RXDESC_T *curr_desc; struct sk_buff *skb; DMA_RWPTR_T rwptr; + unsigned int data32; unsigned int pkt_size; unsigned int desc_count; unsigned int good_frame, chksum_status, rx_status; @@ -4231,7 +4322,7 @@ static int gmac_rx_poll(struct net_devic //unsigned long long rx_time; - + BUG_ON(rx_poll_enabled == 0); #if 1 if (do_again) { @@ -4516,6 +4607,30 @@ static int gmac_rx_poll(struct net_devic #endif //toe_gmac_fill_free_q(); netif_rx_complete(dev); + + rx_poll_enabled = 0; + + data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); + if (tp->port_id == 0) + data32 |= DEFAULT_Q0_INT_BIT; + else + data32 |= DEFAULT_Q1_INT_BIT; + writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); + + data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG); + if (tp->port_id == 0) + data32 |= DEFAULT_Q0_INT_BIT; + else + data32 |= DEFAULT_Q1_INT_BIT; + writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG); + + data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG); + if (tp->port_id == 0) + data32 |= DEFAULT_Q0_INT_BIT; + else + data32 |= DEFAULT_Q1_INT_BIT; + writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG); + // enable GMAC-0 rx interrupt // class-Q & TOE-Q are implemented in future //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);