]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/net/b44.c
net: wireless: sd8797: Marvell sd8797 Wi-Fi driver
[linux-2.6.git] / drivers / net / b44.c
index bafca672ea7d7d2857bc52b17bfe051cea8b4716..41ea84e3f69c60fc9785254a254bd14ecfea1da7 100644 (file)
@@ -5,11 +5,13 @@
  * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
  * Copyright (C) 2006 Felix Fietkau (nbd@openwrt.org)
  * Copyright (C) 2006 Broadcom Corporation.
- * Copyright (C) 2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2007 Michael Buesch <m@bues.ch>
  *
  * Distribute under GPL.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/ssb/ssb.h>
+#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -34,8 +38,8 @@
 #include "b44.h"
 
 #define DRV_MODULE_NAME                "b44"
-#define PFX DRV_MODULE_NAME    ": "
 #define DRV_MODULE_VERSION     "2.0"
+#define DRV_DESCRIPTION                "Broadcom 44xx/47xx 10/100 PCI ethernet driver"
 
 #define B44_DEF_MSG_ENABLE       \
        (NETIF_MSG_DRV          | \
 #define B44_ETHIPV6UDP_HLEN    62
 #define B44_ETHIPV4UDP_HLEN    42
 
-static char version[] __devinitdata =
-       DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION "\n";
-
 MODULE_AUTHOR("Felix Fietkau, Florian Schirmer, Pekka Pietikainen, David S. Miller");
-MODULE_DESCRIPTION("Broadcom 44xx/47xx 10/100 PCI ethernet driver");
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
@@ -102,7 +103,7 @@ MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value");
 
 
 #ifdef CONFIG_B44_PCI
-static const struct pci_device_id b44_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(b44_pci_tbl) = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B0) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1) },
@@ -133,7 +134,6 @@ static void b44_init_rings(struct b44 *);
 
 static void b44_init_hw(struct b44 *, int);
 
-static int dma_desc_align_mask;
 static int dma_desc_sync_size;
 static int instance;
 
@@ -148,9 +148,8 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev,
                                                unsigned long offset,
                                                enum dma_data_direction dir)
 {
-       ssb_dma_sync_single_range_for_device(sdev, dma_base,
-                                            offset & dma_desc_align_mask,
-                                            dma_desc_sync_size, dir);
+       dma_sync_single_for_device(sdev->dma_dev, dma_base + offset,
+                                  dma_desc_sync_size, dir);
 }
 
 static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
@@ -158,9 +157,8 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
                                             unsigned long offset,
                                             enum dma_data_direction dir)
 {
-       ssb_dma_sync_single_range_for_cpu(sdev, dma_base,
-                                         offset & dma_desc_align_mask,
-                                         dma_desc_sync_size, dir);
+       dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset,
+                               dma_desc_sync_size, dir);
 }
 
 static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
@@ -189,11 +187,10 @@ static int b44_wait_bit(struct b44 *bp, unsigned long reg,
                udelay(10);
        }
        if (i == timeout) {
-               printk(KERN_ERR PFX "%s: BUG!  Timeout waiting for bit %08x of register "
-                      "%lx to %s.\n",
-                      bp->dev->name,
-                      bit, reg,
-                      (clear ? "clear" : "set"));
+               if (net_ratelimit())
+                       netdev_err(bp->dev, "BUG!  Timeout waiting for bit %08x of register %lx to %s\n",
+                                  bit, reg, clear ? "clear" : "set");
+
                return -ENODEV;
        }
        return 0;
@@ -333,13 +330,12 @@ static int b44_phy_reset(struct b44 *bp)
        err = b44_readphy(bp, MII_BMCR, &val);
        if (!err) {
                if (val & BMCR_RESET) {
-                       printk(KERN_ERR PFX "%s: PHY Reset would not complete.\n",
-                              bp->dev->name);
+                       netdev_err(bp->dev, "PHY Reset would not complete\n");
                        err = -ENODEV;
                }
        }
 
-       return 0;
+       return err;
 }
 
 static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags)
@@ -384,11 +380,11 @@ static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
        __b44_set_flow_ctrl(bp, pause_enab);
 }
 
