Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Mon, 16 Aug 2010 18:40:44 +0000 (14:40 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 16 Aug 2010 18:40:44 +0000 (14:40 -0400)
16 files changed:
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwmc3200wifi/rx.c
drivers/net/wireless/p54/fwio.c
drivers/net/wireless/rt2x00/rt2x00firmware.c
drivers/net/wireless/rtl818x/rtl8180_dev.c
drivers/net/wireless/rtl818x/rtl8187_dev.c
drivers/net/wireless/zd1211rw/zd_chip.c
include/net/mac80211.h
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/wireless/reg.c

index 20631ae..a3e2f2b 100644 (file)
@@ -2280,6 +2280,7 @@ out:
 
 static int b43_upload_microcode(struct b43_wldev *dev)
 {
+       struct wiphy *wiphy = dev->wl->hw->wiphy;
        const size_t hdr_len = sizeof(struct b43_fw_header);
        const __be32 *data;
        unsigned int i, len;
@@ -2405,6 +2406,10 @@ static int b43_upload_microcode(struct b43_wldev *dev)
                }
        }
 
+       snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
+                       dev->fw.rev, dev->fw.patch);
+       wiphy->hw_version = dev->dev->id.coreid;
+
        if (b43_is_old_txhdr_format(dev)) {
                /* We're over the deadline, but we keep support for old fw
                 * until it turns out to be in major conflict with something new. */
@@ -4250,6 +4255,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
        B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED);
        if (!dev || b43_status(dev) != B43_STAT_INITIALIZED)
                return;
+
+       /* Unregister HW RNG driver */
+       b43_rng_exit(dev->wl);
+
        b43_set_status(dev, B43_STAT_UNINIT);
 
        /* Stop the microcode PSM. */
@@ -4379,6 +4388,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 
        b43_set_status(dev, B43_STAT_INITIALIZED);
 
+       /* Register HW RNG driver */
+       b43_rng_init(dev->wl);
+
 out:
        return err;
 
@@ -4984,7 +4996,6 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id)
                if (err)
                        goto err_one_core_detach;
                b43_leds_register(wl->current_dev);
-               b43_rng_init(wl);
        }
 
       out:
@@ -5020,7 +5031,6 @@ static void b43_remove(struct ssb_device *dev)
        b43_one_core_detach(dev);
 
        if (list_empty(&wl->devlist)) {
-               b43_rng_exit(wl);
                b43_leds_unregister(wl);
                /* Last core on the chip unregistered.
                 * We can destroy common struct b43_wl.
index 1713f5f..67f18ec 100644 (file)
@@ -1623,6 +1623,7 @@ error:
 
 static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 {
+       struct wiphy *wiphy = dev->wl->hw->wiphy;
        const size_t hdr_len = sizeof(struct b43legacy_fw_header);
        const __be32 *data;
        unsigned int i;
@@ -1732,6 +1733,10 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
        dev->fw.rev = fwrev;
        dev->fw.patch = fwpatch;
 
+       snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
+                       dev->fw.rev, dev->fw.patch);
+       wiphy->hw_version = dev->dev->id.coreid;
+
        return 0;
 
 error:
index 1189dbb..0c3963d 100644 (file)
@@ -3064,9 +3064,9 @@ static void ipw2100_tx_send_commands(struct ipw2100_priv *priv)
 
                packet = list_entry(element, struct ipw2100_tx_packet, list);
 
-               IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n",
+               IPW_DEBUG_TX("using TBD at virt=%p, phys=%04X\n",
                             &txq->drv[txq->next],
-                            (void *)(txq->nic + txq->next *
+                            (u32) (txq->nic + txq->next *
                                      sizeof(struct ipw2100_bd)));
 
                packet->index = txq->next;
index c1882fd..d3de509 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -3925,6 +3926,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /**************************
         * 2. Initializing PCI bus
         **************************/
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                               PCIE_LINK_STATE_CLKPM);
+
        if (pci_enable_device(pdev)) {
                err = -ENODEV;
                goto out_ieee80211_free_hw;
index 70c4b8f..bb955d2 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -3960,6 +3961,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        /***************************
         * 2. Initializing PCI bus
         * *************************/
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                               PCIE_LINK_STATE_CLKPM);
+
        if (pci_enable_device(pdev)) {
                err = -ENODEV;
                goto out_ieee80211_free_hw;
index c02fced..a944893 100644 (file)
@@ -1195,11 +1195,8 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
        IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
                    "oid is 0x%x\n", hdr->oid);
 
