diff options
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 133 |
1 files changed, 79 insertions, 54 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 73c766b3cd11..2daa9b97d2c0 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -83,6 +83,12 @@ static int eth_port_link_is_up(unsigned int eth_port_num); | |||
83 | static void eth_port_uc_addr_get(struct net_device *dev, | 83 | static void eth_port_uc_addr_get(struct net_device *dev, |
84 | unsigned char *MacAddr); | 84 | unsigned char *MacAddr); |
85 | static void eth_port_set_multicast_list(struct net_device *); | 85 | static void eth_port_set_multicast_list(struct net_device *); |
86 | static void mv643xx_eth_port_enable_tx(unsigned int port_num, | ||
87 | unsigned int channels); | ||
88 | static void mv643xx_eth_port_enable_rx(unsigned int port_num, | ||
89 | unsigned int channels); | ||
90 | static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num); | ||
91 | static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num); | ||
86 | static int mv643xx_eth_open(struct net_device *); | 92 | static int mv643xx_eth_open(struct net_device *); |
87 | static int mv643xx_eth_stop(struct net_device *); | 93 | static int mv643xx_eth_stop(struct net_device *); |
88 | static int mv643xx_eth_change_mtu(struct net_device *, int); | 94 | static int mv643xx_eth_change_mtu(struct net_device *, int); |
@@ -535,8 +541,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, | |||
535 | netif_carrier_on(dev); | 541 | netif_carrier_on(dev); |
536 | netif_wake_queue(dev); | 542 | netif_wake_queue(dev); |
537 | /* Start TX queue */ | 543 | /* Start TX queue */ |
538 | mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG | 544 | mv643xx_eth_port_enable_tx(port_num, mp->port_tx_queue_command); |
539 | (port_num), 1); | ||
540 | } else { | 545 | } else { |
541 | netif_carrier_off(dev); | 546 | netif_carrier_off(dev); |
542 | netif_stop_queue(dev); | 547 | netif_stop_queue(dev); |
@@ -668,8 +673,8 @@ static void ether_init_rx_desc_ring(struct mv643xx_private *mp) | |||
668 | 673 | ||
669 | mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc); | 674 | mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc); |
670 | 675 | ||
671 | /* Add the queue to the list of RX queues of this port */ | 676 | /* Enable queue 0 for this port */ |
672 | mp->port_rx_queue_command |= 1; | 677 | mp->port_rx_queue_command = 1; |
673 | } | 678 | } |
674 | 679 | ||
675 | /* | 680 | /* |
@@ -715,8 +720,8 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp) | |||
715 | 720 | ||
716 | mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc); | 721 | mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc); |
717 | 722 | ||
718 | /* Add the queue to the list of Tx queues of this port */ | 723 | /* Enable queue 0 for this port */ |
719 | mp->port_tx_queue_command |= 1; | 724 | mp->port_tx_queue_command = 1; |
720 | } | 725 | } |
721 | 726 | ||
722 | /* | 727 | /* |
@@ -747,9 +752,6 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
747 | return -EAGAIN; | 752 | return -EAGAIN; |
748 | } | 753 | } |
749 | 754 | ||
750 | /* Stop RX Queues */ | ||
751 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00); | ||
752 | |||
753 | eth_port_init(mp); | 755 | eth_port_init(mp); |
754 | 756 | ||
755 | INIT_WORK(&mp->rx_task, (void (*)(void *))mv643xx_eth_rx_task, dev); | 757 | INIT_WORK(&mp->rx_task, (void (*)(void *))mv643xx_eth_rx_task, dev); |
@@ -877,7 +879,7 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev) | |||
877 | struct sk_buff *skb; | 879 | struct sk_buff *skb; |
878 | 880 | ||
879 | /* Stop Tx Queues */ | 881 | /* Stop Tx Queues */ |
880 | mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00); | 882 | mv643xx_eth_port_disable_tx(port_num); |
881 | 883 | ||
882 | /* Free outstanding skb's on TX rings */ | 884 | /* Free outstanding skb's on TX rings */ |
883 | for (curr = 0; mp->tx_desc_count && curr < mp->tx_ring_size; curr++) { | 885 | for (curr = 0; mp->tx_desc_count && curr < mp->tx_ring_size; curr++) { |
@@ -907,7 +909,7 @@ static void mv643xx_eth_free_rx_rings(struct net_device *dev) | |||
907 | int curr; | 909 | int curr; |
908 | 910 | ||
909 | /* Stop RX Queues */ | 911 | /* Stop RX Queues */ |
910 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00); | 912 | mv643xx_eth_port_disable_rx(port_num); |
911 | 913 | ||
912 | /* Free preallocated skb's on RX rings */ | 914 | /* Free preallocated skb's on RX rings */ |
913 | for (curr = 0; mp->rx_desc_count && curr < mp->rx_ring_size; curr++) { | 915 | for (curr = 0; mp->rx_desc_count && curr < mp->rx_ring_size; curr++) { |
@@ -1719,13 +1721,6 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX"); | |||
1719 | * return_info Tx/Rx user resource return information. | 1721 | * return_info Tx/Rx user resource return information. |
1720 | */ | 1722 | */ |
1721 | 1723 | ||
1722 | /* defines */ | ||
1723 | /* SDMA command macros */ | ||
1724 | #define ETH_ENABLE_TX_QUEUE(eth_port) \ | ||
1725 | mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), 1) | ||
1726 | |||
1727 | /* locals */ | ||
1728 | |||
1729 | /* PHY routines */ | 1724 | /* PHY routines */ |
1730 | static int ethernet_phy_get(unsigned int eth_port_num); | 1725 | static int ethernet_phy_get(unsigned int eth_port_num); |
1731 | static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr); | 1726 | static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr); |
@@ -1759,9 +1754,6 @@ static void eth_port_set_filter_table_entry(int table, unsigned char entry); | |||
1759 | */ | 1754 | */ |
1760 | static void eth_port_init(struct mv643xx_private *mp) | 1755 | static void eth_port_init(struct mv643xx_private *mp) |
1761 | { | 1756 | { |
1762 | mp->port_rx_queue_command = 0; | ||
1763 | mp->port_tx_queue_command = 0; | ||
1764 | |||
1765 | mp->rx_resource_err = 0; | 1757 | mp->rx_resource_err = 0; |
1766 | mp->tx_resource_err = 0; | 1758 | mp->tx_resource_err = 0; |
1767 | 1759 | ||
@@ -1842,8 +1834,7 @@ static void eth_port_start(struct net_device *dev) | |||
1842 | mp->port_sdma_config); | 1834 | mp->port_sdma_config); |
1843 | 1835 | ||
1844 | /* Enable port Rx. */ | 1836 | /* Enable port Rx. */ |
1845 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), | 1837 | mv643xx_eth_port_enable_rx(port_num, mp->port_rx_queue_command); |
1846 | mp->port_rx_queue_command); | ||
1847 | 1838 | ||
1848 | /* Disable port bandwidth limits by clearing MTU register */ | 1839 | /* Disable port bandwidth limits by clearing MTU register */ |
1849 | mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); | 1840 | mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); |
@@ -2320,6 +2311,67 @@ static void ethernet_phy_reset(unsigned int eth_port_num) | |||
2320 | eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data); | 2311 | eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data); |
2321 | } | 2312 | } |
2322 | 2313 | ||
2314 | static void mv643xx_eth_port_enable_tx(unsigned int port_num, | ||
2315 | unsigned int channels) | ||
2316 | { | ||
2317 | mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), channels); | ||
2318 | } | ||
2319 | |||
2320 | static void mv643xx_eth_port_enable_rx(unsigned int port_num, | ||
2321 | unsigned int channels) | ||
2322 | { | ||
2323 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), channels); | ||
2324 | } | ||
2325 | |||
2326 | static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num) | ||
2327 | { | ||
2328 | u32 channels; | ||
2329 | |||
2330 | /* Stop Tx port activity. Check port Tx activity. */ | ||
2331 | channels = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)) | ||
2332 | & 0xFF; | ||
2333 | if (channels) { | ||
2334 | /* Issue stop command for active channels only */ | ||
2335 | mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), | ||
2336 | (channels << 8)); | ||
2337 | |||
2338 | /* Wait for all Tx activity to terminate. */ | ||
2339 | /* Check port cause register that all Tx queues are stopped */ | ||
2340 | while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)) | ||
2341 | & 0xFF) | ||
2342 | udelay(PHY_WAIT_MICRO_SECONDS); | ||
2343 | |||
2344 | /* Wait for Tx FIFO to empty */ | ||
2345 | while (mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num)) & | ||
2346 | ETH_PORT_TX_FIFO_EMPTY) | ||
2347 | udelay(PHY_WAIT_MICRO_SECONDS); | ||
2348 | } | ||
2349 | |||
2350 | return channels; | ||
2351 | } | ||
2352 | |||
2353 | static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num) | ||
2354 | { | ||
2355 | u32 channels; | ||
2356 | |||
2357 | /* Stop Rx port activity. Check port Rx activity. */ | ||
2358 | channels = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num) | ||
2359 | & 0xFF); | ||
2360 | if (channels) { | ||
2361 | /* Issue stop command for active channels only */ | ||
2362 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), | ||
2363 | (channels << 8)); | ||
2364 | |||
2365 | /* Wait for all Rx activity to terminate. */ | ||
2366 | /* Check port cause register that all Rx queues are stopped */ | ||
2367 | while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num)) | ||
2368 | & 0xFF) | ||
2369 | udelay(PHY_WAIT_MICRO_SECONDS); | ||
2370 | } | ||
2371 | |||
2372 | return channels; | ||
2373 | } | ||
2374 | |||
2323 | /* | 2375 | /* |
2324 | * eth_port_reset - Reset Ethernet port | 2376 | * eth_port_reset - Reset Ethernet port |
2325 | * | 2377 | * |
@@ -2342,35 +2394,8 @@ static void eth_port_reset(unsigned int port_num) | |||
2342 | { | 2394 | { |
2343 | unsigned int reg_data; | 2395 | unsigned int reg_data; |
2344 | 2396 | ||
2345 | /* Stop Tx port activity. Check port Tx activity. */ | 2397 | mv643xx_eth_port_disable_tx(port_num); |
2346 | reg_data = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)); | 2398 | mv643xx_eth_port_disable_rx(port_num); |
2347 | |||
2348 | if (reg_data & 0xFF) { | ||
2349 | /* Issue stop command for active channels only */ | ||
2350 | mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), | ||
2351 | (reg_data << 8)); | ||
2352 | |||
2353 | /* Wait for all Tx activity to terminate. */ | ||
2354 | /* Check port cause register that all Tx queues are stopped */ | ||
2355 | while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)) | ||
2356 | & 0xFF) | ||
2357 | udelay(10); | ||
2358 | } | ||
2359 | |||
2360 | /* Stop Rx port activity. Check port Rx activity. */ | ||
2361 | reg_data = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num)); | ||
2362 | |||
2363 | if (reg_data & 0xFF) { | ||
2364 | /* Issue stop command for active channels only */ | ||
2365 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), | ||
2366 | (reg_data << 8)); | ||
2367 | |||
2368 | /* Wait for all Rx activity to terminate. */ | ||
2369 | /* Check port cause register that all Rx queues are stopped */ | ||
2370 | while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num)) | ||
2371 | & 0xFF) | ||
2372 | udelay(10); | ||
2373 | } | ||
2374 | 2399 | ||
2375 | /* Clear all MIB counters */ | 2400 | /* Clear all MIB counters */ |
2376 | eth_clear_mib_counters(port_num); | 2401 | eth_clear_mib_counters(port_num); |
@@ -2599,7 +2624,7 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
2599 | first_descriptor->cmd_sts = mp->tx_first_command; | 2624 | first_descriptor->cmd_sts = mp->tx_first_command; |
2600 | 2625 | ||
2601 | wmb(); | 2626 | wmb(); |
2602 | ETH_ENABLE_TX_QUEUE(mp->port_num); | 2627 | mv643xx_eth_port_enable_tx(mp->port_num, mp->port_tx_queue_command); |
2603 | 2628 | ||
2604 | /* | 2629 | /* |
2605 | * Finish Tx packet. Update first desc in case of Tx resource | 2630 | * Finish Tx packet. Update first desc in case of Tx resource |
@@ -2652,7 +2677,7 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
2652 | ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT; | 2677 | ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT; |
2653 | 2678 | ||
2654 | wmb(); | 2679 | wmb(); |
2655 | ETH_ENABLE_TX_QUEUE(mp->port_num); | 2680 | mv643xx_eth_port_enable_tx(mp->port_num, mp->port_tx_queue_command); |
2656 | 2681 | ||
2657 | /* Finish Tx packet. Update first desc in case of Tx resource error */ | 2682 | /* Finish Tx packet. Update first desc in case of Tx resource error */ |
2658 | tx_desc_curr = (tx_desc_curr + 1) % mp->tx_ring_size; | 2683 | tx_desc_curr = (tx_desc_curr + 1) % mp->tx_ring_size; |