-#ifdef SSB_DRIVER_MIPS
-extern char *nvram_get(char *name);
+#ifdef CONFIG_BCM47XX
+#include <asm/mach-bcm47xx/nvram.h>
 static void b44_wap54g10_workaround(struct b44 *bp)
 {
-       const char *str;
+       char buf[20];
        u32 val;
        int err;
 
@@ -397,10 +393,9 @@ static void b44_wap54g10_workaround(struct b44 *bp)
         * see https://dev.openwrt.org/ticket/146
         * check and reset bit "isolate"
         */
-       str = nvram_get("boardnum");
-       if (!str)
+       if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
                return;
-       if (simple_strtoul(str, NULL, 0) == 2) {
+       if (simple_strtoul(buf, NULL, 0) == 2) {
                err = __b44_readphy(bp, 0, MII_BMCR, &val);
                if (err)
                        goto error;
@@ -413,7 +408,7 @@ static void b44_wap54g10_workaround(struct b44 *bp)
        }
        return;
 error:
-       printk(KERN_WARNING PFX "PHY: cannot reset MII transceiver isolate bit.\n");
+       pr_warning("PHY: cannot reset MII transceiver isolate bit\n");
 }
 #else
 static inline void b44_wap54g10_workaround(struct b44 *bp)
@@ -506,18 +501,15 @@ static void b44_stats_update(struct b44 *bp)
 static void b44_link_report(struct b44 *bp)
 {
        if (!netif_carrier_ok(bp->dev)) {
-               printk(KERN_INFO PFX "%s: Link is down.\n", bp->dev->name);
+               netdev_info(bp->dev, "Link is down\n");
        } else {
-               printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n",
-                      bp->dev->name,
-                      (bp->flags & B44_FLAG_100_BASE_T) ? 100 : 10,
-                      (bp->flags & B44_FLAG_FULL_DUPLEX) ? "full" : "half");
-
-               printk(KERN_INFO PFX "%s: Flow control is %s for TX and "
-                      "%s for RX.\n",
-                      bp->dev->name,
-                      (bp->flags & B44_FLAG_TX_PAUSE) ? "on" : "off",
-                      (bp->flags & B44_FLAG_RX_PAUSE) ? "on" : "off");
+               netdev_info(bp->dev, "Link is up at %d Mbps, %s duplex\n",
+                           (bp->flags & B44_FLAG_100_BASE_T) ? 100 : 10,
+                           (bp->flags & B44_FLAG_FULL_DUPLEX) ? "full" : "half");
+
+               netdev_info(bp->dev, "Flow control is %s for TX and %s for RX\n",
+                           (bp->flags & B44_FLAG_TX_PAUSE) ? "on" : "off",
+                           (bp->flags & B44_FLAG_RX_PAUSE) ? "on" : "off");
        }
 }
 
@@ -576,11 +568,9 @@ static void b44_check_phy(struct b44 *bp)
                }
 
                if (bmsr & BMSR_RFAULT)
-                       printk(KERN_WARNING PFX "%s: Remote fault detected in PHY\n",
-                              bp->dev->name);
+                       netdev_warn(bp->dev, "Remote fault detected in PHY\n");
                if (bmsr & BMSR_JCD)
-                       printk(KERN_WARNING PFX "%s: Jabber detected in PHY\n",
-                              bp->dev->name);
+                       netdev_warn(bp->dev, "Jabber detected in PHY\n");
        }
 }
 
@@ -613,12 +603,12 @@ static void b44_tx(struct b44 *bp)
 
                BUG_ON(skb == NULL);
 
-               ssb_dma_unmap_single(bp->sdev,
-                                    rp->mapping,
-                                    skb->len,
-                                    DMA_TO_DEVICE);
+               dma_unmap_single(bp->sdev->dma_dev,
+                                rp->mapping,
+                                skb->len,
+                                DMA_TO_DEVICE);
                rp->skb = NULL;
-               dev_kfree_skb_irq(skb);
+               dev_kfree_skb(skb);
        }
 
        bp->tx_cons = cons;