-       if (hdr->oid <= WIFI_IF_NTFY_MAX) {
-               set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
-               wake_up_interruptible(&iwm->wifi_ntfy_queue);
-       } else
-               return -EINVAL;
+       set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
+       wake_up_interruptible(&iwm->wifi_ntfy_queue);
 
        switch (hdr->oid) {
        case UMAC_WIFI_IF_CMD_SET_PROFILE:
index 47006bc..6f027ab 100644 (file)
@@ -123,10 +123,14 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
                bootrec = (struct bootrec *)&bootrec->data[len];
        }
 
-       if (fw_version)
+       if (fw_version) {
                wiphy_info(priv->hw->wiphy,
                           "fw rev %s - softmac protocol %x.%x\n",
                           fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
+               snprintf(dev->wiphy->fw_version, sizeof(dev->wiphy->fw_version),
+                               "%s - %x.%x", fw_version,
+                               priv->fw_var >> 8, priv->fw_var & 0xff);
+       }
 
        if (priv->fw_var < 0x500)
                wiphy_info(priv->hw->wiphy,
index b818a43..f0e1eb7 100644 (file)
@@ -63,6 +63,9 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
 
        INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
             fw->data[fw->size - 4], fw->data[fw->size - 3]);
+       snprintf(rt2x00dev->hw->wiphy->fw_version,
+                       sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",
+                       fw->data[fw->size - 4], fw->data[fw->size - 3]);
 
        retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size);
        switch (retval) {
index b50c39a..9544eb1 100644 (file)
@@ -99,19 +99,66 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
        }
 }
 
-static void rtl8180_handle_rx(struct ieee80211_hw *dev)
+static void rtl8180_handle_tx(struct ieee80211_hw *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
-       unsigned int count = 32;
+       struct rtl8180_tx_ring *ring;
+       int prio;
+
+       spin_lock(&priv->lock);
+
+       for (prio = 3; prio >= 0; prio--) {
+               ring = &priv->tx_ring[prio];
+
+               while (skb_queue_len(&ring->queue)) {
+                       struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
+                       struct sk_buff *skb;
+                       struct ieee80211_tx_info *info;
+                       u32 flags = le32_to_cpu(entry->flags);
+
+                       if (flags & RTL818X_TX_DESC_FLAG_OWN)
+                               break;
+
+                       ring->idx = (ring->idx + 1) % ring->entries;
+                       skb = __skb_dequeue(&ring->queue);
+                       pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
+                                        skb->len, PCI_DMA_TODEVICE);
+
+                       info = IEEE80211_SKB_CB(skb);
+                       ieee80211_tx_info_clear_status(info);
+
+                       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+                           (flags & RTL818X_TX_DESC_FLAG_TX_OK))
+                               info->flags |= IEEE80211_TX_STAT_ACK;
+
+                       info->status.rates[0].count = (flags & 0xFF) + 1;
+                       info->status.rates[1].idx = -1;
+
+                       ieee80211_tx_status(dev, skb);
+                       if (ring->entries - skb_queue_len(&ring->queue) == 2)
+                               ieee80211_wake_queue(dev, prio);
+               }
+       }
+
+       spin_unlock(&priv->lock);
+}
+
+static int rtl8180_poll(struct ieee80211_hw *dev, int budget)
+{
+       struct rtl8180_priv *priv = dev->priv;
+       unsigned int count = 0;
        u8 signal, agc, sq;
 
-       while (count--) {
+       /* handle pending Tx queue cleanup */
+       rtl8180_handle_tx(dev);
+
+       while (count++ < budget) {
                struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
                struct sk_buff *skb = priv->rx_buf[priv->rx_idx];
                u32 flags = le32_to_cpu(entry->flags);
 
                if (flags & RTL818X_RX_DESC_FLAG_OWN)
-                       return;
+                       break;
 
                if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL |
                                      RTL818X_RX_DESC_FLAG_FOF |
@@ -151,7 +198,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
                                rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
 
                        memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
-                       ieee80211_rx_irqsafe(dev, skb);
+                       ieee80211_rx(dev, skb);
 
                        skb = new_skb;
                        priv->rx_buf[priv->rx_idx] = skb;
@@ -168,41 +215,16 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
                        entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
                priv->rx_idx = (priv->rx_idx + 1) % 32;
        }
-}
 
-static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
-{
-       struct rtl8180_priv *priv = dev->priv;
-       struct rtl8180_tx_ring *ring = &priv->tx_ring[prio];
+       if (count < budget) {
+               /* disable polling */
+               ieee80211_napi_complete(dev);
 
-       while (skb_queue_len(&ring->queue)) {
-               struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
-               struct sk_buff *skb;
-               struct ieee80211_tx_info *info;
-               u32 flags = le32_to_cpu(entry->flags);
-
-               if (flags & RTL818X_TX_DESC_FLAG_OWN)
-                       return;
-
-               ring->idx = (ring->idx + 1) % ring->entries;
-               skb = __skb_dequeue(&ring->queue);
-               pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
-                                skb->len, PCI_DMA_TODEVICE);
-
-               info = IEEE80211_SKB_CB(skb);
-               ieee80211_tx_info_clear_status(info);
-
-               if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
-                   (flags & RTL818X_TX_DESC_FLAG_TX_OK))
-                       info->flags |= IEEE80211_TX_STAT_ACK;
-
-               info->status.rates[0].count = (flags & 0xFF) + 1;
-               info->status.rates[1].idx = -1;
-
-               ieee80211_tx_status_irqsafe(dev, skb);
-               if (ring->entries - skb_queue_len(&ring->queue) == 2)
-                       ieee80211_wake_queue(dev, prio);
+               /* enable interrupts */
+               rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
        }
+
+       return count;
 }
 
 static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
