Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / net / wireless / p54 / p54pci.c
index 88b3cad..57c6465 100644 (file)
 #include <net/mac80211.h>
 
 #include "p54.h"
+#include "lmac.h"
 #include "p54pci.h"
 
 MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
 MODULE_DESCRIPTION("Prism54 PCI wireless driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("prism54pci");
+MODULE_FIRMWARE("isl3886pci");
 
-static struct pci_device_id p54p_table[] __devinitdata = {
+static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
        /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
        { PCI_DEVICE(0x1260, 0x3890) },
        /* 3COM 3CRWE154G72 Wireless LAN adapter */
@@ -46,7 +48,6 @@ MODULE_DEVICE_TABLE(pci, p54p_table);
 static int p54p_upload_firmware(struct ieee80211_hw *dev)
 {
        struct p54p_priv *priv = dev->priv;
-       const struct firmware *fw_entry = NULL;
        __le32 reg;
        int err;
        __le32 *data;
@@ -72,21 +73,21 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
        P54P_WRITE(ctrl_stat, reg);
        wmb();
 
-       err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
-       if (err) {
-               printk(KERN_ERR "%s (p54pci): cannot find firmware "
-                      "(isl3886)\n", pci_name(priv->pdev));
-               return err;
-       }
+       /* wait for the firmware to reset properly */
+       mdelay(10);
 
-       err = p54_parse_firmware(dev, fw_entry);
-       if (err) {
-               release_firmware(fw_entry);
+       err = p54_parse_firmware(dev, priv->firmware);
+       if (err)
                return err;
+
+       if (priv->common.fw_interface != FW_LM86) {
+               dev_err(&priv->pdev->dev, "wrong firmware, "
+                       "please get a LM86(PCI) firmware a try again.\n");
+               return -EINVAL;
        }
 
-       data = (__le32 *) fw_entry->data;
-       remains = fw_entry->size;
+       data = (__le32 *) priv->firmware->data;
+       remains = priv->firmware->size;
        device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
        while (remains) {
                u32 i = 0;
@@ -104,8 +105,6 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
                P54P_READ(int_enable);
        }
 
-       release_firmware(fw_entry);
-
        reg = P54P_READ(ctrl_stat);
        reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
        reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
@@ -198,6 +197,14 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
                        i %= ring_limit;
                        continue;
                }
+
+               if (unlikely(len > priv->common.rx_mtu)) {
+                       if (net_ratelimit())
+                               dev_err(&priv->pdev->dev, "rx'd frame size "
+                                       "exceeds length threshold.\n");
+
+                       len = priv->common.rx_mtu;
+               }
                skb_put(skb, len);
 
                if (p54_rx(dev, skb)) {
@@ -235,7 +242,9 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
 
        while (i != idx) {
                desc = &ring[i];
-               kfree(tx_buf[i]);
+               if (tx_buf[i])
+                       if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i]))
+                               p54_free_skb(dev, tx_buf[i]);
                tx_buf[i] = NULL;
 
                pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
@@ -306,8 +315,7 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
        return reg ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-                   size_t len, int free_on_tx)
+static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
        struct p54p_priv *priv = dev->priv;
        struct p54p_ring_control *ring_control = priv->ring_control;
@@ -322,28 +330,21 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
        idx = le32_to_cpu(ring_control->host_idx[1]);
        i = idx % ARRAY_SIZE(ring_control->tx_data);
 
-       mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
+       priv->tx_buf_data[i] = skb;
+       mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+                                PCI_DMA_TODEVICE);
        desc = &ring_control->tx_data[i];
        desc->host_addr = cpu_to_le32(mapping);
-       desc->device_addr = data->req_id;
-       desc->len = cpu_to_le16(len);
+       desc->device_addr = ((struct p54_hdr *)skb->data)->req_id;
+       desc->len = cpu_to_le16(skb->len);
        desc->flags = 0;
 
        wmb();
        ring_control->host_idx[1] = cpu_to_le32(idx + 1);
-
-       if (free_on_tx)
-               priv->tx_buf_data[i] = data;
-
        spin_unlock_irqrestore(&priv->lock, flags);
 
        P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
        P54P_READ(dev_int);
-
-       /* FIXME: unlikely to happen because the device usually runs out of
-          memory before we fill the ring up, but we can make it impossible */
-       if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
-               printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
 }
 
 static void p54p_stop(struct ieee80211_hw *dev)
@@ -393,7 +394,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
                                         le16_to_cpu(desc->len),
                                         PCI_DMA_TODEVICE);
 
-               kfree(priv->tx_buf_data[i]);
+               p54_free_skb(dev, priv->tx_buf_data[i]);
                priv->tx_buf_data[i] = NULL;
        }
 
@@ -405,7 +406,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
                                         le16_to_cpu(desc->len),
                                         PCI_DMA_TODEVICE);
 
-               kfree(priv->tx_buf_mgmt[i]);
+               p54_free_skb(dev, priv->tx_buf_mgmt[i]);
                priv->tx_buf_mgmt[i] = NULL;
        }
 
@@ -418,11 +419,10 @@ static int p54p_open(struct ieee80211_hw *dev)
        int err;
 
        init_completion(&priv->boot_comp);