@@ -653,29 +643,29 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
        if (skb == NULL)
                return -ENOMEM;
 
-       mapping = ssb_dma_map_single(bp->sdev, skb->data,
-                                    RX_PKT_BUF_SZ,
-                                    DMA_FROM_DEVICE);
+       mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
+                                RX_PKT_BUF_SZ,
+                                DMA_FROM_DEVICE);
 
        /* Hardware bug work-around, the chip is unable to do PCI DMA
           to/from anything above 1GB :-( */
-       if (ssb_dma_mapping_error(bp->sdev, mapping) ||
+       if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
                mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
                /* Sigh... */
-               if (!ssb_dma_mapping_error(bp->sdev, mapping))
-                       ssb_dma_unmap_single(bp->sdev, mapping,
+               if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+                       dma_unmap_single(bp->sdev->dma_dev, mapping,
                                             RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
                dev_kfree_skb_any(skb);
                skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
                if (skb == NULL)
                        return -ENOMEM;
-               mapping = ssb_dma_map_single(bp->sdev, skb->data,
-                                            RX_PKT_BUF_SZ,
-                                            DMA_FROM_DEVICE);
-               if (ssb_dma_mapping_error(bp->sdev, mapping) ||
-                       mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
-                       if (!ssb_dma_mapping_error(bp->sdev, mapping))
-                               ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
+               mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
+                                        RX_PKT_BUF_SZ,
+                                        DMA_FROM_DEVICE);
+               if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
+                   mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
+                       if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+                               dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
                        dev_kfree_skb_any(skb);
                        return -ENOMEM;
                }
@@ -750,9 +740,9 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
                                             dest_idx * sizeof(*dest_desc),
                                             DMA_BIDIRECTIONAL);
 
-       ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping,
-                                      RX_PKT_BUF_SZ,
-                                      DMA_FROM_DEVICE);
+       dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping,
+                                  RX_PKT_BUF_SZ,
+                                  DMA_FROM_DEVICE);
 }
 
 static int b44_rx(struct b44 *bp, int budget)
@@ -772,9 +762,9 @@ static int b44_rx(struct b44 *bp, int budget)
                struct rx_header *rh;
                u16 len;
 
-               ssb_dma_sync_single_for_cpu(bp->sdev, map,
-                                           RX_PKT_BUF_SZ,
-                                           DMA_FROM_DEVICE);
+               dma_sync_single_for_cpu(bp->sdev->dma_dev, map,
+                                       RX_PKT_BUF_SZ,
+                                       DMA_FROM_DEVICE);
                rh = (struct rx_header *) skb->data;
                len = le16_to_cpu(rh->len);
                if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
@@ -806,8 +796,8 @@ static int b44_rx(struct b44 *bp, int budget)
                        skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
                        if (skb_size < 0)
                                goto drop_it;
-                       ssb_dma_unmap_single(bp->sdev, map,
-                                            skb_size, DMA_FROM_DEVICE);
+                       dma_unmap_single(bp->sdev->dma_dev, map,
+                                        skb_size, DMA_FROM_DEVICE);
                        /* Leave out rx_header */
                        skb_put(skb, len + RX_PKT_OFFSET);
                        skb_pull(skb, RX_PKT_OFFSET);
@@ -815,7 +805,7 @@ static int b44_rx(struct b44 *bp, int budget)
                        struct sk_buff *copy_skb;
 
                        b44_recycle_rx(bp, cons, bp->rx_prod);
-                       copy_skb = dev_alloc_skb(len + 2);
+                       copy_skb = netdev_alloc_skb(bp->dev, len + 2);
                        if (copy_skb == NULL)
                                goto drop_it_no_recycle;
 
@@ -826,7 +816,7 @@ static int b44_rx(struct b44 *bp, int budget)
                                                         copy_skb->data, len);
                        skb = copy_skb;
                }
-               skb->ip_summed = CHECKSUM_NONE;
+               skb_checksum_none_assert(skb);
                skb->protocol = eth_type_trans(skb, bp->dev);
                netif_receive_skb(skb);
                received++;