@@ -211,31 +233,17 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
        struct rtl8180_priv *priv = dev->priv;
        u16 reg;
 
-       spin_lock(&priv->lock);
        reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS);
-       if (unlikely(reg == 0xFFFF)) {
-               spin_unlock(&priv->lock);
+       if (unlikely(reg == 0xFFFF))
                return IRQ_HANDLED;
-       }
 
        rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg);
 
-       if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR))
-               rtl8180_handle_tx(dev, 3);
-
-       if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR))
-               rtl8180_handle_tx(dev, 2);
-
-       if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR))
-               rtl8180_handle_tx(dev, 1);
-
-       if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR))
-               rtl8180_handle_tx(dev, 0);
-
-       if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR))
-               rtl8180_handle_rx(dev);
+       /* disable interrupts */
+       rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
 
-       spin_unlock(&priv->lock);
+       /* enable polling */
+       ieee80211_napi_schedule(dev);
 
        return IRQ_HANDLED;
 }
@@ -247,7 +255,6 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
        struct rtl8180_priv *priv = dev->priv;
        struct rtl8180_tx_ring *ring;
        struct rtl8180_tx_desc *entry;
-       unsigned long flags;
        unsigned int idx, prio;
        dma_addr_t mapping;
        u32 tx_flags;
@@ -294,7 +301,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
                        plcp_len |= 1 << 15;
        }
 
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock(&priv->lock);
 
        if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
                if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
@@ -318,7 +325,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
        if (ring->entries - skb_queue_len(&ring->queue) < 2)
                ieee80211_stop_queue(dev, prio);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock(&priv->lock);
 
        rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4)));
 
@@ -783,6 +790,7 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
        struct rtl8180_priv *priv = dev->priv;
        struct rtl8180_vif *vif_priv;
        int i;
+       u8 reg;
 
        vif_priv = (struct rtl8180_vif *)&vif->drv_priv;
 
@@ -791,12 +799,14 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
                        rtl818x_iowrite8(priv, &priv->map->BSSID[i],
                                         info->bssid[i]);
 
-               if (is_valid_ether_addr(info->bssid))
-                       rtl818x_iowrite8(priv, &priv->map->MSR,
-                                        RTL818X_MSR_INFRA);
-               else
-                       rtl818x_iowrite8(priv, &priv->map->MSR,
-                                        RTL818X_MSR_NO_LINK);
+               if (is_valid_ether_addr(info->bssid)) {
+                       if (vif->type == NL80211_IFTYPE_ADHOC)
+                               reg = RTL818X_MSR_ADHOC;
+                       else
+                               reg = RTL818X_MSR_INFRA;
+               } else
+                       reg = RTL818X_MSR_NO_LINK;
+               rtl818x_iowrite8(priv, &priv->map->MSR, reg);
        }
 
        if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp)
