Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh...
[pandora-kernel.git] / drivers / net / b44.c
index 1ec2174..aaada57 100644 (file)
@@ -59,7 +59,6 @@
 #define B44_DEF_TX_RING_PENDING                (B44_TX_RING_SIZE - 1)
 #define B44_TX_RING_BYTES      (sizeof(struct dma_desc) * \
                                 B44_TX_RING_SIZE)
-#define B44_DMA_MASK 0x3fffffff
 
 #define TX_RING_GAP(BP)        \
        (B44_TX_RING_SIZE - (BP)->tx_pending)
@@ -110,6 +109,11 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl);
 
 static void b44_halt(struct b44 *);
 static void b44_init_rings(struct b44 *);
+
+#define B44_FULL_RESET         1
+#define B44_FULL_RESET_SKIP_PHY        2
+#define B44_PARTIAL_RESET      3
+
 static void b44_init_hw(struct b44 *, int);
 
 static int dma_desc_align_mask;
@@ -660,7 +664,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
        /* Hardware bug work-around, the chip is unable to do PCI DMA
           to/from anything above 1GB :-( */
        if (dma_mapping_error(mapping) ||
-               mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+               mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
                /* Sigh... */
                if (!dma_mapping_error(mapping))
                        pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
@@ -672,7 +676,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
                                         RX_PKT_BUF_SZ,
                                         PCI_DMA_FROMDEVICE);
                if (dma_mapping_error(mapping) ||
-                       mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+                       mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
                        if (!dma_mapping_error(mapping))
                                pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
                        dev_kfree_skb_any(skb);
@@ -716,7 +720,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
        struct ring_info *src_map, *dest_map;
        struct rx_header *rh;
        int dest_idx;
-       u32 ctrl;
+       __le32 ctrl;
 
        dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
        dest_desc = &bp->rx_ring[dest_idx];
@@ -752,7 +756,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
                                             dest_idx * sizeof(dest_desc),
                                             DMA_BIDIRECTIONAL);
 
-       pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
+       pci_dma_sync_single_for_device(bp->pdev, le32_to_cpu(src_desc->addr),
                                       RX_PKT_BUF_SZ,
                                       PCI_DMA_FROMDEVICE);
 }
@@ -778,7 +782,7 @@ static int b44_rx(struct b44 *bp, int budget)
                                            RX_PKT_BUF_SZ,
                                            PCI_DMA_FROMDEVICE);
                rh = (struct rx_header *) skb->data;
-               len = cpu_to_le16(rh->len);
+               len = le16_to_cpu(rh->len);
                if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
                    (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
                drop_it:
@@ -794,7 +798,7 @@ static int b44_rx(struct b44 *bp, int budget)
                        do {
                                udelay(2);
                                barrier();
-                               len = cpu_to_le16(rh->len);
+                               len = le16_to_cpu(rh->len);
                        } while (len == 0 && i++ < 5);
                        if (len == 0)
                                goto drop_it;
@@ -879,12 +883,14 @@ static int b44_poll(struct net_device *netdev, int *budget)
        }
 
        if (bp->istat & ISTAT_ERRORS) {
-               spin_lock_irq(&bp->lock);
+               unsigned long flags;
+
+               spin_lock_irqsave(&bp->lock, flags);
                b44_halt(bp);
                b44_init_rings(bp);
-               b44_init_hw(bp, 1);
+               b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
                netif_wake_queue(bp->dev);
-               spin_unlock_irq(&bp->lock);
+               spin_unlock_irqrestore(&bp->lock, flags);
                done = 1;
        }
 
@@ -908,8 +914,9 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id)
        istat = br32(bp, B44_ISTAT);
        imask = br32(bp, B44_IMASK);
 
-       /* ??? What the fuck is the purpose of the interrupt mask
-        * ??? register if we have to mask it out by hand anyways?
+       /* The interrupt mask register controls which interrupt bits
+        * will actually raise an interrupt to the CPU when set by hw/firmware,
+        * but doesn't mask off the bits.
         */
        istat &= imask;
        if (istat) {
@@ -951,7 +958,7 @@ static void b44_tx_timeout(struct net_device *dev)
 
        b44_halt(bp);
        b44_init_rings(bp);
-       b44_init_hw(bp, 1);
+       b44_init_hw(bp, B44_FULL_RESET);
 
        spin_unlock_irq(&bp->lock);
 
@@ -980,7 +987,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
-       if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+       if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
                /* Chip can't handle DMA to/from >1GB, use bounce buffer */
                if (!dma_mapping_error(mapping))
                        pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
@@ -992,7 +999,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                mapping = pci_map_single(bp->pdev, bounce_skb->data,
                                         len, PCI_DMA_TODEVICE);
-               if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+               if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
                        if (!dma_mapping_error(mapping))
                                pci_unmap_single(bp->pdev, mapping,
                                         len, PCI_DMA_TODEVICE);
@@ -1068,7 +1075,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
        b44_halt(bp);
        dev->mtu = new_mtu;
        b44_init_rings(bp);
-       b44_init_hw(bp, 1);
+       b44_init_hw(bp, B44_FULL_RESET);
        spin_unlock_irq(&bp->lock);
 
        b44_enable_ints(bp);
@@ -1219,7 +1226,7 @@ static int b44_alloc_consistent(struct b44 *bp)
                                             DMA_BIDIRECTIONAL);
 
                if (dma_mapping_error(rx_ring_dma) ||
-                       rx_ring_dma + size > B44_DMA_MASK) {
+                       rx_ring_dma + size > DMA_30BIT_MASK) {
                        kfree(rx_ring);
                        goto out_err;
                }