@@ -847,23 +837,31 @@ static int b44_poll(struct napi_struct *napi, int budget)
 {
        struct b44 *bp = container_of(napi, struct b44, napi);
        int work_done;
+       unsigned long flags;
 
-       spin_lock_irq(&bp->lock);
+       spin_lock_irqsave(&bp->lock, flags);
 
        if (bp->istat & (ISTAT_TX | ISTAT_TO)) {
                /* spin_lock(&bp->tx_lock); */
                b44_tx(bp);
                /* spin_unlock(&bp->tx_lock); */
        }
-       spin_unlock_irq(&bp->lock);
+       if (bp->istat & ISTAT_RFO) {    /* fast recovery, in ~20msec */
+               bp->istat &= ~ISTAT_RFO;
+               b44_disable_ints(bp);
+               ssb_device_enable(bp->sdev, 0); /* resets ISTAT_RFO */
+               b44_init_rings(bp);
+               b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
+               netif_wake_queue(bp->dev);
+       }
+
+       spin_unlock_irqrestore(&bp->lock, flags);
 
        work_done = 0;
        if (bp->istat & ISTAT_RX)
                work_done += b44_rx(bp, budget);
 
        if (bp->istat & ISTAT_ERRORS) {
-               unsigned long flags;
-
                spin_lock_irqsave(&bp->lock, flags);
                b44_halt(bp);
                b44_init_rings(bp);
@@ -902,7 +900,7 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id)
                handled = 1;
 
                if (unlikely(!netif_running(dev))) {
-                       printk(KERN_INFO "%s: late interrupt.\n", dev->name);
+                       netdev_info(dev, "late interrupt\n");
                        goto irq_ack;
                }
 
@@ -913,9 +911,6 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id)
                        bp->istat = istat;
                        __b44_disable_ints(bp);
                        __napi_schedule(&bp->napi);
-               } else {
-                       printk(KERN_ERR PFX "%s: Error, poll already scheduled\n",
-                              dev->name);
                }
 
 irq_ack:
@@ -930,8 +925,7 @@ static void b44_tx_timeout(struct net_device *dev)
 {
        struct b44 *bp = netdev_priv(dev);
 
-       printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
-              dev->name);
+       netdev_err(dev, "transmit timed out, resetting\n");
 
        spin_lock_irq(&bp->lock);
 
@@ -946,7 +940,7 @@ static void b44_tx_timeout(struct net_device *dev)
        netif_wake_queue(dev);
 }
 
-static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct b44 *bp = netdev_priv(dev);
        int rc = NETDEV_TX_OK;
@@ -960,29 +954,28 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* This is a hard error, log it. */
        if (unlikely(TX_BUFFS_AVAIL(bp) < 1)) {
                netif_stop_queue(dev);
-               printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
-                      dev->name);
+               netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
                goto err_out;
        }
 
-       mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE);
-       if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
+       mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
+       if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
                struct sk_buff *bounce_skb;
 
                /* Chip can't handle DMA to/from >1GB, use bounce buffer */
-               if (!ssb_dma_mapping_error(bp->sdev, mapping))
-                       ssb_dma_unmap_single(bp->sdev, mapping, len,
+               if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+                       dma_unmap_single(bp->sdev->dma_dev, mapping, len,
                                             DMA_TO_DEVICE);
 
                bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA);
                if (!bounce_skb)
                        goto err_out;
 
-               mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data,
-                                            len, DMA_TO_DEVICE);
-               if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
-                       if (!ssb_dma_mapping_error(bp->sdev, mapping))
-                               ssb_dma_unmap_single(bp->sdev, mapping,
+               mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data,
+                                        len, DMA_TO_DEVICE);
+               if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
+                       if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+                               dma_unmap_single(bp->sdev->dma_dev, mapping,
                                                     len, DMA_TO_DEVICE);
                        dev_kfree_skb_any(bounce_skb);
                        goto err_out;
@@ -1025,8 +1018,6 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (TX_BUFFS_AVAIL(bp) < 1)
                netif_stop_queue(dev);
 
-       dev->trans_start = jiffies;
-
 out_unlock:
        spin_unlock_irqrestore(&bp->lock, flags);
 
