diff options
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 98 |
1 files changed, 55 insertions, 43 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 6bb5af35eda6..b4e18a58cb1b 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/types.h> | 55 | #include <linux/types.h> |
56 | #include <linux/inet_lro.h> | 56 | #include <linux/inet_lro.h> |
57 | #include <asm/system.h> | 57 | #include <asm/system.h> |
58 | #include <linux/list.h> | ||
58 | 59 | ||
59 | static char mv643xx_eth_driver_name[] = "mv643xx_eth"; | 60 | static char mv643xx_eth_driver_name[] = "mv643xx_eth"; |
60 | static char mv643xx_eth_driver_version[] = "1.4"; | 61 | static char mv643xx_eth_driver_version[] = "1.4"; |
@@ -88,7 +89,24 @@ static char mv643xx_eth_driver_version[] = "1.4"; | |||
88 | #define MAC_ADDR_LOW 0x0014 | 89 | #define MAC_ADDR_LOW 0x0014 |
89 | #define MAC_ADDR_HIGH 0x0018 | 90 | #define MAC_ADDR_HIGH 0x0018 |
90 | #define SDMA_CONFIG 0x001c | 91 | #define SDMA_CONFIG 0x001c |
92 | #define TX_BURST_SIZE_16_64BIT 0x01000000 | ||
93 | #define TX_BURST_SIZE_4_64BIT 0x00800000 | ||
94 | #define BLM_TX_NO_SWAP 0x00000020 | ||
95 | #define BLM_RX_NO_SWAP 0x00000010 | ||
96 | #define RX_BURST_SIZE_16_64BIT 0x00000008 | ||
97 | #define RX_BURST_SIZE_4_64BIT 0x00000004 | ||
91 | #define PORT_SERIAL_CONTROL 0x003c | 98 | #define PORT_SERIAL_CONTROL 0x003c |
99 | #define SET_MII_SPEED_TO_100 0x01000000 | ||
100 | #define SET_GMII_SPEED_TO_1000 0x00800000 | ||
101 | #define SET_FULL_DUPLEX_MODE 0x00200000 | ||
102 | #define MAX_RX_PACKET_9700BYTE 0x000a0000 | ||
103 | #define DISABLE_AUTO_NEG_SPEED_GMII 0x00002000 | ||
104 | #define DO_NOT_FORCE_LINK_FAIL 0x00000400 | ||
105 | #define SERIAL_PORT_CONTROL_RESERVED 0x00000200 | ||
106 | #define DISABLE_AUTO_NEG_FOR_FLOW_CTRL 0x00000008 | ||
107 | #define DISABLE_AUTO_NEG_FOR_DUPLEX 0x00000004 | ||
108 | #define FORCE_LINK_PASS 0x00000002 | ||
109 | #define SERIAL_PORT_ENABLE 0x00000001 | ||
92 | #define PORT_STATUS 0x0044 | 110 | #define PORT_STATUS 0x0044 |
93 | #define TX_FIFO_EMPTY 0x00000400 | 111 | #define TX_FIFO_EMPTY 0x00000400 |
94 | #define TX_IN_PROGRESS 0x00000080 | 112 | #define TX_IN_PROGRESS 0x00000080 |
@@ -106,7 +124,9 @@ static char mv643xx_eth_driver_version[] = "1.4"; | |||
106 | #define TX_BW_BURST 0x005c | 124 | #define TX_BW_BURST 0x005c |
107 | #define INT_CAUSE 0x0060 | 125 | #define INT_CAUSE 0x0060 |
108 | #define INT_TX_END 0x07f80000 | 126 | #define INT_TX_END 0x07f80000 |
127 | #define INT_TX_END_0 0x00080000 | ||
109 | #define INT_RX 0x000003fc | 128 | #define INT_RX 0x000003fc |
129 | #define INT_RX_0 0x00000004 | ||
110 | #define INT_EXT 0x00000002 | 130 | #define INT_EXT 0x00000002 |
111 | #define INT_CAUSE_EXT 0x0064 | 131 | #define INT_CAUSE_EXT 0x0064 |
112 | #define INT_EXT_LINK_PHY 0x00110000 | 132 | #define INT_EXT_LINK_PHY 0x00110000 |
@@ -135,15 +155,8 @@ static char mv643xx_eth_driver_version[] = "1.4"; | |||
135 | 155 | ||
136 | 156 | ||
137 | /* | 157 | /* |
138 | * SDMA configuration register. | 158 | * SDMA configuration register default value. |
139 | */ | 159 | */ |
140 | #define RX_BURST_SIZE_4_64BIT (2 << 1) | ||
141 | #define RX_BURST_SIZE_16_64BIT (4 << 1) | ||
142 | #define BLM_RX_NO_SWAP (1 << 4) | ||
143 | #define BLM_TX_NO_SWAP (1 << 5) | ||
144 | #define TX_BURST_SIZE_4_64BIT (2 << 22) | ||
145 | #define TX_BURST_SIZE_16_64BIT (4 << 22) | ||
146 | |||
147 | #if defined(__BIG_ENDIAN) | 160 | #if defined(__BIG_ENDIAN) |
148 | #define PORT_SDMA_CONFIG_DEFAULT_VALUE \ | 161 | #define PORT_SDMA_CONFIG_DEFAULT_VALUE \ |
149 | (RX_BURST_SIZE_4_64BIT | \ | 162 | (RX_BURST_SIZE_4_64BIT | \ |
@@ -160,22 +173,11 @@ static char mv643xx_eth_driver_version[] = "1.4"; | |||
160 | 173 | ||
161 | 174 | ||
162 | /* | 175 | /* |
163 | * Port serial control register. | 176 | * Misc definitions. |
164 | */ | 177 | */ |
165 | #define SET_MII_SPEED_TO_100 (1 << 24) | 178 | #define DEFAULT_RX_QUEUE_SIZE 128 |
166 | #define SET_GMII_SPEED_TO_1000 (1 << 23) | 179 | #define DEFAULT_TX_QUEUE_SIZE 256 |
167 | #define SET_FULL_DUPLEX_MODE (1 << 21) | 180 | #define SKB_DMA_REALIGN ((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES) |
168 | #define MAX_RX_PACKET_9700BYTE (5 << 17) | ||
169 | #define DISABLE_AUTO_NEG_SPEED_GMII (1 << 13) | ||
170 | #define DO_NOT_FORCE_LINK_FAIL (1 << 10) | ||
171 | #define SERIAL_PORT_CONTROL_RESERVED (1 << 9) | ||
172 | #define DISABLE_AUTO_NEG_FOR_FLOW_CTRL (1 << 3) | ||
173 | #define DISABLE_AUTO_NEG_FOR_DUPLEX (1 << 2) | ||
174 | #define FORCE_LINK_PASS (1 << 1) | ||
175 | #define SERIAL_PORT_ENABLE (1 << 0) | ||
176 | |||
177 | #define DEFAULT_RX_QUEUE_SIZE 128 | ||
178 | #define DEFAULT_TX_QUEUE_SIZE 256 | ||
179 | 181 | ||
180 | 182 | ||
181 | /* | 183 | /* |
@@ -393,6 +395,7 @@ struct mv643xx_eth_private { | |||
393 | struct work_struct tx_timeout_task; | 395 | struct work_struct tx_timeout_task; |
394 | 396 | ||
395 | struct napi_struct napi; | 397 | struct napi_struct napi; |
398 | u32 int_mask; | ||
396 | u8 oom; | 399 | u8 oom; |
397 | u8 work_link; | 400 | u8 work_link; |
398 | u8 work_tx; | 401 | u8 work_tx; |
@@ -651,23 +654,20 @@ static int rxq_refill(struct rx_queue *rxq, int budget) | |||
651 | refilled = 0; | 654 | refilled = 0; |
652 | while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) { | 655 | while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) { |
653 | struct sk_buff *skb; | 656 | struct sk_buff *skb; |
654 | int unaligned; | ||
655 | int rx; | 657 | int rx; |
656 | struct rx_desc *rx_desc; | 658 | struct rx_desc *rx_desc; |
657 | 659 | ||
658 | skb = __skb_dequeue(&mp->rx_recycle); | 660 | skb = __skb_dequeue(&mp->rx_recycle); |
659 | if (skb == NULL) | 661 | if (skb == NULL) |
660 | skb = dev_alloc_skb(mp->skb_size + | 662 | skb = dev_alloc_skb(mp->skb_size); |
661 | dma_get_cache_alignment() - 1); | ||
662 | 663 | ||
663 | if (skb == NULL) { | 664 | if (skb == NULL) { |
664 | mp->oom = 1; | 665 | mp->oom = 1; |
665 | goto oom; | 666 | goto oom; |
666 | } | 667 | } |
667 | 668 | ||
668 | unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1); | 669 | if (SKB_DMA_REALIGN) |
669 | if (unaligned) | 670 | skb_reserve(skb, SKB_DMA_REALIGN); |
670 | skb_reserve(skb, dma_get_cache_alignment() - unaligned); | ||
671 | 671 | ||
672 | refilled++; | 672 | refilled++; |
673 | rxq->rx_desc_count++; | 673 | rxq->rx_desc_count++; |
@@ -969,8 +969,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) | |||
969 | if (skb != NULL) { | 969 | if (skb != NULL) { |
970 | if (skb_queue_len(&mp->rx_recycle) < | 970 | if (skb_queue_len(&mp->rx_recycle) < |
971 | mp->rx_ring_size && | 971 | mp->rx_ring_size && |
972 | skb_recycle_check(skb, mp->skb_size + | 972 | skb_recycle_check(skb, mp->skb_size)) |
973 | dma_get_cache_alignment() - 1)) | ||
974 | __skb_queue_head(&mp->rx_recycle, skb); | 973 | __skb_queue_head(&mp->rx_recycle, skb); |
975 | else | 974 | else |
976 | dev_kfree_skb(skb); | 975 | dev_kfree_skb(skb); |
@@ -1723,20 +1722,20 @@ static void uc_addr_set(struct mv643xx_eth_private *mp, unsigned char *addr) | |||
1723 | 1722 | ||
1724 | static u32 uc_addr_filter_mask(struct net_device *dev) | 1723 | static u32 uc_addr_filter_mask(struct net_device *dev) |
1725 | { | 1724 | { |
1726 | struct dev_addr_list *uc_ptr; | 1725 | struct netdev_hw_addr *ha; |
1727 | u32 nibbles; | 1726 | u32 nibbles; |
1728 | 1727 | ||
1729 | if (dev->flags & IFF_PROMISC) | 1728 | if (dev->flags & IFF_PROMISC) |
1730 | return 0; | 1729 | return 0; |
1731 | 1730 | ||
1732 | nibbles = 1 << (dev->dev_addr[5] & 0x0f); | 1731 | nibbles = 1 << (dev->dev_addr[5] & 0x0f); |
1733 | for (uc_ptr = dev->uc_list; uc_ptr != NULL; uc_ptr = uc_ptr->next) { | 1732 | list_for_each_entry(ha, &dev->uc_list, list) { |
1734 | if (memcmp(dev->dev_addr, uc_ptr->da_addr, 5)) | 1733 | if (memcmp(dev->dev_addr, ha->addr, 5)) |
1735 | return 0; | 1734 | return 0; |
1736 | if ((dev->dev_addr[5] ^ uc_ptr->da_addr[5]) & 0xf0) | 1735 | if ((dev->dev_addr[5] ^ ha->addr[5]) & 0xf0) |
1737 | return 0; | 1736 | return 0; |
1738 | 1737 | ||
1739 | nibbles |= 1 << (uc_ptr->da_addr[5] & 0x0f); | 1738 | nibbles |= 1 << (ha->addr[5] & 0x0f); |
1740 | } | 1739 | } |
1741 | 1740 | ||
1742 | return nibbles; | 1741 | return nibbles; |
@@ -1810,7 +1809,6 @@ static void mv643xx_eth_program_multicast_filter(struct net_device *dev) | |||
1810 | if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) { | 1809 | if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) { |
1811 | int port_num; | 1810 | int port_num; |
1812 | u32 accept; | 1811 | u32 accept; |
1813 | int i; | ||
1814 | 1812 | ||
1815 | oom: | 1813 | oom: |
1816 | port_num = mp->port_num; | 1814 | port_num = mp->port_num; |
@@ -2067,15 +2065,16 @@ static int mv643xx_eth_collect_events(struct mv643xx_eth_private *mp) | |||
2067 | u32 int_cause; | 2065 | u32 int_cause; |
2068 | u32 int_cause_ext; | 2066 | u32 int_cause_ext; |
2069 | 2067 | ||
2070 | int_cause = rdlp(mp, INT_CAUSE) & (INT_TX_END | INT_RX | INT_EXT); | 2068 | int_cause = rdlp(mp, INT_CAUSE) & mp->int_mask; |
2071 | if (int_cause == 0) | 2069 | if (int_cause == 0) |
2072 | return 0; | 2070 | return 0; |
2073 | 2071 | ||
2074 | int_cause_ext = 0; | 2072 | int_cause_ext = 0; |
2075 | if (int_cause & INT_EXT) | 2073 | if (int_cause & INT_EXT) { |
2074 | int_cause &= ~INT_EXT; | ||
2076 | int_cause_ext = rdlp(mp, INT_CAUSE_EXT); | 2075 | int_cause_ext = rdlp(mp, INT_CAUSE_EXT); |
2076 | } | ||
2077 | 2077 | ||
2078 | int_cause &= INT_TX_END | INT_RX; | ||
2079 | if (int_cause) { | 2078 | if (int_cause) { |
2080 | wrlp(mp, INT_CAUSE, ~int_cause); | 2079 | wrlp(mp, INT_CAUSE, ~int_cause); |
2081 | mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) & | 2080 | mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) & |
@@ -2182,6 +2181,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) | |||
2182 | if (mp->work_link) { | 2181 | if (mp->work_link) { |
2183 | mp->work_link = 0; | 2182 | mp->work_link = 0; |
2184 | handle_link_event(mp); | 2183 | handle_link_event(mp); |
2184 | work_done++; | ||
2185 | continue; | 2185 | continue; |
2186 | } | 2186 | } |
2187 | 2187 | ||
@@ -2220,7 +2220,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) | |||
2220 | if (mp->oom) | 2220 | if (mp->oom) |
2221 | mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); | 2221 | mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); |
2222 | napi_complete(napi); | 2222 | napi_complete(napi); |
2223 | wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); | 2223 | wrlp(mp, INT_MASK, mp->int_mask); |
2224 | } | 2224 | } |
2225 | 2225 | ||
2226 | return work_done; | 2226 | return work_done; |
@@ -2341,6 +2341,14 @@ static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp) | |||
2341 | * size field are ignored by the hardware. | 2341 | * size field are ignored by the hardware. |
2342 | */ | 2342 | */ |
2343 | mp->skb_size = (skb_size + 7) & ~7; | 2343 | mp->skb_size = (skb_size + 7) & ~7; |
2344 | |||
2345 | /* | ||
2346 | * If NET_SKB_PAD is smaller than a cache line, | ||
2347 | * netdev_alloc_skb() will cause skb->data to be misaligned | ||
2348 | * to a cache line boundary. If this is the case, include | ||
2349 | * some extra space to allow re-aligning the data area. | ||
2350 | */ | ||
2351 | mp->skb_size += SKB_DMA_REALIGN; | ||
2344 | } | 2352 | } |
2345 | 2353 | ||
2346 | static int mv643xx_eth_open(struct net_device *dev) | 2354 | static int mv643xx_eth_open(struct net_device *dev) |
@@ -2366,6 +2374,8 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
2366 | 2374 | ||
2367 | skb_queue_head_init(&mp->rx_recycle); | 2375 | skb_queue_head_init(&mp->rx_recycle); |
2368 | 2376 | ||
2377 | mp->int_mask = INT_EXT; | ||
2378 | |||
2369 | for (i = 0; i < mp->rxq_count; i++) { | 2379 | for (i = 0; i < mp->rxq_count; i++) { |
2370 | err = rxq_init(mp, i); | 2380 | err = rxq_init(mp, i); |
2371 | if (err) { | 2381 | if (err) { |
@@ -2375,6 +2385,7 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
2375 | } | 2385 | } |
2376 | 2386 | ||
2377 | rxq_refill(mp->rxq + i, INT_MAX); | 2387 | rxq_refill(mp->rxq + i, INT_MAX); |
2388 | mp->int_mask |= INT_RX_0 << i; | ||
2378 | } | 2389 | } |
2379 | 2390 | ||
2380 | if (mp->oom) { | 2391 | if (mp->oom) { |
@@ -2389,12 +2400,13 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
2389 | txq_deinit(mp->txq + i); | 2400 | txq_deinit(mp->txq + i); |
2390 | goto out_free; | 2401 | goto out_free; |
2391 | } | 2402 | } |
2403 | mp->int_mask |= INT_TX_END_0 << i; | ||
2392 | } | 2404 | } |
2393 | 2405 | ||
2394 | port_start(mp); | 2406 | port_start(mp); |
2395 | 2407 | ||
2396 | wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); | 2408 | wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); |
2397 | wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); | 2409 | wrlp(mp, INT_MASK, mp->int_mask); |
2398 | 2410 | ||
2399 | return 0; | 2411 | return 0; |
2400 | 2412 | ||
@@ -2538,7 +2550,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev) | |||
2538 | 2550 | ||
2539 | mv643xx_eth_irq(dev->irq, dev); | 2551 | mv643xx_eth_irq(dev->irq, dev); |
2540 | 2552 | ||
2541 | wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); | 2553 | wrlp(mp, INT_MASK, mp->int_mask); |
2542 | } | 2554 | } |
2543 | #endif | 2555 | #endif |
2544 | 2556 | ||