@@ -861,6 +871,7 @@ static const struct ieee80211_ops rtl8180_ops = {
        .prepare_multicast      = rtl8180_prepare_multicast,
        .configure_filter       = rtl8180_configure_filter,
        .get_tsf                = rtl8180_get_tsf,
+       .napi_poll              = rtl8180_poll,
 };
 
 static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom)
@@ -992,6 +1003,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
        dev->queues = 1;
        dev->max_signal = 65;
 
+       dev->napi_weight = 64;
+
        reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
        reg &= RTL818X_TX_CONF_HWVER_MASK;
        switch (reg) {
index 5738a55..0801c1d 100644 (file)
@@ -1176,13 +1176,12 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
                else
                        reg = 0;
 
-               if (is_valid_ether_addr(info->bssid)) {
+               if (is_valid_ether_addr(info->bssid))
                        reg |= RTL818X_MSR_INFRA;
-                       rtl818x_iowrite8(priv, &priv->map->MSR, reg);
-               } else {
+               else
                        reg |= RTL818X_MSR_NO_LINK;
-                       rtl818x_iowrite8(priv, &priv->map->MSR, reg);
-               }
+
+               rtl818x_iowrite8(priv, &priv->map->MSR, reg);
 
                mutex_unlock(&priv->conf_mutex);
        }
index b2af3c5..87a95bc 100644 (file)
@@ -973,6 +973,7 @@ static void dump_fw_registers(struct zd_chip *chip)
 
 static int print_fw_version(struct zd_chip *chip)
 {
+       struct wiphy *wiphy = zd_chip_to_mac(chip)->hw->wiphy;
        int r;
        u16 version;
 
@@ -982,6 +983,10 @@ static int print_fw_version(struct zd_chip *chip)
                return r;
 
        dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version);
+
+       snprintf(wiphy->fw_version, sizeof(wiphy->fw_version),
+                       "%04hx", version);
+
        return 0;
 }
 