@@ -1081,8 +1072,8 @@ static void b44_free_rings(struct b44 *bp)
 
                if (rp->skb == NULL)
                        continue;
-               ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ,
-                                    DMA_FROM_DEVICE);
+               dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ,
+                                DMA_FROM_DEVICE);
                dev_kfree_skb_any(rp->skb);
                rp->skb = NULL;
        }
@@ -1093,8 +1084,8 @@ static void b44_free_rings(struct b44 *bp)
 
                if (rp->skb == NULL)
                        continue;
-               ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len,
-                                    DMA_TO_DEVICE);
+               dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len,
+                                DMA_TO_DEVICE);
                dev_kfree_skb_any(rp->skb);
                rp->skb = NULL;
        }
@@ -1116,14 +1107,12 @@ static void b44_init_rings(struct b44 *bp)
        memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
 
        if (bp->flags & B44_FLAG_RX_RING_HACK)
-               ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma,
-                                              DMA_TABLE_BYTES,
-                                              DMA_BIDIRECTIONAL);
+               dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma,
+                                          DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
 
        if (bp->flags & B44_FLAG_TX_RING_HACK)
-               ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma,
-                                              DMA_TABLE_BYTES,
-                                              DMA_TO_DEVICE);
+               dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma,
+                                          DMA_TABLE_BYTES, DMA_TO_DEVICE);
 
        for (i = 0; i < bp->rx_pending; i++) {
                if (b44_alloc_rx_skb(bp, -1, i) < 0)
@@ -1143,27 +1132,23 @@ static void b44_free_consistent(struct b44 *bp)
        bp->tx_buffers = NULL;
        if (bp->rx_ring) {
                if (bp->flags & B44_FLAG_RX_RING_HACK) {
-                       ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma,
-                                            DMA_TABLE_BYTES,
-                                            DMA_BIDIRECTIONAL);
+                       dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma,
+                                        DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
                        kfree(bp->rx_ring);
                } else
-                       ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
-                                               bp->rx_ring, bp->rx_ring_dma,
-                                               GFP_KERNEL);
+                       dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
+                                         bp->rx_ring, bp->rx_ring_dma);
                bp->rx_ring = NULL;
                bp->flags &= ~B44_FLAG_RX_RING_HACK;
        }
        if (bp->tx_ring) {
                if (bp->flags & B44_FLAG_TX_RING_HACK) {
-                       ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma,
-                                            DMA_TABLE_BYTES,
-                                            DMA_TO_DEVICE);
+                       dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma,
+                                        DMA_TABLE_BYTES, DMA_TO_DEVICE);
                        kfree(bp->tx_ring);
                } else
-                       ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
-                                               bp->tx_ring, bp->tx_ring_dma,
-                                               GFP_KERNEL);
+                       dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
+                                         bp->tx_ring, bp->tx_ring_dma);
                bp->tx_ring = NULL;
                bp->flags &= ~B44_FLAG_TX_RING_HACK;
        }
@@ -1188,7 +1173,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
                goto out_err;
 
        size = DMA_TABLE_BYTES;
