diff options
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 139 |
1 files changed, 60 insertions, 79 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index fb6b232069d6..7c9dbc8c9423 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -58,11 +58,10 @@ | |||
58 | 58 | ||
59 | #define INT_CAUSE_UNMASK_ALL 0x0007ffff | 59 | #define INT_CAUSE_UNMASK_ALL 0x0007ffff |
60 | #define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff | 60 | #define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff |
61 | #ifdef MV643XX_RX_QUEUE_FILL_ON_TASK | ||
62 | #define INT_CAUSE_MASK_ALL 0x00000000 | 61 | #define INT_CAUSE_MASK_ALL 0x00000000 |
62 | #define INT_CAUSE_MASK_ALL_EXT 0x00000000 | ||
63 | #define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL | 63 | #define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL |
64 | #define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT | 64 | #define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT |
65 | #endif | ||
66 | 65 | ||
67 | #ifdef MV643XX_CHECKSUM_OFFLOAD_TX | 66 | #ifdef MV643XX_CHECKSUM_OFFLOAD_TX |
68 | #define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1) | 67 | #define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1) |
@@ -259,14 +258,13 @@ static void mv643xx_eth_update_mac_address(struct net_device *dev) | |||
259 | static void mv643xx_eth_set_rx_mode(struct net_device *dev) | 258 | static void mv643xx_eth_set_rx_mode(struct net_device *dev) |
260 | { | 259 | { |
261 | struct mv643xx_private *mp = netdev_priv(dev); | 260 | struct mv643xx_private *mp = netdev_priv(dev); |
262 | u32 config_reg; | ||
263 | 261 | ||
264 | config_reg = ethernet_get_config_reg(mp->port_num); | ||
265 | if (dev->flags & IFF_PROMISC) | 262 | if (dev->flags & IFF_PROMISC) |
266 | config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; | 263 | mp->port_config |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; |
267 | else | 264 | else |
268 | config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; | 265 | mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; |
269 | ethernet_set_config_reg(mp->port_num, config_reg); | 266 | |
267 | mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config); | ||
270 | } | 268 | } |
271 | 269 | ||
272 | /* | 270 | /* |
@@ -369,15 +367,6 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev, | |||
369 | 367 | ||
370 | dev_kfree_skb_irq(pkt_info.return_info); | 368 | dev_kfree_skb_irq(pkt_info.return_info); |
371 | released = 0; | 369 | released = 0; |
372 | |||
373 | /* | ||
374 | * Decrement the number of outstanding skbs counter on | ||
375 | * the TX queue. | ||
376 | */ | ||
377 | if (mp->tx_ring_skbs == 0) | ||
378 | panic("ERROR - TX outstanding SKBs" | ||
379 | " counter is corrupted"); | ||
380 | mp->tx_ring_skbs--; | ||
381 | } else | 370 | } else |
382 | dma_unmap_page(NULL, pkt_info.buf_ptr, | 371 | dma_unmap_page(NULL, pkt_info.buf_ptr, |
383 | pkt_info.byte_cnt, DMA_TO_DEVICE); | 372 | pkt_info.byte_cnt, DMA_TO_DEVICE); |
@@ -412,15 +401,13 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) | |||
412 | struct pkt_info pkt_info; | 401 | struct pkt_info pkt_info; |
413 | 402 | ||
414 | #ifdef MV643XX_NAPI | 403 | #ifdef MV643XX_NAPI |
415 | while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) { | 404 | while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) { |
416 | #else | 405 | #else |
417 | while (eth_port_receive(mp, &pkt_info) == ETH_OK) { | 406 | while (eth_port_receive(mp, &pkt_info) == ETH_OK) { |
418 | #endif | 407 | #endif |
419 | mp->rx_ring_skbs--; | 408 | mp->rx_ring_skbs--; |
420 | received_packets++; | 409 | received_packets++; |
421 | #ifdef MV643XX_NAPI | 410 | |
422 | budget--; | ||
423 | #endif | ||
424 | /* Update statistics. Note byte count includes 4 byte CRC count */ | 411 | /* Update statistics. Note byte count includes 4 byte CRC count */ |
425 | stats->rx_packets++; | 412 | stats->rx_packets++; |
426 | stats->rx_bytes += pkt_info.byte_cnt; | 413 | stats->rx_bytes += pkt_info.byte_cnt; |
@@ -1044,9 +1031,6 @@ static void mv643xx_tx(struct net_device *dev) | |||
1044 | DMA_TO_DEVICE); | 1031 | DMA_TO_DEVICE); |
1045 | 1032 | ||
1046 | dev_kfree_skb_irq(pkt_info.return_info); | 1033 | dev_kfree_skb_irq(pkt_info.return_info); |
1047 | |||
1048 | if (mp->tx_ring_skbs) | ||
1049 | mp->tx_ring_skbs--; | ||
1050 | } else | 1034 | } else |
1051 | dma_unmap_page(NULL, pkt_info.buf_ptr, | 1035 | dma_unmap_page(NULL, pkt_info.buf_ptr, |
1052 | pkt_info.byte_cnt, DMA_TO_DEVICE); | 1036 | pkt_info.byte_cnt, DMA_TO_DEVICE); |
@@ -1189,7 +1173,6 @@ linear: | |||
1189 | pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, | 1173 | pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, |
1190 | DMA_TO_DEVICE); | 1174 | DMA_TO_DEVICE); |
1191 | pkt_info.return_info = skb; | 1175 | pkt_info.return_info = skb; |
1192 | mp->tx_ring_skbs++; | ||
1193 | status = eth_port_send(mp, &pkt_info); | 1176 | status = eth_port_send(mp, &pkt_info); |
1194 | if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) | 1177 | if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) |
1195 | printk(KERN_ERR "%s: Error on transmitting packet\n", | 1178 | printk(KERN_ERR "%s: Error on transmitting packet\n", |
@@ -1274,7 +1257,6 @@ linear: | |||
1274 | pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT | | 1257 | pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT | |
1275 | ETH_TX_LAST_DESC; | 1258 | ETH_TX_LAST_DESC; |
1276 | pkt_info.return_info = skb; | 1259 | pkt_info.return_info = skb; |
1277 | mp->tx_ring_skbs++; | ||
1278 | } else { | 1260 | } else { |
1279 | pkt_info.return_info = 0; | 1261 | pkt_info.return_info = 0; |
1280 | } | 1262 | } |
@@ -1311,7 +1293,6 @@ linear: | |||
1311 | pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, | 1293 | pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, |
1312 | DMA_TO_DEVICE); | 1294 | DMA_TO_DEVICE); |
1313 | pkt_info.return_info = skb; | 1295 | pkt_info.return_info = skb; |
1314 | mp->tx_ring_skbs++; | ||
1315 | status = eth_port_send(mp, &pkt_info); | 1296 | status = eth_port_send(mp, &pkt_info); |
1316 | if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) | 1297 | if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) |
1317 | printk(KERN_ERR "%s: Error on transmitting packet\n", | 1298 | printk(KERN_ERR "%s: Error on transmitting packet\n", |
@@ -1356,6 +1337,43 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev) | |||
1356 | return &mp->stats; | 1337 | return &mp->stats; |
1357 | } | 1338 | } |
1358 | 1339 | ||
1340 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1341 | static inline void mv643xx_enable_irq(struct mv643xx_private *mp) | ||
1342 | { | ||
1343 | int port_num = mp->port_num; | ||
1344 | unsigned long flags; | ||
1345 | |||
1346 | spin_lock_irqsave(&mp->lock, flags); | ||
1347 | mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), | ||
1348 | INT_CAUSE_UNMASK_ALL); | ||
1349 | mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), | ||
1350 | INT_CAUSE_UNMASK_ALL_EXT); | ||
1351 | spin_unlock_irqrestore(&mp->lock, flags); | ||
1352 | } | ||
1353 | |||
1354 | static inline void mv643xx_disable_irq(struct mv643xx_private *mp) | ||
1355 | { | ||
1356 | int port_num = mp->port_num; | ||
1357 | unsigned long flags; | ||
1358 | |||
1359 | spin_lock_irqsave(&mp->lock, flags); | ||
1360 | mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), | ||
1361 | INT_CAUSE_MASK_ALL); | ||
1362 | mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), | ||
1363 | INT_CAUSE_MASK_ALL_EXT); | ||
1364 | spin_unlock_irqrestore(&mp->lock, flags); | ||
1365 | } | ||
1366 | |||
1367 | static void mv643xx_netpoll(struct net_device *netdev) | ||
1368 | { | ||
1369 | struct mv643xx_private *mp = netdev_priv(netdev); | ||
1370 | |||
1371 | mv643xx_disable_irq(mp); | ||
1372 | mv643xx_eth_int_handler(netdev->irq, netdev, NULL); | ||
1373 | mv643xx_enable_irq(mp); | ||
1374 | } | ||
1375 | #endif | ||
1376 | |||
1359 | /*/ | 1377 | /*/ |
1360 | * mv643xx_eth_probe | 1378 | * mv643xx_eth_probe |
1361 | * | 1379 | * |
@@ -1406,6 +1424,10 @@ static int mv643xx_eth_probe(struct device *ddev) | |||
1406 | dev->weight = 64; | 1424 | dev->weight = 64; |
1407 | #endif | 1425 | #endif |
1408 | 1426 | ||
1427 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1428 | dev->poll_controller = mv643xx_netpoll; | ||
1429 | #endif | ||
1430 | |||
1409 | dev->watchdog_timeo = 2 * HZ; | 1431 | dev->watchdog_timeo = 2 * HZ; |
1410 | dev->tx_queue_len = mp->tx_ring_size; | 1432 | dev->tx_queue_len = mp->tx_ring_size; |
1411 | dev->base_addr = 0; | 1433 | dev->base_addr = 0; |
@@ -1883,6 +1905,9 @@ static void eth_port_start(struct mv643xx_private *mp) | |||
1883 | /* Enable port Rx. */ | 1905 | /* Enable port Rx. */ |
1884 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), | 1906 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), |
1885 | mp->port_rx_queue_command); | 1907 | mp->port_rx_queue_command); |
1908 | |||
1909 | /* Disable port bandwidth limits by clearing MTU register */ | ||
1910 | mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); | ||
1886 | } | 1911 | } |
1887 | 1912 | ||
1888 | /* | 1913 | /* |
@@ -2292,34 +2317,6 @@ static void eth_port_reset(unsigned int port_num) | |||
2292 | mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data); | 2317 | mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data); |
2293 | } | 2318 | } |
2294 | 2319 | ||
2295 | /* | ||
2296 | * ethernet_set_config_reg - Set specified bits in configuration register. | ||
2297 | * | ||
2298 | * DESCRIPTION: | ||
2299 | * This function sets specified bits in the given ethernet | ||
2300 | * configuration register. | ||
2301 | * | ||
2302 | * INPUT: | ||
2303 | * unsigned int eth_port_num Ethernet Port number. | ||
2304 | * unsigned int value 32 bit value. | ||
2305 | * | ||
2306 | * OUTPUT: | ||
2307 | * The set bits in the value parameter are set in the configuration | ||
2308 | * register. | ||
2309 | * | ||
2310 | * RETURN: | ||
2311 | * None. | ||
2312 | * | ||
2313 | */ | ||
2314 | static void ethernet_set_config_reg(unsigned int eth_port_num, | ||
2315 | unsigned int value) | ||
2316 | { | ||
2317 | unsigned int eth_config_reg; | ||
2318 | |||
2319 | eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num)); | ||
2320 | eth_config_reg |= value; | ||
2321 | mv_write(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num), eth_config_reg); | ||
2322 | } | ||
2323 | 2320 | ||
2324 | static int eth_port_autoneg_supported(unsigned int eth_port_num) | 2321 | static int eth_port_autoneg_supported(unsigned int eth_port_num) |
2325 | { | 2322 | { |
@@ -2346,31 +2343,6 @@ static int eth_port_link_is_up(unsigned int eth_port_num) | |||
2346 | } | 2343 | } |
2347 | 2344 | ||
2348 | /* | 2345 | /* |
2349 | * ethernet_get_config_reg - Get the port configuration register | ||
2350 | * | ||
2351 | * DESCRIPTION: | ||
2352 | * This function returns the configuration register value of the given | ||
2353 | * ethernet port. | ||
2354 | * | ||
2355 | * INPUT: | ||
2356 | * unsigned int eth_port_num Ethernet Port number. | ||
2357 | * | ||
2358 | * OUTPUT: | ||
2359 | * None. | ||
2360 | * | ||
2361 | * RETURN: | ||
2362 | * Port configuration register value. | ||
2363 | */ | ||
2364 | static unsigned int ethernet_get_config_reg(unsigned int eth_port_num) | ||
2365 | { | ||
2366 | unsigned int eth_config_reg; | ||
2367 | |||
2368 | eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG | ||
2369 | (eth_port_num)); | ||
2370 | return eth_config_reg; | ||
2371 | } | ||
2372 | |||
2373 | /* | ||
2374 | * eth_port_read_smi_reg - Read PHY registers | 2346 | * eth_port_read_smi_reg - Read PHY registers |
2375 | * | 2347 | * |
2376 | * DESCRIPTION: | 2348 | * DESCRIPTION: |
@@ -2528,6 +2500,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
2528 | return ETH_ERROR; | 2500 | return ETH_ERROR; |
2529 | } | 2501 | } |
2530 | 2502 | ||
2503 | mp->tx_ring_skbs++; | ||
2504 | BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); | ||
2505 | |||
2531 | /* Get the Tx Desc ring indexes */ | 2506 | /* Get the Tx Desc ring indexes */ |
2532 | tx_desc_curr = mp->tx_curr_desc_q; | 2507 | tx_desc_curr = mp->tx_curr_desc_q; |
2533 | tx_desc_used = mp->tx_used_desc_q; | 2508 | tx_desc_used = mp->tx_used_desc_q; |
@@ -2594,6 +2569,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
2594 | if (mp->tx_resource_err) | 2569 | if (mp->tx_resource_err) |
2595 | return ETH_QUEUE_FULL; | 2570 | return ETH_QUEUE_FULL; |
2596 | 2571 | ||
2572 | mp->tx_ring_skbs++; | ||
2573 | BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); | ||
2574 | |||
2597 | /* Get the Tx Desc ring indexes */ | 2575 | /* Get the Tx Desc ring indexes */ |
2598 | tx_desc_curr = mp->tx_curr_desc_q; | 2576 | tx_desc_curr = mp->tx_curr_desc_q; |
2599 | tx_desc_used = mp->tx_used_desc_q; | 2577 | tx_desc_used = mp->tx_used_desc_q; |
@@ -2694,6 +2672,9 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, | |||
2694 | /* Any Tx return cancels the Tx resource error status */ | 2672 | /* Any Tx return cancels the Tx resource error status */ |
2695 | mp->tx_resource_err = 0; | 2673 | mp->tx_resource_err = 0; |
2696 | 2674 | ||
2675 | BUG_ON(mp->tx_ring_skbs == 0); | ||
2676 | mp->tx_ring_skbs--; | ||
2677 | |||
2697 | return ETH_OK; | 2678 | return ETH_OK; |
2698 | } | 2679 | } |
2699 | 2680 | ||