aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c34
7 files changed, 75 insertions, 25 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 9b60a0c5de5..21c841847d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -638,12 +638,16 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
s8 scale_action = 0;
unsigned long flags;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- u16 fc, rate_mask;
+ u16 fc;
+ u16 rate_mask = 0;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE("enter\n");
+ if (sta)
+ rate_mask = sta->supp_rates[sband->band];
+
/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = le16_to_cpu(hdr->frame_control);
@@ -651,11 +655,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
is_multicast_ether_addr(hdr->addr1) ||
!sta || !priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
- info->control.rates[0].idx = rate_lowest_index(sband, sta);
+ if (!rate_mask)
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, NULL);
+ else
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, sta);
return;
}
- rate_mask = sta->supp_rates[sband->band];
index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
if (sband->band == IEEE80211_BAND_5GHZ)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index f3f17929ca0..27f50471aed 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -944,7 +944,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
}
/* See if there's a better rate or modulation mode to try. */
- rs_rate_scale_perform(priv, hdr, sta, lq_sta);
+ if (sta && sta->supp_rates[sband->band])
+ rs_rate_scale_perform(priv, hdr, sta, lq_sta);
out:
return;
}
@@ -2101,14 +2102,23 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_lq_sta *lq_sta = priv_sta;
int rate_idx;
+ u64 mask_bit = 0;
IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
+ if (sta)
+ mask_bit = sta->supp_rates[sband->band];
+
/* Send management frames and broadcast/multicast data using lowest
* rate. */
if (!ieee80211_is_data(hdr->frame_control) ||
is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) {
- info->control.rates[0].idx = rate_lowest_index(sband, sta);
+ if (!mask_bit)
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, NULL);
+ else
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, sta);
return;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 5da6b35cd26..129e2d330ab 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1719,6 +1719,10 @@ static int iwl_read_ucode(struct iwl_priv *priv)
priv->ucode_data_backup.len = data_size;
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+ if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
+ !priv->ucode_data_backup.v_addr)
+ goto err_pci_alloc;
+
/* Initialization instructions and data */
if (init_size && init_data_size) {
priv->ucode_init.len = init_size;
@@ -2482,7 +2486,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
dev_kfree_skb_any(skb);
IWL_DEBUG_MACDUMP("leave\n");
- return 0;
+ return NETDEV_TX_OK;
}
static int iwl_mac_add_interface(struct ieee80211_hw *hw,
@@ -3864,7 +3868,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
err = iwl_eeprom_check_version(priv);
if (err)
- goto out_iounmap;
+ goto out_free_eeprom;
/* extract MAC Address */
iwl_eeprom_get_mac(priv, priv->mac_addr);
@@ -3941,6 +3945,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
out_remove_sysfs:
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
out_uninit_drv:
iwl_uninit_drv(priv);
@@ -3949,8 +3955,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
out_iounmap:
pci_iounmap(pdev, priv->hw_base);
out_pci_release_regions:
- pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
+ pci_release_regions(pdev);
out_pci_disable_device:
pci_disable_device(pdev);
out_ieee80211_free_hw:
@@ -4038,6 +4044,19 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
priv->is_open = 1;
}
+ /* pci driver assumes state will be saved in this function.
+ * pci state is saved and device disabled when interface is
+ * stopped, so at this time pci device will always be disabled -
+ * whether interface was started or not. saving pci state now will
+ * cause saved state be that of a disabled device, which will cause
+ * problems during resume in that we will end up with a disabled device.
+ *
+ * indicate that the current saved state (from when interface was
+ * stopped) is valid. if interface was never up at time of suspend
+ * then the saved state will still be valid as it was saved during
+ * .probe. */
+ pdev->state_saved = true;
+
pci_set_power_state(pdev, PCI_D3hot);
return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 8c71ad4f88c..4b35b30e493 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -224,7 +224,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
IWL_ERROR("Error: Response NULL in '%s'\n",
get_cmd_string(cmd->id));
ret = -EIO;
- goto out;
+ goto cancel;
}
ret = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 412f66bac1a..70a8b21ca39 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -480,6 +480,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv)
priv->num_stations = 0;
memset(priv->stations, 0, sizeof(priv->stations));
+ /* clean ucode key table bit map */
+ priv->ucode_key_table = 0;
+
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
EXPORT_SYMBOL(iwl_clear_stations_table);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index b0ee86c6268..ab13ff22a8c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -148,7 +148,7 @@ static void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
pci_unmap_single(dev,
pci_unmap_addr(&txq->cmd[index]->meta, mapping),
pci_unmap_len(&txq->cmd[index]->meta, len),
- PCI_DMA_TODEVICE);
+ PCI_DMA_BIDIRECTIONAL);
/* Unmap chunks, if any. */
for (i = 1; i < num_tbs; i++) {
@@ -964,7 +964,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
* within command buffer array. */
txcmd_phys = pci_map_single(priv->pci_dev,
out_cmd, sizeof(struct iwl_cmd),
- PCI_DMA_TODEVICE);
+ PCI_DMA_BIDIRECTIONAL);
pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
/* Add buffer containing Tx command and MAC(!) header to TFD's
@@ -1115,7 +1115,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
phys_addr = pci_map_single(priv->pci_dev, out_cmd,
- len, PCI_DMA_TODEVICE);
+ len, PCI_DMA_BIDIRECTIONAL);
pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
pci_unmap_len_set(&out_cmd->meta, len, len);
phys_addr += offsetof(struct iwl_cmd, hdr);
@@ -1212,7 +1212,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
pci_unmap_single(priv->pci_dev,
pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping),
pci_unmap_len(&txq->cmd[cmd_idx]->meta, len),
- PCI_DMA_TODEVICE);
+ PCI_DMA_BIDIRECTIONAL);
for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index d64580805d6..57dd34e256d 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -745,7 +745,7 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_
IWL_ERROR("Error: Response NULL in '%s'\n",
get_cmd_string(cmd->id));
ret = -EIO;
- goto out;
+ goto cancel;
}
ret = 0;
@@ -6538,7 +6538,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
dev_kfree_skb_any(skb);
IWL_DEBUG_MAC80211("leave\n");
- return 0;
+ return NETDEV_TX_OK;
}
static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
@@ -7911,7 +7911,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (err < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
- goto out_remove_sysfs;
+ goto out_iounmap;
}
/***********************
@@ -7921,7 +7921,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
err = iwl3945_eeprom_init(priv);
if (err) {
IWL_ERROR("Unable to init EEPROM\n");
- goto out_remove_sysfs;
+ goto out_iounmap;
}
/* MAC Address location in EEPROM same for 3945/4965 */
get_eeprom_mac(priv, priv->mac_addr);
@@ -7975,7 +7975,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
err = iwl3945_init_channel_map(priv);
if (err) {
IWL_ERROR("initializing regulatory failed: %d\n", err);
- goto out_release_irq;
+ goto out_unset_hw_setting;
}
err = iwl3945_init_geos(priv);
@@ -8045,25 +8045,22 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
return 0;
out_remove_sysfs:
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
out_free_geos:
iwl3945_free_geos(priv);
out_free_channel_map:
iwl3945_free_channel_map(priv);
-
-
- out_release_irq:
- destroy_workqueue(priv->workqueue);
- priv->workqueue = NULL;
+ out_unset_hw_setting:
iwl3945_unset_hw_setting(priv);
-
out_iounmap:
pci_iounmap(pdev, priv->hw_base);
out_pci_release_regions:
pci_release_regions(pdev);
out_pci_disable_device:
- pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
+ pci_disable_device(pdev);
out_ieee80211_free_hw:
ieee80211_free_hw(priv->hw);
out:
@@ -8143,6 +8140,19 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
priv->is_open = 1;
}
+ /* pci driver assumes state will be saved in this function.
+ * pci state is saved and device disabled when interface is
+ * stopped, so at this time pci device will always be disabled -
+ * whether interface was started or not. saving pci state now will
+ * cause saved state be that of a disabled device, which will cause
+ * problems during resume in that we will end up with a disabled device.
+ *
+ * indicate that the current saved state (from when interface was
+ * stopped) is valid. if interface was never up at time of suspend
+ * then the saved state will still be valid as it was saved during
+ * .probe. */
+ pdev->state_saved = true;
+
pci_set_power_state(pdev, PCI_D3hot);
return 0;