-       bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp);
+       bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
+                                        &bp->rx_ring_dma, gfp);
        if (!bp->rx_ring) {
                /* Allocation may have failed due to pci_alloc_consistent
                   insisting on use of GFP_DMA, which is more restrictive
@@ -1200,11 +1186,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
                if (!rx_ring)
                        goto out_err;
 
-               rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring,
-                                                DMA_TABLE_BYTES,
-                                                DMA_BIDIRECTIONAL);
+               rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring,
+                                            DMA_TABLE_BYTES,
+                                            DMA_BIDIRECTIONAL);
 
-               if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) ||
+               if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) ||
                        rx_ring_dma + size > DMA_BIT_MASK(30)) {
                        kfree(rx_ring);
                        goto out_err;
@@ -1215,7 +1201,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
                bp->flags |= B44_FLAG_RX_RING_HACK;
        }
 
-       bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp);
+       bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
+                                        &bp->tx_ring_dma, gfp);
        if (!bp->tx_ring) {
                /* Allocation may have failed due to ssb_dma_alloc_consistent
                   insisting on use of GFP_DMA, which is more restrictive
@@ -1227,11 +1214,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
                if (!tx_ring)
                        goto out_err;
 
-               tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring,
-                                           DMA_TABLE_BYTES,
-                                           DMA_TO_DEVICE);
+               tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring,
+                                            DMA_TABLE_BYTES,
+                                            DMA_TO_DEVICE);
 
-               if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) ||
+               if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) ||
                        tx_ring_dma + size > DMA_BIT_MASK(30)) {
                        kfree(tx_ring);
                        goto out_err;
@@ -1298,14 +1285,18 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind)
        switch (sdev->bus->bustype) {
        case SSB_BUSTYPE_SSB:
                bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
-                    (((ssb_clockspeed(sdev->bus) + (B44_MDC_RATIO / 2)) / B44_MDC_RATIO)
+                    (DIV_ROUND_CLOSEST(ssb_clockspeed(sdev->bus),
+                                       B44_MDC_RATIO)
                     & MDIO_CTRL_MAXF_MASK)));
                break;
        case SSB_BUSTYPE_PCI:
-       case SSB_BUSTYPE_PCMCIA:
                bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
                     (0x0d & MDIO_CTRL_MAXF_MASK)));
                break;
+       case SSB_BUSTYPE_PCMCIA:
+       case SSB_BUSTYPE_SDIO:
+               WARN_ON(1); /* A device with this bus does not exist. */
+               break;
        }
 
        br32(bp, B44_MDIO_CTRL);
@@ -1333,7 +1324,7 @@ static void b44_halt(struct b44 *bp)
        /* reset PHY */
        b44_phy_reset(bp);
        /* power down PHY */
-       printk(KERN_INFO PFX "%s: powering down PHY\n", bp->dev->name);
+       netdev_info(bp->dev, "powering down PHY\n");
        bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);
        /* now reset the chip, but without enabling the MAC&PHY
         * part of it. This has to be done _after_ we shut down the PHY */
@@ -1505,8 +1496,7 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
                for (k = 0; k< ethaddr_bytes; k++) {
                        ppattern[offset + magicsync +
                                (j * ETH_ALEN) + k] = macaddr[k];
-                       len++;
-                       set_bit(len, (unsigned long *) pmask);
+                       set_bit(len++, (unsigned long *) pmask);
                }
        }
        return len - 1;
@@ -1525,7 +1515,7 @@ static void b44_setup_pseudo_magicp(struct b44 *bp)
 
        pwol_pattern = kzalloc(B44_PATTERN_SIZE, GFP_KERNEL);
        if (!pwol_pattern) {
-               printk(KERN_ERR PFX "Memory not available for WOL\n");
+               pr_err("Memory not available for WOL\n");
                return;
        }
 
@@ -1689,13 +1679,15 @@ static struct net_device_stats *b44_get_stats(struct net_device *dev)
 
 static int __b44_load_mcast(struct b44 *bp, struct net_device *dev)
 {
-       struct dev_mc_list *mclist;
+       struct netdev_hw_addr *ha;
        int i, num_ents;
 
-       num_ents = min_t(int, dev->mc_count, B44_MCAST_TABLE_SIZE);
-       mclist = dev->mc_list;
-       for (i = 0; mclist && i < num_ents; i++, mclist = mclist->next) {
-               __b44_cam_write(bp, mclist->dmi_addr, i + 1);
+       num_ents = min_t(int, netdev_mc_count(dev), B44_MCAST_TABLE_SIZE);
+       i = 0;
+       netdev_for_each_mc_addr(ha, dev) {
+               if (i == num_ents)
+                       break;
+               __b44_cam_write(bp, ha->addr, i++ + 1);
        }
        return i+1;
 }
@@ -1717,7 +1709,7 @@ static void __b44_set_rx_mode(struct net_device *dev)
                __b44_set_mac_addr(bp);
 
                if ((dev->flags & IFF_ALLMULTI) ||
-                   (dev->mc_count > B44_MCAST_TABLE_SIZE))
+                   (netdev_mc_count(dev) > B44_MCAST_TABLE_SIZE))
                        val |= RXCONFIG_ALLMULTI;
                else
                        i = __b44_load_mcast(bp, dev);