index b0787a1..3f1e03b 100644 (file)
@@ -1102,6 +1102,10 @@ enum ieee80211_hw_flags {
  *
  * @max_rates: maximum number of alternate rate retry stages
  * @max_rate_tries: maximum number of tries for each stage
+ *
+ * @napi_weight: weight used for NAPI polling.  You must specify an
+ *     appropriate value here if a napi_poll operation is provided
+ *     by your driver.
  */
 struct ieee80211_hw {
        struct ieee80211_conf conf;
@@ -1113,6 +1117,7 @@ struct ieee80211_hw {
        int channel_change_time;
        int vif_data_size;
        int sta_data_size;
+       int napi_weight;
        u16 queues;
        u16 max_listen_interval;
        s8 max_signal;
@@ -1687,6 +1692,8 @@ enum ieee80211_ampdu_mlme_action {
  *     switch operation for CSAs received from the AP may implement this
  *     callback. They must then call ieee80211_chswitch_done() to indicate
  *     completion of the channel switch.
+ *
+ * @napi_poll: Poll Rx queue for incoming data frames.
  */
 struct ieee80211_ops {
        int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1752,6 +1759,7 @@ struct ieee80211_ops {
        void (*flush)(struct ieee80211_hw *hw, bool drop);
        void (*channel_switch)(struct ieee80211_hw *hw,
                               struct ieee80211_channel_switch *ch_switch);
+       int (*napi_poll)(struct ieee80211_hw *hw, int budget);
 };
 
 /**
@@ -1897,6 +1905,22 @@ void ieee80211_free_hw(struct ieee80211_hw *hw);
  */
 void ieee80211_restart_hw(struct ieee80211_hw *hw);
 
+/** ieee80211_napi_schedule - schedule NAPI poll
+ *
+ * Use this function to schedule NAPI polling on a device.
+ *
+ * @hw: the hardware to start polling
+ */
+void ieee80211_napi_schedule(struct ieee80211_hw *hw);
+
+/** ieee80211_napi_complete - complete NAPI polling
+ *
+ * Use this function to finish NAPI polling on a device.
+ *
+ * @hw: the hardware to stop polling
+ */
+void ieee80211_napi_complete(struct ieee80211_hw *hw);
+
 /**
  * ieee80211_rx - receive frame
  *
index 65e0ed6..79d5645 100644 (file)
@@ -870,6 +870,11 @@ struct ieee80211_local {
                struct dentry *keys;
        } debugfs;
 #endif
+
+       /* dummy netdev for use w/ NAPI */
+       struct net_device napi_dev;
+
+       struct napi_struct napi;
 };
 
 static inline struct ieee80211_sub_if_data *
index ebbe264..c1008a9 100644 (file)
@@ -187,6 +187,8 @@ static int ieee80211_open(struct net_device *dev)
                res = drv_start(local);
                if (res)
                        goto err_del_bss;
+               if (local->ops->napi_poll)
+                       napi_enable(&local->napi);
                /* we're brought up, everything changes */
                hw_reconf_flags = ~0;
                ieee80211_led_radio(local, true);
@@ -519,6 +521,8 @@ static int ieee80211_stop(struct net_device *dev)
        ieee80211_recalc_ps(local, -1);
 
        if (local->open_count == 0) {
+               if (local->ops->napi_poll)
+                       napi_disable(&local->napi);
                ieee80211_clear_tx_pending(local);
                ieee80211_stop_device(local);
 
index 798a91b..1ed956c 100644 (file)
@@ -390,6 +390,30 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
 }
 #endif
 
+static int ieee80211_napi_poll(struct napi_struct *napi, int budget)
+{
+       struct ieee80211_local *local =
+               container_of(napi, struct ieee80211_local, napi);
+
+       return local->ops->napi_poll(&local->hw, budget);
+}
+
+void ieee80211_napi_schedule(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       napi_schedule(&local->napi);
+}
+EXPORT_SYMBOL(ieee80211_napi_schedule);
+
+void ieee80211_napi_complete(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       napi_complete(&local->napi);
+}
+EXPORT_SYMBOL(ieee80211_napi_complete);
+
 struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
                                        const struct ieee80211_ops *ops)
 {
@@ -494,6 +518,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        skb_queue_head_init(&local->skb_queue);
        skb_queue_head_init(&local->skb_queue_unreliable);
 
+       /* init dummy netdev for use w/ NAPI */
+       init_dummy_netdev(&local->napi_dev);
+
        return local_to_hw(local);
 }
 EXPORT_SYMBOL(ieee80211_alloc_hw);
@@ -683,6 +710,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                goto fail_ifa;
 #endif
 
+       netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
+                       local->hw.napi_weight);
+
        return 0;
 
 #ifdef CONFIG_INET
index f180db0..b0d9a08 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/random.h>
+#include <linux/ctype.h>
 #include <linux/nl80211.h>
 #include <linux/platform_device.h>
 #include <net/cfg80211.h>
@@ -181,14 +182,6 @@ static bool is_alpha2_set(const char *alpha2)
        return false;
 }
 
-static bool is_alpha_upper(char letter)
-{
-       /* ASCII A - Z */
-       if (letter >= 65 && letter <= 90)
-               return true;
-       return false;
-}
-
 static bool is_unknown_alpha2(const char *alpha2)
 {
        if (!alpha2)
@@ -220,7 +213,7 @@ static bool is_an_alpha2(const char *alpha2)
 {
        if (!alpha2)
                return false;
-       if (is_alpha_upper(alpha2[0]) && is_alpha_upper(alpha2[1]))
+       if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
                return true;
        return false;
 }
@@ -1399,6 +1392,11 @@ static DECLARE_WORK(reg_work, reg_todo);
 
 static void queue_regulatory_request(struct regulatory_request *request)
 {
+       if (isalpha(request->alpha2[0]))
+               request->alpha2[0] = toupper(request->alpha2[0]);
+       if (isalpha(request->alpha2[1]))
+               request->alpha2[1] = toupper(request->alpha2[1]);
+
        spin_lock(&reg_requests_lock);
        list_add_tail(&request->list, &reg_requests_list);
        spin_unlock(&reg_requests_lock);