@@ -1246,7 +1253,7 @@ static int b44_alloc_consistent(struct b44 *bp)
                                             DMA_TO_DEVICE);
 
                if (dma_mapping_error(tx_ring_dma) ||
-                       tx_ring_dma + size > B44_DMA_MASK) {
+                       tx_ring_dma + size > DMA_30BIT_MASK) {
                        kfree(tx_ring);
                        goto out_err;
                }
@@ -1281,7 +1288,7 @@ static void b44_chip_reset(struct b44 *bp)
        if (ssb_is_core_up(bp)) {
                bw32(bp, B44_RCV_LAZY, 0);
                bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
-               b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1);
+               b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
                bw32(bp, B44_DMATX_CTRL, 0);
                bp->tx_prod = bp->tx_cons = 0;
                if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK) {
@@ -1365,12 +1372,12 @@ static int b44_set_mac_addr(struct net_device *dev, void *p)
  * packet processing.  Invoked with bp->lock held.
  */
 static void __b44_set_rx_mode(struct net_device *);
-static void b44_init_hw(struct b44 *bp, int full_reset)
+static void b44_init_hw(struct b44 *bp, int reset_kind)
 {
        u32 val;
 
        b44_chip_reset(bp);
-       if (full_reset) {
+       if (reset_kind == B44_FULL_RESET) {
                b44_phy_reset(bp);
                b44_setup_phy(bp);
        }
@@ -1387,7 +1394,10 @@ static void b44_init_hw(struct b44 *bp, int full_reset)
        bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
 
        bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
-       if (full_reset) {
+       if (reset_kind == B44_PARTIAL_RESET) {
+               bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+                                     (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+       } else {
                bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
                bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
                bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
@@ -1398,9 +1408,6 @@ static void b44_init_hw(struct b44 *bp, int full_reset)
                bp->rx_prod = bp->rx_pending;
 
                bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
-       } else {
-               bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-                                     (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
        }
 
        val = br32(bp, B44_ENET_CTRL);
@@ -1417,7 +1424,7 @@ static int b44_open(struct net_device *dev)
                goto out;
 
        b44_init_rings(bp);
-       b44_init_hw(bp, 1);
+       b44_init_hw(bp, B44_FULL_RESET);
 
        b44_check_phy(bp);
 
@@ -1626,7 +1633,7 @@ static int b44_close(struct net_device *dev)
        netif_poll_enable(dev);
 
        if (bp->flags & B44_FLAG_WOL_ENABLE) {
-               b44_init_hw(bp, 0);
+               b44_init_hw(bp, B44_PARTIAL_RESET);
                b44_setup_wol(bp);
        }
 
@@ -1902,7 +1909,7 @@ static int b44_set_ringparam(struct net_device *dev,
 
        b44_halt(bp);
        b44_init_rings(bp);
-       b44_init_hw(bp, 1);
+       b44_init_hw(bp, B44_FULL_RESET);
        netif_wake_queue(bp->dev);
        spin_unlock_irq(&bp->lock);
 
@@ -1945,7 +1952,7 @@ static int b44_set_pauseparam(struct net_device *dev,
        if (bp->flags & B44_FLAG_PAUSE_AUTO) {
                b44_halt(bp);
                b44_init_rings(bp);
-               b44_init_hw(bp, 1);
+               b44_init_hw(bp, B44_FULL_RESET);
        } else {
                __b44_set_flow_ctrl(bp, bp->flags);
        }
@@ -2053,7 +2060,7 @@ out:
 static int b44_read_eeprom(struct b44 *bp, u8 *data)
 {
        long i;
-       u16 *ptr = (u16 *) data;
+       __le16 *ptr = (__le16 *) data;
 
        for (i = 0; i < 128; i += 2)
                ptr[i / 2] = cpu_to_le16(readw(bp->regs + 4096 + i));
@@ -2143,13 +2150,13 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
 
        pci_set_master(pdev);
 
-       err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
+       err = pci_set_dma_mask(pdev, (u64) DMA_30BIT_MASK);
        if (err) {
                dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
                goto err_out_free_res;
        }
 
-       err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
+       err = pci_set_consistent_dma_mask(pdev, (u64) DMA_30BIT_MASK);
        if (err) {
                dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
                goto err_out_free_res;
@@ -2301,7 +2308,7 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
 
        free_irq(dev->irq, dev);
        if (bp->flags & B44_FLAG_WOL_ENABLE) {
-               b44_init_hw(bp, 0);
+               b44_init_hw(bp, B44_PARTIAL_RESET);
                b44_setup_wol(bp);
        }
        pci_disable_device(pdev);
@@ -2312,21 +2319,32 @@ static int b44_resume(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct b44 *bp = netdev_priv(dev);
+       int rc = 0;
 
        pci_restore_state(pdev);
-       pci_enable_device(pdev);
+       rc = pci_enable_device(pdev);
+       if (rc) {
+               printk(KERN_ERR PFX "%s: pci_enable_device failed\n",
+                       dev->name);
+               return rc;
+       }
+
        pci_set_master(pdev);
 
        if (!netif_running(dev))
                return 0;
 
-       if (request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev))
+       rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
+       if (rc) {
                printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name);
+               pci_disable_device(pdev);
+               return rc;
+       }
 
        spin_lock_irq(&bp->lock);
 
        b44_init_rings(bp);
-       b44_init_hw(bp, 1);
+       b44_init_hw(bp, B44_FULL_RESET);
        netif_device_attach(bp->dev);
        spin_unlock_irq(&bp->lock);