@@ -1757,15 +1749,18 @@ static void b44_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *inf
        struct b44 *bp = netdev_priv(dev);
        struct ssb_bus *bus = bp->sdev->bus;
 
-       strncpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-       strncpy(info->version, DRV_MODULE_VERSION, sizeof(info->driver));
+       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
        switch (bus->bustype) {
        case SSB_BUSTYPE_PCI:
-               strncpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info));
+               strlcpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info));
                break;
-       case SSB_BUSTYPE_PCMCIA:
        case SSB_BUSTYPE_SSB:
-               strncpy(info->bus_info, "SSB", sizeof(info->bus_info));
+               strlcpy(info->bus_info, "SSB", sizeof(info->bus_info));
+               break;
+       case SSB_BUSTYPE_PCMCIA:
+       case SSB_BUSTYPE_SDIO:
+               WARN_ON(1); /* A device with this bus does not exist. */
                break;
        }
 }
@@ -1811,8 +1806,8 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        if (bp->flags & B44_FLAG_ADV_100FULL)
                cmd->advertising |= ADVERTISED_100baseT_Full;
        cmd->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
-       cmd->speed = (bp->flags & B44_FLAG_100_BASE_T) ?
-               SPEED_100 : SPEED_10;
+       ethtool_cmd_speed_set(cmd, ((bp->flags & B44_FLAG_100_BASE_T) ?
+                                   SPEED_100 : SPEED_10));
        cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
                DUPLEX_FULL : DUPLEX_HALF;
        cmd->port = 0;
@@ -1824,7 +1819,7 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        if (cmd->autoneg == AUTONEG_ENABLE)
                cmd->advertising |= ADVERTISED_Autoneg;
        if (!netif_running(dev)){
-               cmd->speed = 0;
+               ethtool_cmd_speed_set(cmd, 0);
                cmd->duplex = 0xff;
        }
        cmd->maxtxpkt = 0;
@@ -1835,6 +1830,7 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct b44 *bp = netdev_priv(dev);
+       u32 speed = ethtool_cmd_speed(cmd);
 
        /* We do not support gigabit. */
        if (cmd->autoneg == AUTONEG_ENABLE) {
@@ -1842,8 +1838,8 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                    (ADVERTISED_1000baseT_Half |
                     ADVERTISED_1000baseT_Full))
                        return -EINVAL;
-       } else if ((cmd->speed != SPEED_100 &&
-                   cmd->speed != SPEED_10) ||
+       } else if ((speed != SPEED_100 &&
+                   speed != SPEED_10) ||
                   (cmd->duplex != DUPLEX_HALF &&
                    cmd->duplex != DUPLEX_FULL)) {
                        return -EINVAL;
@@ -1877,7 +1873,7 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        } else {
                bp->flags |= B44_FLAG_FORCE_LINK;
                bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX);
-               if (cmd->speed == SPEED_100)
+               if (speed == SPEED_100)
                        bp->flags |= B44_FLAG_100_BASE_T;
                if (cmd->duplex == DUPLEX_FULL)
                        bp->flags |= B44_FLAG_FULL_DUPLEX;
@@ -2095,7 +2091,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
        memcpy(bp->dev->dev_addr, addr, 6);
 
        if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){
-               printk(KERN_ERR PFX "Invalid MAC address found in EEPROM\n");
+               pr_err("Invalid MAC address found in EEPROM\n");
                return -EINVAL;
        }
 
