Commit f318d658 authored by John W. Linville's avatar John W. Linville

Merge branch 'wireless-next-2.6' of...

Merge branch 'wireless-next-2.6' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6
parents 42c4568a 1db5950f
...@@ -246,7 +246,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { ...@@ -246,7 +246,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
.use_rts_for_ht = true, /* use rts/cts protection */ .use_rts_for_ht = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.support_ct_kill_exit = true, .support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
.chain_noise_scale = 1000, .chain_noise_scale = 1000,
}; };
...@@ -274,7 +274,7 @@ struct iwl_cfg iwl1000_bg_cfg = { ...@@ -274,7 +274,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
.led_compensation = 51, .led_compensation = 51,
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.support_ct_kill_exit = true, .support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
.chain_noise_scale = 1000, .chain_noise_scale = 1000,
}; };
......
...@@ -2470,11 +2470,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) ...@@ -2470,11 +2470,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
memset((void *)&priv->hw_params, 0, memset((void *)&priv->hw_params, 0,
sizeof(struct iwl_hw_params)); sizeof(struct iwl_hw_params));
priv->shared_virt = priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev,
pci_alloc_consistent(priv->pci_dev,
sizeof(struct iwl3945_shared), sizeof(struct iwl3945_shared),
&priv->shared_phys); &priv->shared_phys, GFP_KERNEL);
if (!priv->shared_virt) { if (!priv->shared_virt) {
IWL_ERR(priv, "failed to allocate pci memory\n"); IWL_ERR(priv, "failed to allocate pci memory\n");
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
......
...@@ -581,6 +581,13 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) ...@@ -581,6 +581,13 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
/* make sure all queue are not stopped */
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
for (i = 0; i < 4; i++)
atomic_set(&priv->queue_stop_count[i], 0);
/* reset to 0 to enable all the queue first */
priv->txq_ctx_active_msk = 0;
/* Map each Tx/cmd queue to its corresponding fifo */ /* Map each Tx/cmd queue to its corresponding fifo */
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
int ac = default_queue_to_tx_fifo[i]; int ac = default_queue_to_tx_fifo[i];
......
...@@ -648,6 +648,13 @@ int iwl5000_alive_notify(struct iwl_priv *priv) ...@@ -648,6 +648,13 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
/* make sure all queue are not stopped */
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
for (i = 0; i < 4; i++)
atomic_set(&priv->queue_stop_count[i], 0);
/* reset to 0 to enable all the queue first */
priv->txq_ctx_active_msk = 0;
/* map qos queues to fifos one-to-one */ /* map qos queues to fifos one-to-one */
for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
int ac = iwl5000_default_queue_to_tx_fifo[i]; int ac = iwl5000_default_queue_to_tx_fifo[i];
......
...@@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, ...@@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid, struct iwl_lq_sta *lq_data, u8 tid,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
int ret;
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
sta->addr, tid); sta->addr, tid);
ieee80211_start_tx_ba_session(sta, tid); ret = ieee80211_start_tx_ba_session(sta, tid);
if (ret == -EAGAIN) {
/*
* driver and mac80211 is out of sync
* this might be cause by reloading firmware
* stop the tx ba session here
*/
IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
tid);
ret = ieee80211_stop_tx_ba_session(sta, tid,
WLAN_BACK_INITIATOR);
}
} }
} }
......
...@@ -2941,10 +2941,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, ...@@ -2941,10 +2941,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
return ret; return ret;
case IEEE80211_AMPDU_TX_START: case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT(priv, "start Tx\n"); IWL_DEBUG_HT(priv, "start Tx\n");
return iwl_tx_agg_start(priv, sta->addr, tid, ssn); ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn);
if (ret == 0) {
priv->agg_tids_count++;
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
priv->agg_tids_count);
}
return ret;
case IEEE80211_AMPDU_TX_STOP: case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT(priv, "stop Tx\n"); IWL_DEBUG_HT(priv, "stop Tx\n");
ret = iwl_tx_agg_stop(priv, sta->addr, tid); ret = iwl_tx_agg_stop(priv, sta->addr, tid);
if ((ret == 0) && (priv->agg_tids_count > 0)) {
priv->agg_tids_count--;
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
priv->agg_tids_count);
}
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return 0; return 0;
else else
...@@ -3364,6 +3375,7 @@ static int iwl_init_drv(struct iwl_priv *priv) ...@@ -3364,6 +3375,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
priv->iw_mode = NL80211_IFTYPE_STATION; priv->iw_mode = NL80211_IFTYPE_STATION;
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
priv->agg_tids_count = 0;
/* Choose which receivers/antennas to use */ /* Choose which receivers/antennas to use */
if (priv->cfg->ops->hcmd->set_rxon_chain) if (priv->cfg->ops->hcmd->set_rxon_chain)
...@@ -3540,6 +3552,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3540,6 +3552,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/ */
spin_lock_init(&priv->reg_lock); spin_lock_init(&priv->reg_lock);
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
/*
* stop and reset the on-board processor just in case it is in a
* strange state ... like being left stranded by a primary kernel
* and this is now the kdump kernel trying to start up
*/
iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
iwl_hw_detect(priv); iwl_hw_detect(priv);
IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
priv->cfg->name, priv->hw_rev); priv->cfg->name, priv->hw_rev);
......
...@@ -3470,11 +3470,7 @@ enum { ...@@ -3470,11 +3470,7 @@ enum {
IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
IWL_PHY_CALIBRATE_DC_CMD = 8, IWL_PHY_CALIBRATE_DC_CMD = 8,
IWL_PHY_CALIBRATE_LO_CMD = 9, IWL_PHY_CALIBRATE_LO_CMD = 9,
IWL_PHY_CALIBRATE_RX_BB_CMD = 10,
IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, IWL_PHY_CALIBRATE_TX_IQ_CMD = 11,
IWL_PHY_CALIBRATE_RX_IQ_CMD = 12,
IWL_PHY_CALIBRATION_NOISE_CMD = 13,
IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
......
...@@ -1670,9 +1670,9 @@ EXPORT_SYMBOL(iwl_set_tx_power); ...@@ -1670,9 +1670,9 @@ EXPORT_SYMBOL(iwl_set_tx_power);
void iwl_free_isr_ict(struct iwl_priv *priv) void iwl_free_isr_ict(struct iwl_priv *priv)
{ {
if (priv->ict_tbl_vir) { if (priv->ict_tbl_vir) {
pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) + dma_free_coherent(&priv->pci_dev->dev,
PAGE_SIZE, priv->ict_tbl_vir, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
priv->ict_tbl_dma); priv->ict_tbl_vir, priv->ict_tbl_dma);
priv->ict_tbl_vir = NULL; priv->ict_tbl_vir = NULL;
} }
} }
...@@ -1688,9 +1688,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv) ...@@ -1688,9 +1688,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv)
if (priv->cfg->use_isr_legacy) if (priv->cfg->use_isr_legacy)
return 0; return 0;
/* allocate shrared data table */ /* allocate shrared data table */
priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) * priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev,
ICT_COUNT) + PAGE_SIZE, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
&priv->ict_tbl_dma); &priv->ict_tbl_dma, GFP_KERNEL);
if (!priv->ict_tbl_vir) if (!priv->ict_tbl_vir)
return -ENOMEM; return -ENOMEM;
...@@ -3334,7 +3334,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) ...@@ -3334,7 +3334,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
} }
EXPORT_SYMBOL(iwl_dump_fh); EXPORT_SYMBOL(iwl_dump_fh);
void iwl_force_rf_reset(struct iwl_priv *priv) static void iwl_force_rf_reset(struct iwl_priv *priv)
{ {
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return; return;
...@@ -3356,7 +3356,47 @@ void iwl_force_rf_reset(struct iwl_priv *priv) ...@@ -3356,7 +3356,47 @@ void iwl_force_rf_reset(struct iwl_priv *priv)
iwl_internal_short_hw_scan(priv); iwl_internal_short_hw_scan(priv);
return; return;
} }
EXPORT_SYMBOL(iwl_force_rf_reset);
#define IWL_DELAY_NEXT_FORCE_RESET (HZ*3)
int iwl_force_reset(struct iwl_priv *priv, int mode)
{
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EINVAL;
if (priv->last_force_reset_jiffies &&
time_after(priv->last_force_reset_jiffies +
IWL_DELAY_NEXT_FORCE_RESET, jiffies)) {
IWL_DEBUG_INFO(priv, "force reset rejected\n");
return -EAGAIN;
}
IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
switch (mode) {
case IWL_RF_RESET:
iwl_force_rf_reset(priv);
break;
case IWL_FW_RESET:
IWL_ERR(priv, "On demand firmware reload\n");
/* Set the FW error flag -- cleared on iwl_down */
set_bit(STATUS_FW_ERROR, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);
/*
* Keep the restart process from trying to send host
* commands by clearing the INIT status bit
*/
clear_bit(STATUS_READY, &priv->status);
queue_work(priv->workqueue, &priv->restart);
break;
default:
IWL_DEBUG_INFO(priv, "invalid reset request.\n");
return -EINVAL;
}
priv->last_force_reset_jiffies = jiffies;
return 0;
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -414,13 +414,13 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); ...@@ -414,13 +414,13 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
void iwl_cmd_queue_free(struct iwl_priv *priv); void iwl_cmd_queue_free(struct iwl_priv *priv);
int iwl_rx_queue_alloc(struct iwl_priv *priv); int iwl_rx_queue_alloc(struct iwl_priv *priv);
void iwl_rx_handle(struct iwl_priv *priv); void iwl_rx_handle(struct iwl_priv *priv);
int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
struct iwl_rx_queue *q); struct iwl_rx_queue *q);
void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
void iwl_rx_replenish(struct iwl_priv *priv); void iwl_rx_replenish(struct iwl_priv *priv);
void iwl_rx_replenish_now(struct iwl_priv *priv); void iwl_rx_replenish_now(struct iwl_priv *priv);
int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
int iwl_rx_queue_restock(struct iwl_priv *priv); void iwl_rx_queue_restock(struct iwl_priv *priv);
int iwl_rx_queue_space(const struct iwl_rx_queue *q); int iwl_rx_queue_space(const struct iwl_rx_queue *q);
void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority);
void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
...@@ -450,7 +450,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); ...@@ -450,7 +450,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
void iwl_hw_txq_ctx_free(struct iwl_priv *priv); void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
int iwl_hw_tx_queue_init(struct iwl_priv *priv, int iwl_hw_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq); struct iwl_tx_queue *txq);
int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id); int slots_num, u32 txq_id);
void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
...@@ -501,7 +501,7 @@ int iwl_scan_cancel(struct iwl_priv *priv); ...@@ -501,7 +501,7 @@ int iwl_scan_cancel(struct iwl_priv *priv);
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
int iwl_internal_short_hw_scan(struct iwl_priv *priv); int iwl_internal_short_hw_scan(struct iwl_priv *priv);
void iwl_force_rf_reset(struct iwl_priv *priv); int iwl_force_reset(struct iwl_priv *priv, int mode);
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
const u8 *ie, int ie_len, int left); const u8 *ie, int ie_len, int left);
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
......
...@@ -2223,6 +2223,32 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, ...@@ -2223,6 +2223,32 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
return count; return count;
} }
static ssize_t iwl_dbgfs_force_reset_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos) {
struct iwl_priv *priv = file->private_data;
char buf[8];
int buf_size;
int reset, ret;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%d", &reset) != 1)
return -EINVAL;
switch (reset) {
case IWL_RF_RESET:
case IWL_FW_RESET:
ret = iwl_force_reset(priv, reset);
break;
default:
return -EINVAL;
}
return ret ? ret : count;
}
DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
...@@ -2243,6 +2269,7 @@ DEBUGFS_READ_FILE_OPS(fh_reg); ...@@ -2243,6 +2269,7 @@ DEBUGFS_READ_FILE_OPS(fh_reg);
DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
DEBUGFS_WRITE_FILE_OPS(internal_scan); DEBUGFS_WRITE_FILE_OPS(internal_scan);
DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
DEBUGFS_WRITE_FILE_OPS(force_reset);
/* /*
* Create the debugfs files and directories * Create the debugfs files and directories
...@@ -2296,6 +2323,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) ...@@ -2296,6 +2323,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR);
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
......
...@@ -1033,8 +1033,14 @@ struct iwl_event_log { ...@@ -1033,8 +1033,14 @@ struct iwl_event_log {
#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0) #define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0)
#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50) #define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100) #define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200)
#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
enum iwl_reset {
IWL_RF_RESET = 0,
IWL_FW_RESET,
};
struct iwl_priv { struct iwl_priv {
/* ieee device used by generic ieee processing code */ /* ieee device used by generic ieee processing code */
...@@ -1066,6 +1072,12 @@ struct iwl_priv { ...@@ -1066,6 +1072,12 @@ struct iwl_priv {
/* storing the jiffies when the plcp error rate is received */ /* storing the jiffies when the plcp error rate is received */
unsigned long plcp_jiffies; unsigned long plcp_jiffies;
/* reporting the number of tids has AGG on. 0 means no AGGREGATION */
u8 agg_tids_count;
/* force reset */
unsigned long last_force_reset_jiffies;
/* we allocate array of iwl4965_channel_info for NIC's valid channels. /* we allocate array of iwl4965_channel_info for NIC's valid channels.
* Access via channel # using indirect index array */ * Access via channel # using indirect index array */
struct iwl_channel_info *channel_info; /* channel info array */ struct iwl_channel_info *channel_info; /* channel info array */
...@@ -1087,7 +1099,6 @@ struct iwl_priv { ...@@ -1087,7 +1099,6 @@ struct iwl_priv {
unsigned long scan_start; unsigned long scan_start;
unsigned long scan_pass_start; unsigned long scan_pass_start;
unsigned long scan_start_tsf; unsigned long scan_start_tsf;
unsigned long last_internal_scan_jiffies;
void *scan; void *scan;
int scan_bands; int scan_bands;
struct cfg80211_scan_request *scan_request; struct cfg80211_scan_request *scan_request;
......
...@@ -80,7 +80,7 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, ...@@ -80,7 +80,7 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
struct fw_desc *desc) struct fw_desc *desc)
{ {
if (desc->v_addr) if (desc->v_addr)
pci_free_consistent(pci_dev, desc->len, dma_free_coherent(&pci_dev->dev, desc->len,
desc->v_addr, desc->p_addr); desc->v_addr, desc->p_addr);
desc->v_addr = NULL; desc->v_addr = NULL;
desc->len = 0; desc->len = 0;
...@@ -89,7 +89,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, ...@@ -89,7 +89,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev,
struct fw_desc *desc) struct fw_desc *desc)
{ {
desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr); desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
&desc->p_addr, GFP_KERNEL);
return (desc->v_addr != NULL) ? 0 : -ENOMEM; return (desc->v_addr != NULL) ? 0 : -ENOMEM;
} }
......
...@@ -123,12 +123,11 @@ EXPORT_SYMBOL(iwl_rx_queue_space); ...@@ -123,12 +123,11 @@ EXPORT_SYMBOL(iwl_rx_queue_space);
/** /**
* iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
*/ */
int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
{ {
unsigned long flags; unsigned long flags;
u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
u32 reg; u32 reg;
int ret = 0;
spin_lock_irqsave(&q->lock, flags); spin_lock_irqsave(&q->lock, flags);
...@@ -161,7 +160,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) ...@@ -161,7 +160,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
exit_unlock: exit_unlock:
spin_unlock_irqrestore(&q->lock, flags); spin_unlock_irqrestore(&q->lock, flags);
return ret;
} }
EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr);
/** /**
...@@ -184,14 +182,13 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, ...@@ -184,14 +182,13 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
* also updates the memory address in the firmware to reference the new * also updates the memory address in the firmware to reference the new
* target buffer. * target buffer.
*/ */
int iwl_rx_queue_restock(struct iwl_priv *priv) void iwl_rx_queue_restock(struct iwl_priv *priv)
{ {
struct iwl_rx_queue *rxq = &priv->rxq; struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element; struct list_head *element;
struct iwl_rx_mem_buffer *rxb; struct iwl_rx_mem_buffer *rxb;
unsigned long flags; unsigned long flags;
int write; int write;
int ret = 0;
spin_lock_irqsave(&rxq->lock, flags); spin_lock_irqsave(&rxq->lock, flags);
write = rxq->write & ~0x7; write = rxq->write & ~0x7;
...@@ -220,10 +217,8 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) ...@@ -220,10 +217,8 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
spin_lock_irqsave(&rxq->lock, flags); spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1; rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags); spin_unlock_irqrestore(&rxq->lock, flags);
ret = iwl_rx_queue_update_write_ptr(priv, rxq); iwl_rx_queue_update_write_ptr(priv, rxq);
} }
return ret;
} }
EXPORT_SYMBOL(iwl_rx_queue_restock); EXPORT_SYMBOL(iwl_rx_queue_restock);
...@@ -350,9 +345,9 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) ...@@ -350,9 +345,9 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
} }
} }
pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
rxq->dma_addr); rxq->dma_addr);
pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
rxq->rb_stts, rxq->rb_stts_dma); rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL; rxq->bd = NULL;
rxq->rb_stts = NULL; rxq->rb_stts = NULL;
...@@ -362,7 +357,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free); ...@@ -362,7 +357,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free);
int iwl_rx_queue_alloc(struct iwl_priv *priv) int iwl_rx_queue_alloc(struct iwl_priv *priv)
{ {
struct iwl_rx_queue *rxq = &priv->rxq; struct iwl_rx_queue *rxq = &priv->rxq;
struct pci_dev *dev = priv->pci_dev; struct device *dev = &priv->pci_dev->dev;
int i; int i;
spin_lock_init(&rxq->lock); spin_lock_init(&rxq->lock);
...@@ -370,12 +365,13 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) ...@@ -370,12 +365,13 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
INIT_LIST_HEAD(&rxq->rx_used); INIT_LIST_HEAD(&rxq->rx_used);
/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr,
GFP_KERNEL);
if (!rxq->bd) if (!rxq->bd)
goto err_bd; goto err_bd;
rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status), rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
&rxq->rb_stts_dma); &rxq->rb_stts_dma, GFP_KERNEL);
if (!rxq->rb_stts) if (!rxq->rb_stts)
goto err_rb; goto err_rb;
...@@ -392,7 +388,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) ...@@ -392,7 +388,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
return 0; return 0;
err_rb: err_rb:
pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
rxq->dma_addr); rxq->dma_addr);
err_bd: err_bd:
return -ENOMEM; return -ENOMEM;
...@@ -620,6 +616,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, ...@@ -620,6 +616,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
#define REG_RECALIB_PERIOD (60) #define REG_RECALIB_PERIOD (60)
/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
#define ACK_CNT_RATIO (50)
#define BA_TIMEOUT_CNT (5)
#define BA_TIMEOUT_MAX (16)
#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n"
void iwl_rx_statistics(struct iwl_priv *priv, void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb) struct iwl_rx_mem_buffer *rxb)
...@@ -629,6 +630,9 @@ void iwl_rx_statistics(struct iwl_priv *priv, ...@@ -629,6 +630,9 @@ void iwl_rx_statistics(struct iwl_priv *priv,
int combined_plcp_delta; int combined_plcp_delta;
unsigned int plcp_msec; unsigned int plcp_msec;
unsigned long plcp_received_jiffies; unsigned long plcp_received_jiffies;
int actual_ack_cnt_delta;
int expected_ack_cnt_delta;
int ba_timeout_delta;
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
(int)sizeof(priv->statistics), (int)sizeof(priv->statistics),
...@@ -643,6 +647,44 @@ void iwl_rx_statistics(struct iwl_priv *priv, ...@@ -643,6 +647,44 @@ void iwl_rx_statistics(struct iwl_priv *priv,
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
#endif #endif
actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
expected_ack_cnt_delta = le32_to_cpu(
pkt->u.stats.tx.expected_ack_cnt) -
le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
ba_timeout_delta = le32_to_cpu(
pkt->u.stats.tx.agg.ba_timeout) -
le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
if ((priv->agg_tids_count > 0) &&
(expected_ack_cnt_delta > 0) &&
(((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) <
ACK_CNT_RATIO) &&
(ba_timeout_delta > BA_TIMEOUT_CNT)) {
IWL_DEBUG_RADIO(priv,
"actual_ack_cnt delta = %d, expected_ack_cnt = %d\n",
actual_ack_cnt_delta, expected_ack_cnt_delta);
#ifdef CONFIG_IWLWIFI_DEBUG
IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
priv->delta_statistics.tx.rx_detected_cnt);
IWL_DEBUG_RADIO(priv,
"ack_or_ba_timeout_collision delta = %d\n",
priv->delta_statistics.tx.ack_or_ba_timeout_collision);
#endif
IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
ba_timeout_delta);
if ((actual_ack_cnt_delta == 0) &&
(ba_timeout_delta >=
BA_TIMEOUT_MAX)) {
IWL_DEBUG_RADIO(priv,
"call iwl_force_reset(IWL_FW_RESET)\n");
iwl_force_reset(priv, IWL_FW_RESET);
} else {
IWL_DEBUG_RADIO(priv,
"call iwl_force_reset(IWL_RF_RESET)\n");
iwl_force_reset(priv, IWL_RF_RESET);
}
}
/* /*
* check for plcp_err and trigger radio reset if it exceeds * check for plcp_err and trigger radio reset if it exceeds
* the plcp error threshold plcp_delta. * the plcp error threshold plcp_delta.
...@@ -689,7 +731,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, ...@@ -689,7 +731,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
* Reset the RF radio due to the high plcp * Reset the RF radio due to the high plcp
* error rate * error rate
*/ */
iwl_force_rf_reset(priv); iwl_force_reset(priv, IWL_RF_RESET);
} }
} }
......
...@@ -250,8 +250,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, ...@@ -250,8 +250,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
if (!priv->is_internal_short_scan) if (!priv->is_internal_short_scan)
priv->next_scan_jiffies = 0; priv->next_scan_jiffies = 0;
else
priv->last_internal_scan_jiffies = jiffies;
IWL_DEBUG_INFO(priv, "Setting scan to off\n"); IWL_DEBUG_INFO(priv, "Setting scan to off\n");
...@@ -471,21 +469,6 @@ EXPORT_SYMBOL(iwl_init_scan_params); ...@@ -471,21 +469,6 @@ EXPORT_SYMBOL(iwl_init_scan_params);
static int iwl_scan_initiate(struct iwl_priv *priv) static int iwl_scan_initiate(struct iwl_priv *priv)
{ {
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n");
return -EIO;
}
if (test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
return -EAGAIN;
}
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
return -EAGAIN;
}
IWL_DEBUG_INFO(priv, "Starting scan...\n"); IWL_DEBUG_INFO(priv, "Starting scan...\n");
set_bit(STATUS_SCANNING, &priv->status); set_bit(STATUS_SCANNING, &priv->status);
priv->is_internal_short_scan = false; priv->is_internal_short_scan = false;
...@@ -517,6 +500,18 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, ...@@ -517,6 +500,18 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
goto out_unlock; goto out_unlock;
} }
if (test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
ret = -EAGAIN;
goto out_unlock;
}
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
ret = -EAGAIN;
goto out_unlock;
}
/* We don't schedule scan within next_scan_jiffies period. /* We don't schedule scan within next_scan_jiffies period.
* Avoid scanning during possible EAPOL exchange, return * Avoid scanning during possible EAPOL exchange, return
* success immediately. * success immediately.
...@@ -551,8 +546,6 @@ EXPORT_SYMBOL(iwl_mac_hw_scan); ...@@ -551,8 +546,6 @@ EXPORT_SYMBOL(iwl_mac_hw_scan);
* internal short scan, this function should only been called while associated. * internal short scan, this function should only been called while associated.
* It will reset and tune the radio to prevent possible RF related problem * It will reset and tune the radio to prevent possible RF related problem
*/ */
#define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1)
int iwl_internal_short_hw_scan(struct iwl_priv *priv) int iwl_internal_short_hw_scan(struct iwl_priv *priv)
{ {
int ret = 0; int ret = 0;
...@@ -572,12 +565,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv) ...@@ -572,12 +565,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv)
ret = -EAGAIN; ret = -EAGAIN;
goto out; goto out;
} }
if (priv->last_internal_scan_jiffies &&
time_after(priv->last_internal_scan_jiffies +
IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) {
IWL_DEBUG_SCAN(priv, "internal scan rejected\n");
goto out;
}
priv->scan_bands = 0; priv->scan_bands = 0;
if (priv->band == IEEE80211_BAND_5GHZ) if (priv->band == IEEE80211_BAND_5GHZ)
......
...@@ -60,7 +60,8 @@ static const u16 default_tid_to_tx_fifo[] = { ...@@ -60,7 +60,8 @@ static const u16 default_tid_to_tx_fifo[] = {
static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
struct iwl_dma_ptr *ptr, size_t size) struct iwl_dma_ptr *ptr, size_t size)
{ {
ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma); ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
GFP_KERNEL);
if (!ptr->addr) if (!ptr->addr)
return -ENOMEM; return -ENOMEM;
ptr->size = size; ptr->size = size;
...@@ -73,21 +74,20 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv, ...@@ -73,21 +74,20 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
if (unlikely(!ptr->addr)) if (unlikely(!ptr->addr))
return; return;
pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma); dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
memset(ptr, 0, sizeof(*ptr)); memset(ptr, 0, sizeof(*ptr));
} }
/** /**
* iwl_txq_update_write_ptr - Send new write index to hardware * iwl_txq_update_write_ptr - Send new write index to hardware
*/ */
int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
{ {
u32 reg = 0; u32 reg = 0;
int ret = 0;
int txq_id = txq->q.id; int txq_id = txq->q.id;
if (txq->need_update == 0) if (txq->need_update == 0)
return ret; return;
/* if we're trying to save power */ /* if we're trying to save power */
if (test_bit(STATUS_POWER_PMI, &priv->status)) { if (test_bit(STATUS_POWER_PMI, &priv->status)) {
...@@ -101,7 +101,7 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) ...@@ -101,7 +101,7 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
txq_id, reg); txq_id, reg);
iwl_set_bit(priv, CSR_GP_CNTRL, iwl_set_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
return ret; return;
} }
iwl_write_direct32(priv, HBUS_TARG_WRPTR, iwl_write_direct32(priv, HBUS_TARG_WRPTR,
...@@ -114,8 +114,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) ...@@ -114,8 +114,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
txq->q.write_ptr | (txq_id << 8)); txq->q.write_ptr | (txq_id << 8));
txq->need_update = 0; txq->need_update = 0;
return ret;
} }
EXPORT_SYMBOL(iwl_txq_update_write_ptr); EXPORT_SYMBOL(iwl_txq_update_write_ptr);
...@@ -132,7 +130,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) ...@@ -132,7 +130,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
{ {
struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct iwl_queue *q = &txq->q; struct iwl_queue *q = &txq->q;
struct pci_dev *dev = priv->pci_dev; struct device *dev = &priv->pci_dev->dev;
int i; int i;
if (q->n_bd == 0) if (q->n_bd == 0)
...@@ -149,7 +147,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) ...@@ -149,7 +147,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
/* De-alloc circular buffer of TFDs */ /* De-alloc circular buffer of TFDs */
if (txq->q.n_bd) if (txq->q.n_bd)
pci_free_consistent(dev, priv->hw_params.tfd_size * dma_free_coherent(dev, priv->hw_params.tfd_size *
txq->q.n_bd, txq->tfds, txq->q.dma_addr); txq->q.n_bd, txq->tfds, txq->q.dma_addr);
/* De-alloc array of per-TFD driver data */ /* De-alloc array of per-TFD driver data */
...@@ -179,7 +177,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) ...@@ -179,7 +177,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
{ {
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
struct iwl_queue *q = &txq->q; struct iwl_queue *q = &txq->q;
struct pci_dev *dev = priv->pci_dev; struct device *dev = &priv->pci_dev->dev;
int i; int i;
if (q->n_bd == 0) if (q->n_bd == 0)
...@@ -191,8 +189,8 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) ...@@ -191,8 +189,8 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
/* De-alloc circular buffer of TFDs */ /* De-alloc circular buffer of TFDs */
if (txq->q.n_bd) if (txq->q.n_bd)
pci_free_consistent(dev, priv->hw_params.tfd_size * dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
txq->q.n_bd, txq->tfds, txq->q.dma_addr); txq->tfds, txq->q.dma_addr);
/* deallocate arrays */ /* deallocate arrays */
kfree(txq->cmd); kfree(txq->cmd);
...@@ -283,7 +281,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, ...@@ -283,7 +281,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
static int iwl_tx_queue_alloc(struct iwl_priv *priv, static int iwl_tx_queue_alloc(struct iwl_priv *priv,
struct iwl_tx_queue *txq, u32 id) struct iwl_tx_queue *txq, u32 id)
{ {
struct pci_dev *dev = priv->pci_dev; struct device *dev = &priv->pci_dev->dev;
size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
/* Driver private data, only for Tx (not command) queues, /* Driver private data, only for Tx (not command) queues,
...@@ -302,8 +300,8 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, ...@@ -302,8 +300,8 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
/* Circular buffer of transmit frame descriptors (TFDs), /* Circular buffer of transmit frame descriptors (TFDs),
* shared with device */ * shared with device */
txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr); txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
GFP_KERNEL);
if (!txq->tfds) { if (!txq->tfds) {
IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
goto error; goto error;
...@@ -731,7 +729,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -731,7 +729,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
u8 tid = 0; u8 tid = 0;
u8 *qc = NULL; u8 *qc = NULL;
unsigned long flags; unsigned long flags;
int ret;
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (iwl_is_rfkill(priv)) { if (iwl_is_rfkill(priv)) {
...@@ -806,9 +803,11 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -806,9 +803,11 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr->seq_ctrl |= cpu_to_le16(seq_number); hdr->seq_ctrl |= cpu_to_le16(seq_number);
seq_number += 0x10; seq_number += 0x10;
/* aggregation is on for this <sta,tid> */ /* aggregation is on for this <sta,tid> */
if (info->flags & IEEE80211_TX_CTL_AMPDU) if (info->flags & IEEE80211_TX_CTL_AMPDU &&
priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
} }
}
txq = &priv->txq[txq_id]; txq = &priv->txq[txq_id];
swq_id = txq->swq_id; swq_id = txq->swq_id;
...@@ -949,7 +948,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -949,7 +948,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Tell device the write index *just past* this latest filled TFD */ /* Tell device the write index *just past* this latest filled TFD */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
ret = iwl_txq_update_write_ptr(priv, txq); iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
/* /*
...@@ -963,9 +962,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -963,9 +962,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (sta_priv && sta_priv->client) if (sta_priv && sta_priv->client)
atomic_inc(&sta_priv->pending_frames); atomic_inc(&sta_priv->pending_frames);
if (ret)
return ret;
if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
if (wait_write_ptr) { if (wait_write_ptr) {
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
...@@ -1004,7 +1000,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ...@@ -1004,7 +1000,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
struct iwl_cmd_meta *out_meta; struct iwl_cmd_meta *out_meta;
dma_addr_t phys_addr; dma_addr_t phys_addr;
unsigned long flags; unsigned long flags;
int len, ret; int len;
u32 idx; u32 idx;
u16 fix_size; u16 fix_size;
...@@ -1101,10 +1097,10 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ...@@ -1101,10 +1097,10 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
/* Increment and update queue's write index */ /* Increment and update queue's write index */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
ret = iwl_txq_update_write_ptr(priv, txq); iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->hcmd_lock, flags); spin_unlock_irqrestore(&priv->hcmd_lock, flags);
return ret ? ret : idx; return idx;
} }
static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
...@@ -1328,7 +1324,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) ...@@ -1328,7 +1324,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
{ {
int tx_fifo_id, txq_id, sta_id, ssn = -1; int tx_fifo_id, txq_id, sta_id, ssn = -1;
struct iwl_tid_data *tid_data; struct iwl_tid_data *tid_data;
int ret, write_ptr, read_ptr; int write_ptr, read_ptr;
unsigned long flags; unsigned long flags;
if (!ra) { if (!ra) {
...@@ -1380,13 +1376,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) ...@@ -1380,13 +1376,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, /*
* the only reason this call can fail is queue number out of range,
* which can happen if uCode is reloaded and all the station
* information are lost. if it is outside the range, there is no need
* to deactivate the uCode queue, just return "success" to allow
* mac80211 to clean up it own data.
*/
priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
tx_fifo_id); tx_fifo_id);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
if (ret)
return ret;
ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
return 0; return 0;
......
...@@ -352,7 +352,7 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) ...@@ -352,7 +352,7 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
static void iwl3945_unset_hw_params(struct iwl_priv *priv) static void iwl3945_unset_hw_params(struct iwl_priv *priv)
{ {
if (priv->shared_virt) if (priv->shared_virt)
pci_free_consistent(priv->pci_dev, dma_free_coherent(&priv->pci_dev->dev,
sizeof(struct iwl3945_shared), sizeof(struct iwl3945_shared),
priv->shared_virt, priv->shared_virt,
priv->shared_phys); priv->shared_phys);
...@@ -478,7 +478,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -478,7 +478,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
u8 wait_write_ptr = 0; u8 wait_write_ptr = 0;
u8 *qc = NULL; u8 *qc = NULL;
unsigned long flags; unsigned long flags;
int rc;
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (iwl_is_rfkill(priv)) { if (iwl_is_rfkill(priv)) {
...@@ -663,12 +662,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -663,12 +662,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Tell device the write index *just past* this latest filled TFD */ /* Tell device the write index *just past* this latest filled TFD */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
rc = iwl_txq_update_write_ptr(priv, txq); iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
if (rc)
return rc;
if ((iwl_queue_space(q) < q->high_mark) if ((iwl_queue_space(q) < q->high_mark)
&& priv->mac80211_registered) { && priv->mac80211_registered) {
if (wait_write_ptr) { if (wait_write_ptr) {
...@@ -1063,13 +1059,13 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv, ...@@ -1063,13 +1059,13 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
* also updates the memory address in the firmware to reference the new * also updates the memory address in the firmware to reference the new
* target buffer. * target buffer.
*/ */
static int iwl3945_rx_queue_restock(struct iwl_priv *priv) static void iwl3945_rx_queue_restock(struct iwl_priv *priv)
{ {
struct iwl_rx_queue *rxq = &priv->rxq; struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element; struct list_head *element;
struct iwl_rx_mem_buffer *rxb; struct iwl_rx_mem_buffer *rxb;
unsigned long flags; unsigned long flags;
int write, rc; int write;
spin_lock_irqsave(&rxq->lock, flags); spin_lock_irqsave(&rxq->lock, flags);
write = rxq->write & ~0x7; write = rxq->write & ~0x7;
...@@ -1099,12 +1095,8 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) ...@@ -1099,12 +1095,8 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
spin_lock_irqsave(&rxq->lock, flags); spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1; rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags); spin_unlock_irqrestore(&rxq->lock, flags);
rc = iwl_rx_queue_update_write_ptr(priv, rxq); iwl_rx_queue_update_write_ptr(priv, rxq);
if (rc)
return rc;
} }
return 0;
} }
/** /**
...@@ -1249,9 +1241,9 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx ...@@ -1249,9 +1241,9 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
} }
} }
pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
rxq->dma_addr); rxq->dma_addr);
pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
rxq->rb_stts, rxq->rb_stts_dma); rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL; rxq->bd = NULL;
rxq->rb_stts = NULL; rxq->rb_stts = NULL;
...@@ -4047,6 +4039,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e ...@@ -4047,6 +4039,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
spin_lock_init(&priv->reg_lock); spin_lock_init(&priv->reg_lock);
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
/*
* stop and reset the on-board processor just in case it is in a
* strange state ... like being left stranded by a primary kernel
* and this is now the kdump kernel trying to start up
*/
iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
/*********************** /***********************
* 4. Read EEPROM * 4. Read EEPROM
* ********************/ * ********************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment