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;
}
}
+ 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. */
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. */
b43_set_status(dev, B43_STAT_INITIALIZED);
+ /* Register HW RNG driver */
+ b43_rng_init(dev->wl);
+
out:
return err;
if (err)
goto err_one_core_detach;
b43_leds_register(wl->current_dev);
- b43_rng_init(wl);
}
out:
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.
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;
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:
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;
#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>
/**************************
* 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;
#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>
/***************************
* 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;
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:
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,
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) {
}
}
-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 |
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;
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)
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;
}
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;
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)
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)));
struct rtl8180_priv *priv = dev->priv;
struct rtl8180_vif *vif_priv;
int i;
+ u8 reg;
vif_priv = (struct rtl8180_vif *)&vif->drv_priv;
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)
.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)
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) {
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);
}
static int print_fw_version(struct zd_chip *chip)
{
+ struct wiphy *wiphy = zd_chip_to_mac(chip)->hw->wiphy;
int r;
u16 version;
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;
}
*
* @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;
int channel_change_time;
int vif_data_size;
int sta_data_size;
+ int napi_weight;
u16 queues;
u16 max_listen_interval;
s8 max_signal;
* 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);
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);
};
/**
*/
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
*
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 *
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);
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);
}
#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)
{
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);
goto fail_ifa;
#endif
+ netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
+ local->hw.napi_weight);
+
return 0;
#ifdef CONFIG_INET
#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>
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)
{
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;
}
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(®_requests_lock);
list_add_tail(&request->list, ®_requests_list);
spin_unlock(®_requests_lock);