@@ -2132,20 +2128,17 @@ static const struct net_device_ops b44_netdev_ops = {
 static int __devinit b44_init_one(struct ssb_device *sdev,
                                  const struct ssb_device_id *ent)
 {
-       static int b44_version_printed = 0;
        struct net_device *dev;
        struct b44 *bp;
        int err;
 
        instance++;
 
-       if (b44_version_printed++ == 0)
-               printk(KERN_INFO "%s", version);
-
+       pr_info_once("%s version %s\n", DRV_DESCRIPTION, DRV_MODULE_VERSION);
 
        dev = alloc_etherdev(sizeof(*bp));
        if (!dev) {
-               dev_err(sdev->dev, "Etherdev alloc failed, aborting.\n");
+               dev_err(sdev->dev, "Etherdev alloc failed, aborting\n");
                err = -ENOMEM;
                goto out;
        }
@@ -2173,24 +2166,24 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
        dev->irq = sdev->irq;
        SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
 
-       netif_carrier_off(dev);
-
        err = ssb_bus_powerup(sdev->bus, 0);
        if (err) {
                dev_err(sdev->dev,
                        "Failed to powerup the bus\n");
                goto err_out_free_dev;
        }
-       err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30));
-       if (err) {
+
+       if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) ||
+           dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) {
                dev_err(sdev->dev,
-                       "Required 30BIT DMA mask unsupported by the system.\n");
+                       "Required 30BIT DMA mask unsupported by the system\n");
                goto err_out_powerdown;
        }
+
        err = b44_get_invariants(bp);
        if (err) {
                dev_err(sdev->dev,
-                       "Problem fetching invariants of chip, aborting.\n");
+                       "Problem fetching invariants of chip, aborting\n");
                goto err_out_powerdown;
        }
 
@@ -2210,10 +2203,12 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
 
        err = register_netdev(dev);
        if (err) {
-               dev_err(sdev->dev, "Cannot register net device, aborting.\n");
+               dev_err(sdev->dev, "Cannot register net device, aborting\n");
                goto err_out_powerdown;
        }
 
+       netif_carrier_off(dev);
+
        ssb_set_drvdata(sdev, dev);
 
        /* Chip reset provides power to the b44 MAC & PCI cores, which
@@ -2221,8 +2216,11 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
         */
        b44_chip_reset(bp, B44_CHIP_RESET_FULL);
 
-       printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n",
-              dev->name, dev->dev_addr);
+       /* do a phy reset to test if there is an active phy */
+       if (b44_phy_reset(bp) < 0)
+               bp->phy_addr = B44_PHY_ADDR_NO_PHY;
+
+       netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
 
        return 0;
 
@@ -2293,18 +2291,27 @@ static int b44_resume(struct ssb_device *sdev)
        if (!netif_running(dev))
                return 0;
 
+       spin_lock_irq(&bp->lock);
+       b44_init_rings(bp);
+       b44_init_hw(bp, B44_FULL_RESET);
+       spin_unlock_irq(&bp->lock);
+
+       /*
+        * As a shared interrupt, the handler can be called immediately. To be
+        * able to check the interrupt status the hardware must already be
+        * powered back on (b44_init_hw).
+        */
        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);
+               netdev_err(dev, "request_irq failed\n");
+               spin_lock_irq(&bp->lock);
+               b44_halt(bp);
+               b44_free_rings(bp);
+               spin_unlock_irq(&bp->lock);
                return rc;
        }
 
-       spin_lock_irq(&bp->lock);
-
-       b44_init_rings(bp);
-       b44_init_hw(bp, B44_FULL_RESET);
        netif_device_attach(bp->dev);
-       spin_unlock_irq(&bp->lock);
 
        b44_enable_ints(bp);
        netif_wake_queue(dev);
@@ -2323,7 +2330,7 @@ static struct ssb_driver b44_ssb_driver = {
        .resume         = b44_resume,
 };
 
-static inline int b44_pci_init(void)
+static inline int __init b44_pci_init(void)
 {
        int err = 0;
 #ifdef CONFIG_B44_PCI
@@ -2332,7 +2339,7 @@ static inline int b44_pci_init(void)
        return err;
 }
 
-static inline void b44_pci_exit(void)
+static inline void __exit b44_pci_exit(void)
 {
 #ifdef CONFIG_B44_PCI
        ssb_pcihost_unregister(&b44_pci_driver);
@@ -2345,7 +2352,6 @@ static int __init b44_init(void)
        int err;
 
        /* Setup paramaters for syncing RX/TX DMA descriptors */
-       dma_desc_align_mask = ~(dma_desc_align_size - 1);
        dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
 
        err = b44_pci_init();