Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / drivers / net / mv643xx_eth.c
index 9f26613..eeab1df 100644 (file)
@@ -281,10 +281,16 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
 {
        struct mv643xx_private *mp = netdev_priv(dev);
 
-       netif_device_detach(dev);
+       if (!netif_running(dev))
+               return;
+
+       netif_stop_queue(dev);
+
        eth_port_reset(mp->port_num);
        eth_port_start(dev);
-       netif_device_attach(dev);
+
+       if (mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB)
+               netif_wake_queue(dev);
 }
 
 /**
@@ -379,6 +385,8 @@ static int mv643xx_eth_receive_queue(struct net_device *dev, int budget)
        struct pkt_info pkt_info;
 
        while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) {
+               dma_unmap_single(NULL, pkt_info.buf_ptr, RX_SKB_SIZE,
+                                                       DMA_FROM_DEVICE);
                mp->rx_desc_count--;
                received_packets++;
 
@@ -552,9 +560,9 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
 #else
        if (eth_int_cause & ETH_INT_CAUSE_RX)
                mv643xx_eth_receive_queue(dev, INT_MAX);
+#endif
        if (eth_int_cause_ext & ETH_INT_CAUSE_TX)
                mv643xx_eth_free_completed_tx_descs(dev);
-#endif
 
        /*
         * If no real interrupt occured, exit.
@@ -772,7 +780,7 @@ static int mv643xx_eth_open(struct net_device *dev)
        int err;
 
        err = request_irq(dev->irq, mv643xx_eth_int_handler,
-                       SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+                       IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev);
        if (err) {
                printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
                                                                port_num);
@@ -1186,10 +1194,15 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        BUG_ON(netif_queue_stopped(dev));
        BUG_ON(skb == NULL);
-       BUG_ON(mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB);
+
+       if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
+               printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
+               netif_stop_queue(dev);
+               return 1;
+       }
 
        if (has_tiny_unaligned_frags(skb)) {
-               if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
+               if (__skb_linearize(skb)) {
                        stats->tx_dropped++;
                        printk(KERN_DEBUG "%s: failed to linearize tiny "
                                        "unaligned fragment\n", dev->name);
@@ -1408,6 +1421,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        mv643xx_eth_update_pscr(dev, &cmd);
        mv643xx_set_settings(dev, &cmd);
 
+       SET_MODULE_OWNER(dev);
+       SET_NETDEV_DEV(dev, &pdev->dev);
        err = register_netdev(dev);
        if (err)
                goto out;