diff options
Diffstat (limited to 'drivers/net/niu.c')
-rw-r--r-- | drivers/net/niu.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index abfc61c3a38c..9a0c6d3adfe9 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
@@ -33,8 +33,8 @@ | |||
33 | 33 | ||
34 | #define DRV_MODULE_NAME "niu" | 34 | #define DRV_MODULE_NAME "niu" |
35 | #define PFX DRV_MODULE_NAME ": " | 35 | #define PFX DRV_MODULE_NAME ": " |
36 | #define DRV_MODULE_VERSION "0.5" | 36 | #define DRV_MODULE_VERSION "0.6" |
37 | #define DRV_MODULE_RELDATE "October 5, 2007" | 37 | #define DRV_MODULE_RELDATE "January 5, 2008" |
38 | 38 | ||
39 | static char version[] __devinitdata = | 39 | static char version[] __devinitdata = |
40 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 40 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
@@ -2241,6 +2241,8 @@ static int niu_process_rx_pkt(struct niu *np, struct rx_ring_info *rp) | |||
2241 | skb->protocol = eth_type_trans(skb, np->dev); | 2241 | skb->protocol = eth_type_trans(skb, np->dev); |
2242 | netif_receive_skb(skb); | 2242 | netif_receive_skb(skb); |
2243 | 2243 | ||
2244 | np->dev->last_rx = jiffies; | ||
2245 | |||
2244 | return num_rcr; | 2246 | return num_rcr; |
2245 | } | 2247 | } |
2246 | 2248 | ||
@@ -2508,15 +2510,19 @@ static int niu_rx_error(struct niu *np, struct rx_ring_info *rp) | |||
2508 | u64 stat = nr64(RX_DMA_CTL_STAT(rp->rx_channel)); | 2510 | u64 stat = nr64(RX_DMA_CTL_STAT(rp->rx_channel)); |
2509 | int err = 0; | 2511 | int err = 0; |
2510 | 2512 | ||
2511 | dev_err(np->device, PFX "%s: RX channel %u error, stat[%llx]\n", | ||
2512 | np->dev->name, rp->rx_channel, (unsigned long long) stat); | ||
2513 | |||
2514 | niu_log_rxchan_errors(np, rp, stat); | ||
2515 | 2513 | ||
2516 | if (stat & (RX_DMA_CTL_STAT_CHAN_FATAL | | 2514 | if (stat & (RX_DMA_CTL_STAT_CHAN_FATAL | |
2517 | RX_DMA_CTL_STAT_PORT_FATAL)) | 2515 | RX_DMA_CTL_STAT_PORT_FATAL)) |
2518 | err = -EINVAL; | 2516 | err = -EINVAL; |
2519 | 2517 | ||
2518 | if (err) { | ||
2519 | dev_err(np->device, PFX "%s: RX channel %u error, stat[%llx]\n", | ||
2520 | np->dev->name, rp->rx_channel, | ||
2521 | (unsigned long long) stat); | ||
2522 | |||
2523 | niu_log_rxchan_errors(np, rp, stat); | ||
2524 | } | ||
2525 | |||
2520 | nw64(RX_DMA_CTL_STAT(rp->rx_channel), | 2526 | nw64(RX_DMA_CTL_STAT(rp->rx_channel), |
2521 | stat & RX_DMA_CTL_WRITE_CLEAR_ERRS); | 2527 | stat & RX_DMA_CTL_WRITE_CLEAR_ERRS); |
2522 | 2528 | ||
@@ -2749,13 +2755,16 @@ static int niu_device_error(struct niu *np) | |||
2749 | return -ENODEV; | 2755 | return -ENODEV; |
2750 | } | 2756 | } |
2751 | 2757 | ||
2752 | static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp) | 2758 | static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp, |
2759 | u64 v0, u64 v1, u64 v2) | ||
2753 | { | 2760 | { |
2754 | u64 v0 = lp->v0; | 2761 | |
2755 | u64 v1 = lp->v1; | ||
2756 | u64 v2 = lp->v2; | ||
2757 | int i, err = 0; | 2762 | int i, err = 0; |
2758 | 2763 | ||
2764 | lp->v0 = v0; | ||
2765 | lp->v1 = v1; | ||
2766 | lp->v2 = v2; | ||
2767 | |||
2759 | if (v1 & 0x00000000ffffffffULL) { | 2768 | if (v1 & 0x00000000ffffffffULL) { |
2760 | u32 rx_vec = (v1 & 0xffffffff); | 2769 | u32 rx_vec = (v1 & 0xffffffff); |
2761 | 2770 | ||
@@ -2764,8 +2773,13 @@ static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp) | |||
2764 | 2773 | ||
2765 | if (rx_vec & (1 << rp->rx_channel)) { | 2774 | if (rx_vec & (1 << rp->rx_channel)) { |
2766 | int r = niu_rx_error(np, rp); | 2775 | int r = niu_rx_error(np, rp); |
2767 | if (r) | 2776 | if (r) { |
2768 | err = r; | 2777 | err = r; |
2778 | } else { | ||
2779 | if (!v0) | ||
2780 | nw64(RX_DMA_CTL_STAT(rp->rx_channel), | ||
2781 | RX_DMA_CTL_STAT_MEX); | ||
2782 | } | ||
2769 | } | 2783 | } |
2770 | } | 2784 | } |
2771 | } | 2785 | } |
@@ -2803,7 +2817,7 @@ static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp) | |||
2803 | if (err) | 2817 | if (err) |
2804 | niu_enable_interrupts(np, 0); | 2818 | niu_enable_interrupts(np, 0); |
2805 | 2819 | ||
2806 | return -EINVAL; | 2820 | return err; |
2807 | } | 2821 | } |
2808 | 2822 | ||
2809 | static void niu_rxchan_intr(struct niu *np, struct rx_ring_info *rp, | 2823 | static void niu_rxchan_intr(struct niu *np, struct rx_ring_info *rp, |
@@ -2905,7 +2919,7 @@ static irqreturn_t niu_interrupt(int irq, void *dev_id) | |||
2905 | } | 2919 | } |
2906 | 2920 | ||
2907 | if (unlikely((v0 & ((u64)1 << LDN_MIF)) || v1 || v2)) { | 2921 | if (unlikely((v0 & ((u64)1 << LDN_MIF)) || v1 || v2)) { |
2908 | int err = niu_slowpath_interrupt(np, lp); | 2922 | int err = niu_slowpath_interrupt(np, lp, v0, v1, v2); |
2909 | if (err) | 2923 | if (err) |
2910 | goto out; | 2924 | goto out; |
2911 | } | 2925 | } |
@@ -5194,7 +5208,8 @@ static int niu_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
5194 | } | 5208 | } |
5195 | kfree_skb(skb); | 5209 | kfree_skb(skb); |
5196 | skb = skb_new; | 5210 | skb = skb_new; |
5197 | } | 5211 | } else |
5212 | skb_orphan(skb); | ||
5198 | 5213 | ||
5199 | align = ((unsigned long) skb->data & (16 - 1)); | 5214 | align = ((unsigned long) skb->data & (16 - 1)); |
5200 | headroom = align + sizeof(struct tx_pkt_hdr); | 5215 | headroom = align + sizeof(struct tx_pkt_hdr); |