-       err = request_irq(priv->pdev->irq, &p54p_interrupt,
+       err = request_irq(priv->pdev->irq, p54p_interrupt,
                          IRQF_SHARED, "p54pci", dev);
        if (err) {
-               printk(KERN_ERR "%s: failed to register IRQ handler\n",
-                      wiphy_name(dev->wiphy));
+               dev_err(&priv->pdev->dev, "failed to register IRQ handler\n");
                return err;
        }
 
@@ -481,35 +481,29 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
        struct ieee80211_hw *dev;
        unsigned long mem_addr, mem_len;
        int err;
-       DECLARE_MAC_BUF(mac);
 
        err = pci_enable_device(pdev);
        if (err) {
-               printk(KERN_ERR "%s (p54pci): Cannot enable new PCI device\n",
-                      pci_name(pdev));
+               dev_err(&pdev->dev, "Cannot enable new PCI device\n");
                return err;
        }
 
        mem_addr = pci_resource_start(pdev, 0);
        mem_len = pci_resource_len(pdev, 0);
        if (mem_len < sizeof(struct p54p_csr)) {
-               printk(KERN_ERR "%s (p54pci): Too short PCI resources\n",
-                      pci_name(pdev));
-               pci_disable_device(pdev);
-               return err;
+               dev_err(&pdev->dev, "Too short PCI resources\n");
+               goto err_disable_dev;
        }
 
        err = pci_request_regions(pdev, "p54pci");
        if (err) {
-               printk(KERN_ERR "%s (p54pci): Cannot obtain PCI resources\n",
-                      pci_name(pdev));
-               return err;
+               dev_err(&pdev->dev, "Cannot obtain PCI resources\n");
+               goto err_disable_dev;
        }
 
-       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
-           pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
-               printk(KERN_ERR "%s (p54pci): No suitable DMA available\n",
-                      pci_name(pdev));
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) ||
+           pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               dev_err(&pdev->dev, "No suitable DMA available\n");
                goto err_free_reg;
        }
 
@@ -521,8 +515,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
 
        dev = p54_init_common(sizeof(*priv));
        if (!dev) {
-               printk(KERN_ERR "%s (p54pci): ieee80211 alloc failed\n",
-                      pci_name(pdev));
+               dev_err(&pdev->dev, "ieee80211 alloc failed\n");
                err = -ENOMEM;
                goto err_free_reg;
        }
@@ -535,17 +528,15 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
 
        priv->map = ioremap(mem_addr, mem_len);
        if (!priv->map) {
-               printk(KERN_ERR "%s (p54pci): Cannot map device memory\n",
-                      pci_name(pdev));
-               err = -EINVAL;  // TODO: use a better error code?
+               dev_err(&pdev->dev, "Cannot map device memory\n");
+               err = -ENOMEM;
                goto err_free_dev;
        }
 
        priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control),
                                                  &priv->ring_control_dma);
        if (!priv->ring_control) {
-               printk(KERN_ERR "%s (p54pci): Cannot allocate rings\n",
-                      pci_name(pdev));
+               dev_err(&pdev->dev, "Cannot allocate rings\n");
                err = -ENOMEM;
                goto err_iounmap;
        }
@@ -556,6 +547,16 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
        spin_lock_init(&priv->lock);
        tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev);
 
+       err = request_firmware(&priv->firmware, "isl3886pci",
+                              &priv->pdev->dev);
+       if (err) {
+               dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n");
+               err = request_firmware(&priv->firmware, "isl3886",
+                                      &priv->pdev->dev);
+               if (err)
+                       goto err_free_common;
+       }
+
        err = p54p_open(dev);
        if (err)
                goto err_free_common;
@@ -564,17 +565,14 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
        if (err)
                goto err_free_common;
 
-       err = ieee80211_register_hw(dev);
-       if (err) {
-               printk(KERN_ERR "%s (p54pci): Cannot register netdevice\n",
-                      pci_name(pdev));
+       err = p54_register_common(dev, &pdev->dev);
+       if (err)
                goto err_free_common;
-       }
 
        return 0;
 
  err_free_common:
-       p54_free_common(dev);
+       release_firmware(priv->firmware);
        pci_free_consistent(pdev, sizeof(*priv->ring_control),
                            priv->ring_control, priv->ring_control_dma);
 
@@ -583,10 +581,11 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
 
  err_free_dev:
        pci_set_drvdata(pdev, NULL);
-       ieee80211_free_hw(dev);
+       p54_free_common(dev);
 
  err_free_reg:
        pci_release_regions(pdev);
+ err_disable_dev:
        pci_disable_device(pdev);
        return err;
 }
@@ -599,15 +598,15 @@ static void __devexit p54p_remove(struct pci_dev *pdev)
        if (!dev)
                return;
 
-       ieee80211_unregister_hw(dev);
+       p54_unregister_common(dev);
        priv = dev->priv;
+       release_firmware(priv->firmware);
        pci_free_consistent(pdev, sizeof(*priv->ring_control),
                            priv->ring_control, priv->ring_control_dma);
-       p54_free_common(dev);
        iounmap(priv->map);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
-       ieee80211_free_hw(dev);
+       p54_free_common(dev);
 }
 
 #ifdef CONFIG_PM