diff options
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 110 |
1 files changed, 49 insertions, 61 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 40ae36b20c9d..c0998ef938e0 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -32,6 +32,8 @@ | |||
32 | */ | 32 | */ |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
35 | #include <linux/in.h> | ||
36 | #include <linux/ip.h> | ||
35 | #include <linux/tcp.h> | 37 | #include <linux/tcp.h> |
36 | #include <linux/udp.h> | 38 | #include <linux/udp.h> |
37 | #include <linux/etherdevice.h> | 39 | #include <linux/etherdevice.h> |
@@ -444,6 +446,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) | |||
444 | netif_rx(skb); | 446 | netif_rx(skb); |
445 | #endif | 447 | #endif |
446 | } | 448 | } |
449 | dev->last_rx = jiffies; | ||
447 | } | 450 | } |
448 | 451 | ||
449 | return received_packets; | 452 | return received_packets; |
@@ -461,7 +464,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) | |||
461 | */ | 464 | */ |
462 | 465 | ||
463 | static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, | 466 | static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, |
464 | struct pt_regs *regs) | 467 | struct pt_regs *regs) |
465 | { | 468 | { |
466 | struct net_device *dev = (struct net_device *)dev_id; | 469 | struct net_device *dev = (struct net_device *)dev_id; |
467 | struct mv643xx_private *mp = netdev_priv(dev); | 470 | struct mv643xx_private *mp = netdev_priv(dev); |
@@ -1047,16 +1050,15 @@ static int mv643xx_poll(struct net_device *dev, int *budget) | |||
1047 | 1050 | ||
1048 | static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb) | 1051 | static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb) |
1049 | { | 1052 | { |
1050 | unsigned int frag; | 1053 | unsigned int frag; |
1051 | skb_frag_t *fragp; | 1054 | skb_frag_t *fragp; |
1052 | |||
1053 | for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { | ||
1054 | fragp = &skb_shinfo(skb)->frags[frag]; | ||
1055 | if (fragp->size <= 8 && fragp->page_offset & 0x7) | ||
1056 | return 1; | ||
1057 | 1055 | ||
1058 | } | 1056 | for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { |
1059 | return 0; | 1057 | fragp = &skb_shinfo(skb)->frags[frag]; |
1058 | if (fragp->size <= 8 && fragp->page_offset & 0x7) | ||
1059 | return 1; | ||
1060 | } | ||
1061 | return 0; | ||
1060 | } | 1062 | } |
1061 | 1063 | ||
1062 | 1064 | ||
@@ -2137,26 +2139,26 @@ static void eth_port_set_multicast_list(struct net_device *dev) | |||
2137 | */ | 2139 | */ |
2138 | if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) { | 2140 | if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) { |
2139 | for (table_index = 0; table_index <= 0xFC; table_index += 4) { | 2141 | for (table_index = 0; table_index <= 0xFC; table_index += 4) { |
2140 | /* Set all entries in DA filter special multicast | 2142 | /* Set all entries in DA filter special multicast |
2141 | * table (Ex_dFSMT) | 2143 | * table (Ex_dFSMT) |
2142 | * Set for ETH_Q0 for now | 2144 | * Set for ETH_Q0 for now |
2143 | * Bits | 2145 | * Bits |
2144 | * 0 Accept=1, Drop=0 | 2146 | * 0 Accept=1, Drop=0 |
2145 | * 3-1 Queue ETH_Q0=0 | 2147 | * 3-1 Queue ETH_Q0=0 |
2146 | * 7-4 Reserved = 0; | 2148 | * 7-4 Reserved = 0; |
2147 | */ | 2149 | */ |
2148 | mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); | 2150 | mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); |
2149 | 2151 | ||
2150 | /* Set all entries in DA filter other multicast | 2152 | /* Set all entries in DA filter other multicast |
2151 | * table (Ex_dFOMT) | 2153 | * table (Ex_dFOMT) |
2152 | * Set for ETH_Q0 for now | 2154 | * Set for ETH_Q0 for now |
2153 | * Bits | 2155 | * Bits |
2154 | * 0 Accept=1, Drop=0 | 2156 | * 0 Accept=1, Drop=0 |
2155 | * 3-1 Queue ETH_Q0=0 | 2157 | * 3-1 Queue ETH_Q0=0 |
2156 | * 7-4 Reserved = 0; | 2158 | * 7-4 Reserved = 0; |
2157 | */ | 2159 | */ |
2158 | mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); | 2160 | mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); |
2159 | } | 2161 | } |
2160 | return; | 2162 | return; |
2161 | } | 2163 | } |
2162 | 2164 | ||
@@ -2617,7 +2619,6 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
2617 | struct eth_tx_desc *current_descriptor; | 2619 | struct eth_tx_desc *current_descriptor; |
2618 | struct eth_tx_desc *first_descriptor; | 2620 | struct eth_tx_desc *first_descriptor; |
2619 | u32 command; | 2621 | u32 command; |
2620 | unsigned long flags; | ||
2621 | 2622 | ||
2622 | /* Do not process Tx ring in case of Tx ring resource error */ | 2623 | /* Do not process Tx ring in case of Tx ring resource error */ |
2623 | if (mp->tx_resource_err) | 2624 | if (mp->tx_resource_err) |
@@ -2634,8 +2635,6 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
2634 | return ETH_ERROR; | 2635 | return ETH_ERROR; |
2635 | } | 2636 | } |
2636 | 2637 | ||
2637 | spin_lock_irqsave(&mp->lock, flags); | ||
2638 | |||
2639 | mp->tx_ring_skbs++; | 2638 | mp->tx_ring_skbs++; |
2640 | BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); | 2639 | BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); |
2641 | 2640 | ||
@@ -2685,15 +2684,11 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
2685 | mp->tx_resource_err = 1; | 2684 | mp->tx_resource_err = 1; |
2686 | mp->tx_curr_desc_q = tx_first_desc; | 2685 | mp->tx_curr_desc_q = tx_first_desc; |
2687 | 2686 | ||
2688 | spin_unlock_irqrestore(&mp->lock, flags); | ||
2689 | |||
2690 | return ETH_QUEUE_LAST_RESOURCE; | 2687 | return ETH_QUEUE_LAST_RESOURCE; |
2691 | } | 2688 | } |
2692 | 2689 | ||
2693 | mp->tx_curr_desc_q = tx_next_desc; | 2690 | mp->tx_curr_desc_q = tx_next_desc; |
2694 | 2691 | ||
2695 | spin_unlock_irqrestore(&mp->lock, flags); | ||
2696 | |||
2697 | return ETH_OK; | 2692 | return ETH_OK; |
2698 | } | 2693 | } |
2699 | #else | 2694 | #else |
@@ -2704,14 +2699,11 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
2704 | int tx_desc_used; | 2699 | int tx_desc_used; |
2705 | struct eth_tx_desc *current_descriptor; | 2700 | struct eth_tx_desc *current_descriptor; |
2706 | unsigned int command_status; | 2701 | unsigned int command_status; |
2707 | unsigned long flags; | ||
2708 | 2702 | ||
2709 | /* Do not process Tx ring in case of Tx ring resource error */ | 2703 | /* Do not process Tx ring in case of Tx ring resource error */ |
2710 | if (mp->tx_resource_err) | 2704 | if (mp->tx_resource_err) |
2711 | return ETH_QUEUE_FULL; | 2705 | return ETH_QUEUE_FULL; |
2712 | 2706 | ||
2713 | spin_lock_irqsave(&mp->lock, flags); | ||
2714 | |||
2715 | mp->tx_ring_skbs++; | 2707 | mp->tx_ring_skbs++; |
2716 | BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); | 2708 | BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); |
2717 | 2709 | ||
@@ -2742,12 +2734,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
2742 | /* Check for ring index overlap in the Tx desc ring */ | 2734 | /* Check for ring index overlap in the Tx desc ring */ |
2743 | if (tx_desc_curr == tx_desc_used) { | 2735 | if (tx_desc_curr == tx_desc_used) { |
2744 | mp->tx_resource_err = 1; | 2736 | mp->tx_resource_err = 1; |
2745 | |||
2746 | spin_unlock_irqrestore(&mp->lock, flags); | ||
2747 | return ETH_QUEUE_LAST_RESOURCE; | 2737 | return ETH_QUEUE_LAST_RESOURCE; |
2748 | } | 2738 | } |
2749 | 2739 | ||
2750 | spin_unlock_irqrestore(&mp->lock, flags); | ||
2751 | return ETH_OK; | 2740 | return ETH_OK; |
2752 | } | 2741 | } |
2753 | #endif | 2742 | #endif |
@@ -2898,8 +2887,10 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp, | |||
2898 | p_pkt_info->return_info = mp->rx_skb[rx_curr_desc]; | 2887 | p_pkt_info->return_info = mp->rx_skb[rx_curr_desc]; |
2899 | p_pkt_info->l4i_chk = p_rx_desc->buf_size; | 2888 | p_pkt_info->l4i_chk = p_rx_desc->buf_size; |
2900 | 2889 | ||
2901 | /* Clean the return info field to indicate that the packet has been */ | 2890 | /* |
2902 | /* moved to the upper layers */ | 2891 | * Clean the return info field to indicate that the |
2892 | * packet has been moved to the upper layers | ||
2893 | */ | ||
2903 | mp->rx_skb[rx_curr_desc] = NULL; | 2894 | mp->rx_skb[rx_curr_desc] = NULL; |
2904 | 2895 | ||
2905 | /* Update current index in data structure */ | 2896 | /* Update current index in data structure */ |
@@ -2980,7 +2971,7 @@ struct mv643xx_stats { | |||
2980 | }; | 2971 | }; |
2981 | 2972 | ||
2982 | #define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \ | 2973 | #define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \ |
2983 | offsetof(struct mv643xx_private, m) | 2974 | offsetof(struct mv643xx_private, m) |
2984 | 2975 | ||
2985 | static const struct mv643xx_stats mv643xx_gstrings_stats[] = { | 2976 | static const struct mv643xx_stats mv643xx_gstrings_stats[] = { |
2986 | { "rx_packets", MV643XX_STAT(stats.rx_packets) }, | 2977 | { "rx_packets", MV643XX_STAT(stats.rx_packets) }, |
@@ -3131,9 +3122,8 @@ mv643xx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | |||
3131 | return 0; | 3122 | return 0; |
3132 | } | 3123 | } |
3133 | 3124 | ||
3134 | static void | 3125 | static void mv643xx_get_drvinfo(struct net_device *netdev, |
3135 | mv643xx_get_drvinfo(struct net_device *netdev, | 3126 | struct ethtool_drvinfo *drvinfo) |
3136 | struct ethtool_drvinfo *drvinfo) | ||
3137 | { | 3127 | { |
3138 | strncpy(drvinfo->driver, mv643xx_driver_name, 32); | 3128 | strncpy(drvinfo->driver, mv643xx_driver_name, 32); |
3139 | strncpy(drvinfo->version, mv643xx_driver_version, 32); | 3129 | strncpy(drvinfo->version, mv643xx_driver_version, 32); |
@@ -3142,39 +3132,37 @@ mv643xx_get_drvinfo(struct net_device *netdev, | |||
3142 | drvinfo->n_stats = MV643XX_STATS_LEN; | 3132 | drvinfo->n_stats = MV643XX_STATS_LEN; |
3143 | } | 3133 | } |
3144 | 3134 | ||
3145 | static int | 3135 | static int mv643xx_get_stats_count(struct net_device *netdev) |
3146 | mv643xx_get_stats_count(struct net_device *netdev) | ||
3147 | { | 3136 | { |
3148 | return MV643XX_STATS_LEN; | 3137 | return MV643XX_STATS_LEN; |
3149 | } | 3138 | } |
3150 | 3139 | ||
3151 | static void | 3140 | static void mv643xx_get_ethtool_stats(struct net_device *netdev, |
3152 | mv643xx_get_ethtool_stats(struct net_device *netdev, | 3141 | struct ethtool_stats *stats, uint64_t *data) |
3153 | struct ethtool_stats *stats, uint64_t *data) | ||
3154 | { | 3142 | { |
3155 | struct mv643xx_private *mp = netdev->priv; | 3143 | struct mv643xx_private *mp = netdev->priv; |
3156 | int i; | 3144 | int i; |
3157 | 3145 | ||
3158 | eth_update_mib_counters(mp); | 3146 | eth_update_mib_counters(mp); |
3159 | 3147 | ||
3160 | for(i = 0; i < MV643XX_STATS_LEN; i++) { | 3148 | for (i = 0; i < MV643XX_STATS_LEN; i++) { |
3161 | char *p = (char *)mp+mv643xx_gstrings_stats[i].stat_offset; | 3149 | char *p = (char *)mp+mv643xx_gstrings_stats[i].stat_offset; |
3162 | data[i] = (mv643xx_gstrings_stats[i].sizeof_stat == | 3150 | data[i] = (mv643xx_gstrings_stats[i].sizeof_stat == |
3163 | sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; | 3151 | sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; |
3164 | } | 3152 | } |
3165 | } | 3153 | } |
3166 | 3154 | ||
3167 | static void | 3155 | static void mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, |
3168 | mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) | 3156 | uint8_t *data) |
3169 | { | 3157 | { |
3170 | int i; | 3158 | int i; |
3171 | 3159 | ||
3172 | switch(stringset) { | 3160 | switch(stringset) { |
3173 | case ETH_SS_STATS: | 3161 | case ETH_SS_STATS: |
3174 | for (i=0; i < MV643XX_STATS_LEN; i++) { | 3162 | for (i=0; i < MV643XX_STATS_LEN; i++) { |
3175 | memcpy(data + i * ETH_GSTRING_LEN, | 3163 | memcpy(data + i * ETH_GSTRING_LEN, |
3176 | mv643xx_gstrings_stats[i].stat_string, | 3164 | mv643xx_gstrings_stats[i].stat_string, |
3177 | ETH_GSTRING_LEN); | 3165 | ETH_GSTRING_LEN); |
3178 | } | 3166 | } |
3179 | break; | 3167 | break; |
3180 | } | 3168 | } |