diff options
author | David S. Miller <davem@davemloft.net> | 2008-05-15 00:52:37 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-05-15 00:52:37 -0700 |
commit | f42a44494bcdf03fc851c03d438464d59c0ceaf5 (patch) | |
tree | 986ea7b54e9fc79a64863fd7e92eabd99ffd37a3 /drivers/net/wireless/iwlwifi | |
parent | 63fe46da9c380b3f2bbdf3765044649517cc717c (diff) | |
parent | ef85ad541f9a6ccd3f89ec73f92b2d6f45a9d3e8 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
20 files changed, 1838 insertions, 1479 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 995dd537083f..5f3e849043f7 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -96,13 +96,13 @@ config IWLWIFI_DEBUG control which debug output is sent to the kernel log by setting the value in - /sys/bus/pci/drivers/${DRIVER}/debug_level + /sys/class/net/wlan0/device/debug_level This entry will only exist if this option is enabled. To set a value, simply echo an 8-byte hex value to the same file: - % echo 0x43fff > /sys/bus/pci/drivers/${DRIVER}/debug_level + % echo 0x43fff > /sys/class/net/wlan0/device/debug_level You can find the list of debug mask values in: drivers/net/wireless/iwlwifi/iwl-4965-debug.h diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index b0b2b5ebfa61..5c73eede7193 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_IWLCORE) += iwlcore.o iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o +iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o @@ -10,7 +11,7 @@ iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o obj-$(CONFIG_IWL4965) += iwl4965.o -iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o +iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o ifeq ($(CONFIG_IWL5000),y) iwl4965-objs += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 9df48b33f0ca..ad4e7b74ca24 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -520,7 +520,7 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, { /* First cache any information we need before we overwrite * the information provided in the skb from the hardware */ - s8 signal = stats->ssi; + s8 signal = stats->signal; s8 noise = 0; int rate = stats->rate_idx; u64 tsf = stats->mactime; @@ -693,7 +693,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, } /* Convert 3945's rssi indicator to dBm */ - rx_status.ssi = rx_stats->rssi - IWL_RSSI_OFFSET; + rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET; /* Set default noise value to -127 */ if (priv->last_rx_noise == 0) @@ -712,21 +712,21 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, * Calculate rx_status.signal (quality indicator in %) based on SNR. */ if (rx_stats_noise_diff) { snr = rx_stats_sig_avg / rx_stats_noise_diff; - rx_status.noise = rx_status.ssi - + rx_status.noise = rx_status.signal - iwl3945_calc_db_from_ratio(snr); - rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, + rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, rx_status.noise); /* If noise info not available, calculate signal quality indicator (%) * using just the dBm signal level. */ } else { rx_status.noise = priv->last_rx_noise; - rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, 0); + rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0); } IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", - rx_status.ssi, rx_status.noise, rx_status.signal, + rx_status.signal, rx_status.noise, rx_status.qual, rx_stats_sig_avg, rx_stats_noise_diff); header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); @@ -736,8 +736,8 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, IWL_DEBUG_STATS_LIMIT("[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", network_packet ? '*' : ' ', le16_to_cpu(rx_hdr->channel), - rx_status.ssi, rx_status.ssi, - rx_status.ssi, rx_status.rate_idx); + rx_status.signal, rx_status.signal, + rx_status.noise, rx_status.rate_idx); #ifdef CONFIG_IWL3945_DEBUG if (iwl3945_debug_level & (IWL_DL_RX)) @@ -748,7 +748,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, if (network_packet) { priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); priv->last_tsf = le64_to_cpu(rx_end->timestamp); - priv->last_rx_rssi = rx_status.ssi; + priv->last_rx_rssi = rx_status.signal; priv->last_rx_noise = rx_status.noise; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index fb96c62ad0ff..9fdc1405e853 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -886,6 +886,7 @@ struct iwl3945_priv { struct work_struct report_work; struct work_struct request_scan; struct work_struct beacon_update; + struct work_struct set_monitor; struct tasklet_struct irq_tasklet; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 29749e2a8ff0..ee55b283226b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -829,7 +829,7 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags) #define IWL49_NUM_QUEUES 16 /** - * struct iwl4965_tfd_frame_data + * struct iwl_tfd_frame_data * * Describes up to 2 buffers containing (contiguous) portions of a Tx frame. * Each buffer must be on dword boundary. @@ -848,7 +848,7 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags) * 31-20: Tx buffer 2 length (bytes) * 19- 0: Tx buffer 2 address bits [35:16] */ -struct iwl4965_tfd_frame_data { +struct iwl_tfd_frame_data { __le32 tb1_addr; __le32 val1; @@ -878,7 +878,7 @@ struct iwl4965_tfd_frame_data { /** - * struct iwl4965_tfd_frame + * struct iwl_tfd_frame * * Transmit Frame Descriptor (TFD) * @@ -905,7 +905,7 @@ struct iwl4965_tfd_frame_data { * * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx. */ -struct iwl4965_tfd_frame { +struct iwl_tfd_frame { __le32 val0; /* __le32 rsvd1:24; */ /* __le32 num_tbs:5; */ @@ -914,7 +914,7 @@ struct iwl4965_tfd_frame { #define IWL_num_tbs_SYM val0 /* __le32 rsvd2:1; */ /* __le32 padding:2; */ - struct iwl4965_tfd_frame_data pa[10]; + struct iwl_tfd_frame_data pa[10]; __le32 reserved; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 24dee00b0e85..8e3660ebba7d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -360,9 +360,9 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, unsigned long state; DECLARE_MAC_BUF(mac); - spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); + spin_lock_bh(&sta->lock); state = sta->ampdu_mlme.tid_state_tx[tid]; - spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); + spin_unlock_bh(&sta->lock); if (state == HT_AGG_STATE_IDLE && rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { @@ -662,7 +662,8 @@ static u16 rs_get_supported_rates(struct iwl4965_lq_sta *lq_sta, } } -static u16 rs_get_adjacent_rate(u8 index, u16 rate_mask, int rate_type) +static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask, + int rate_type) { u8 high = IWL_RATE_INVALID; u8 low = IWL_RATE_INVALID; @@ -763,7 +764,8 @@ static u32 rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta, goto out; } - high_low = rs_get_adjacent_rate(scale_index, rate_mask, tbl->lq_type); + high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask, + tbl->lq_type); low = high_low & 0xff; if (low == IWL_RATE_INVALID) @@ -990,7 +992,7 @@ out: * These control how long we stay using same modulation mode before * searching for a new mode. */ -static void rs_set_stay_in_table(u8 is_legacy, +static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, struct iwl4965_lq_sta *lq_sta) { IWL_DEBUG_RATE("we are staying in the same table\n"); @@ -1079,7 +1081,8 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, new_rate = high = low = start_hi = IWL_RATE_INVALID; for (; ;) { - high_low = rs_get_adjacent_rate(rate, rate_mask, tbl->lq_type); + high_low = rs_get_adjacent_rate(priv, rate, rate_mask, + tbl->lq_type); low = high_low & 0xff; high = (high_low >> 8) & 0xff; @@ -1565,7 +1568,9 @@ static void rs_stay_in_table(struct iwl4965_lq_sta *lq_sta) int i; int active_tbl; int flush_interval_passed = 0; + struct iwl_priv *priv; + priv = lq_sta->drv; active_tbl = lq_sta->active_tbl; tbl = &(lq_sta->lq_info[active_tbl]); @@ -1838,7 +1843,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, /* (Else) not in search of better modulation mode, try for better * starting rate, while staying in this mode. */ - high_low = rs_get_adjacent_rate(index, rate_scale_index_msk, + high_low = rs_get_adjacent_rate(priv, index, rate_scale_index_msk, tbl->lq_type); low = high_low & 0xff; high = (high_low >> 8) & 0xff; @@ -1998,7 +2003,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, (lq_sta->action_counter >= 1)) { lq_sta->action_counter = 0; IWL_DEBUG_RATE("LQ: STAY in legacy table\n"); - rs_set_stay_in_table(1, lq_sta); + rs_set_stay_in_table(priv, 1, lq_sta); } /* If we're in an HT mode, and all 3 mode switch actions @@ -2015,7 +2020,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, } #endif /*CONFIG_IWL4965_HT */ lq_sta->action_counter = 0; - rs_set_stay_in_table(0, lq_sta); + rs_set_stay_in_table(priv, 0, lq_sta); } /* @@ -2169,11 +2174,13 @@ out: rcu_read_unlock(); } -static void *rs_alloc_sta(void *priv, gfp_t gfp) +static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) { struct iwl4965_lq_sta *lq_sta; + struct iwl_priv *priv; int i, j; + priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE("create station rate scale window\n"); lq_sta = kzalloc(sizeof(struct iwl4965_lq_sta), gfp); @@ -2443,10 +2450,12 @@ static void rs_clear(void *priv_rate) IWL_DEBUG_RATE("leave\n"); } -static void rs_free_sta(void *priv, void *priv_sta) +static void rs_free_sta(void *priv_rate, void *priv_sta) { struct iwl4965_lq_sta *lq_sta = priv_sta; + struct iwl_priv *priv; + priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE("enter\n"); kfree(lq_sta); IWL_DEBUG_RATE("leave\n"); @@ -2462,6 +2471,9 @@ static int open_file_generic(struct inode *inode, struct file *file) static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, u32 *rate_n_flags, int index) { + struct iwl_priv *priv; + + priv = lq_sta->drv; if (lq_sta->dbg_fixed_rate) { if (index < 12) { *rate_n_flags = lq_sta->dbg_fixed_rate; @@ -2481,10 +2493,12 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct iwl4965_lq_sta *lq_sta = file->private_data; + struct iwl_priv *priv; char buf[64]; int buf_size; u32 parsed_rate; + priv = lq_sta->drv; memset(buf, 0, sizeof(buf)); buf_size = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, buf_size)) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 5d675e39bab8..17847f981e11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -50,11 +50,10 @@ static struct iwl_mod_params iwl4965_mod_params = { .num_of_queues = IWL49_NUM_QUEUES, .enable_qos = 1, .amsdu_size_8K = 1, + .restart_fw = 1, /* the rest are 0 by default */ }; -static void iwl4965_hw_card_show_info(struct iwl_priv *priv); - #ifdef CONFIG_IWL4965_HT static const u16 default_tid_to_tx_fifo[] = { @@ -224,6 +223,102 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) return 0; } +/** + * iwl4965_set_ucode_ptrs - Set uCode address location + * + * Tell initialization uCode where to find runtime uCode. + * + * BSM registers initially contain pointers to initialization uCode. + * We need to replace them to load runtime uCode inst and data, + * and to save runtime data when powering down. + */ +static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) +{ + dma_addr_t pinst; + dma_addr_t pdata; + unsigned long flags; + int ret = 0; + + /* bits 35:4 for 4965 */ + pinst = priv->ucode_code.p_addr >> 4; + pdata = priv->ucode_data_backup.p_addr >> 4; + + spin_lock_irqsave(&priv->lock, flags); + ret = iwl_grab_nic_access(priv); + if (ret) { + spin_unlock_irqrestore(&priv->lock, flags); + return ret; + } + + /* Tell bootstrap uCode where to find image to load */ + iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); + iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); + iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, + priv->ucode_data.len); + + /* Inst bytecount must be last to set up, bit 31 signals uCode + * that all new ptr/size info is in place */ + iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, + priv->ucode_code.len | BSM_DRAM_INST_LOAD); + iwl_release_nic_access(priv); + + spin_unlock_irqrestore(&priv->lock, flags); + + IWL_DEBUG_INFO("Runtime uCode pointers are set.\n"); + + return ret; +} + +/** + * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received + * + * Called after REPLY_ALIVE notification received from "initialize" uCode. + * + * The 4965 "initialize" ALIVE reply contains calibration data for: + * Voltage, temperature, and MIMO tx gain correction, now stored in priv + * (3945 does not contain this data). + * + * Tell "initialize" uCode to go ahead and load the runtime uCode. +*/ +static void iwl4965_init_alive_start(struct iwl_priv *priv) +{ + /* Check alive response for "valid" sign from uCode */ + if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { + /* We had an error bringing up the hardware, so take it + * all the way back down so we can try again */ + IWL_DEBUG_INFO("Initialize Alive failed.\n"); + goto restart; + } + + /* Bootstrap uCode has loaded initialize uCode ... verify inst image. + * This is a paranoid check, because we would not have gotten the + * "initialize" alive if code weren't properly loaded. */ + if (iwl_verify_ucode(priv)) { + /* Runtime instruction load was bad; + * take it all the way back down so we can try again */ + IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n"); + goto restart; + } + + /* Calculate temperature */ + priv->temperature = iwl4965_get_temperature(priv); + + /* Send pointers to protocol/runtime uCode image ... init code will + * load and launch runtime uCode, which will send us another "Alive" + * notification. */ + IWL_DEBUG_INFO("Initialization Alive received.\n"); + if (iwl4965_set_ucode_ptrs(priv)) { + /* Runtime instruction load won't happen; + * take it all the way back down so we can try again */ + IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n"); + goto restart; + } + return; + +restart: + queue_work(priv->workqueue, &priv->restart); +} + static int is_fat_channel(__le32 rxon_flags) { return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) || @@ -372,178 +467,31 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) return ret; } -static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) +static int iwl4965_disable_tx_fifo(struct iwl_priv *priv) { - int ret; unsigned long flags; - unsigned int rb_size; + int ret; spin_lock_irqsave(&priv->lock, flags); + ret = iwl_grab_nic_access(priv); - if (ret) { + if (unlikely(ret)) { + IWL_ERROR("Tx fifo reset failed"); spin_unlock_irqrestore(&priv->lock, flags); return ret; } - if (priv->cfg->mod_params->amsdu_size_8K) - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; - else - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; - - /* Stop Rx DMA */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - - /* Reset driver's Rx queue write index */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); - - /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - rxq->dma_addr >> 8); - - /* Tell device where in DRAM to update its Rx status */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, - (priv->shared_phys + - offsetof(struct iwl4965_shared, rb_closed)) >> 4); - - /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | - FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | - rb_size | - /* 0x10 << 4 | */ - (RX_QUEUE_SIZE_LOG << - FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); - - /* - * iwl_write32(priv,CSR_INT_COAL_REG,0); - */ - - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -/* Tell 4965 where to find the "keep warm" buffer */ -static int iwl4965_kw_init(struct iwl_priv *priv) -{ - unsigned long flags; - int rc; - - spin_lock_irqsave(&priv->lock, flags); - rc = iwl_grab_nic_access(priv); - if (rc) - goto out; - - iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, - priv->kw.dma_addr >> 4); + iwl_write_prph(priv, IWL49_SCD_TXFACT, 0); iwl_release_nic_access(priv); -out: spin_unlock_irqrestore(&priv->lock, flags); - return rc; -} - -static int iwl4965_kw_alloc(struct iwl_priv *priv) -{ - struct pci_dev *dev = priv->pci_dev; - struct iwl4965_kw *kw = &priv->kw; - - kw->size = IWL4965_KW_SIZE; /* TBW need set somewhere else */ - kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr); - if (!kw->v_addr) - return -ENOMEM; return 0; } -/** - * iwl4965_kw_free - Free the "keep warm" buffer - */ -static void iwl4965_kw_free(struct iwl_priv *priv) -{ - struct pci_dev *dev = priv->pci_dev; - struct iwl4965_kw *kw = &priv->kw; - - if (kw->v_addr) { - pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr); - memset(kw, 0, sizeof(*kw)); - } -} - -/** - * iwl4965_txq_ctx_reset - Reset TX queue context - * Destroys all DMA structures and initialise them again - * - * @param priv - * @return error code - */ -static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) -{ - int rc = 0; - int txq_id, slots_num; - unsigned long flags; - - iwl4965_kw_free(priv); - - /* Free all tx/cmd queues and keep-warm buffer */ - iwl4965_hw_txq_ctx_free(priv); - - /* Alloc keep-warm buffer */ - rc = iwl4965_kw_alloc(priv); - if (rc) { - IWL_ERROR("Keep Warm allocation failed"); - goto error_kw; - } - - spin_lock_irqsave(&priv->lock, flags); - - rc = iwl_grab_nic_access(priv); - if (unlikely(rc)) { - IWL_ERROR("TX reset failed"); - spin_unlock_irqrestore(&priv->lock, flags); - goto error_reset; - } - - /* Turn off all Tx DMA channels */ - iwl_write_prph(priv, IWL49_SCD_TXFACT, 0); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - /* Tell 4965 where to find the keep-warm buffer */ - rc = iwl4965_kw_init(priv); - if (rc) { - IWL_ERROR("kw_init failed\n"); - goto error_reset; - } - - /* Alloc and init all (default 16) Tx queues, - * including the command queue (#4) */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { - slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? - TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num, - txq_id); - if (rc) { - IWL_ERROR("Tx %d queue init failed\n", txq_id); - goto error; - } - } - - return rc; - - error: - iwl4965_hw_txq_ctx_free(priv); - error_reset: - iwl4965_kw_free(priv); - error_kw: - return rc; -} static int iwl4965_apm_init(struct iwl_priv *priv) { - unsigned long flags; int ret = 0; - spin_lock_irqsave(&priv->lock, flags); iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); @@ -575,7 +523,6 @@ static int iwl4965_apm_init(struct iwl_priv *priv) iwl_release_nic_access(priv); out: - spin_unlock_irqrestore(&priv->lock, flags); return ret; } @@ -621,59 +568,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } - -int iwl4965_hw_nic_init(struct iwl_priv *priv) -{ - unsigned long flags; - struct iwl4965_rx_queue *rxq = &priv->rxq; - int ret; - - /* nic_init */ - priv->cfg->ops->lib->apm_ops.init(priv); - - spin_lock_irqsave(&priv->lock, flags); - iwl_write32(priv, CSR_INT_COALESCING, 512 / 32); - spin_unlock_irqrestore(&priv->lock, flags); - - ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); - - priv->cfg->ops->lib->apm_ops.config(priv); - - iwl4965_hw_card_show_info(priv); - - /* end nic_init */ - - /* Allocate the RX queue, or reset if it is already allocated */ - if (!rxq->bd) { - ret = iwl4965_rx_queue_alloc(priv); - if (ret) { - IWL_ERROR("Unable to initialize Rx queue\n"); - return -ENOMEM; - } - } else - iwl4965_rx_queue_reset(priv, rxq); - - iwl4965_rx_replenish(priv); - - iwl4965_rx_init(priv, rxq); - - spin_lock_irqsave(&priv->lock, flags); - - rxq->need_update = 1; - iwl4965_rx_queue_update_write_ptr(priv, rxq); - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Allocate and init all Tx and Command queues */ - ret = iwl4965_txq_ctx_reset(priv); - if (ret) - return ret; - - set_bit(STATUS_INIT, &priv->status); - - return 0; -} - int iwl4965_hw_nic_stop_master(struct iwl_priv *priv) { int rc = 0; @@ -734,7 +628,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv) } /* Deallocate memory for all Tx queues */ - iwl4965_hw_txq_ctx_free(priv); + iwl_hw_txq_ctx_free(priv); } int iwl4965_hw_nic_reset(struct iwl_priv *priv) @@ -984,7 +878,7 @@ static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index) * NOTE: Acquire priv->lock before calling this function ! */ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, - struct iwl4965_tx_queue *txq, + struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry) { int txq_id = txq->q.id; @@ -1188,82 +1082,6 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv) return 0; } -/** - * iwl4965_hw_txq_ctx_free - Free TXQ Context - * - * Destroy all TX DMA queues and structures - */ -void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv) -{ - int txq_id; - - /* Tx queues */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) - iwl4965_tx_queue_free(priv, &priv->txq[txq_id]); - - /* Keep-warm buffer */ - iwl4965_kw_free(priv); -} - -/** - * iwl4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] - * - * Does NOT advance any TFD circular buffer read/write indexes - * Does NOT free the TFD itself (which is within circular buffer) - */ -int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq) -{ - struct iwl4965_tfd_frame *bd_tmp = (struct iwl4965_tfd_frame *)&txq->bd[0]; - struct iwl4965_tfd_frame *bd = &bd_tmp[txq->q.read_ptr]; - struct pci_dev *dev = priv->pci_dev; - int i; - int counter = 0; - int index, is_odd; - - /* Host command buffers stay mapped in memory, nothing to clean */ - if (txq->q.id == IWL_CMD_QUEUE_NUM) - return 0; - - /* Sanity check on number of chunks */ - counter = IWL_GET_BITS(*bd, num_tbs); - if (counter > MAX_NUM_OF_TBS) { - IWL_ERROR("Too many chunks: %i\n", counter); - /* @todo issue fatal error, it is quite serious situation */ - return 0; - } - - /* Unmap chunks, if any. - * TFD info for odd chunks is different format than for even chunks. */ - for (i = 0; i < counter; i++) { - index = i / 2; - is_odd = i & 0x1; - - if (is_odd) - pci_unmap_single( - dev, - IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) | - (IWL_GET_BITS(bd->pa[index], - tb2_addr_hi20) << 16), - IWL_GET_BITS(bd->pa[index], tb2_len), - PCI_DMA_TODEVICE); - - else if (i > 0) - pci_unmap_single(dev, - le32_to_cpu(bd->pa[index].tb1_addr), - IWL_GET_BITS(bd->pa[index], tb1_len), - PCI_DMA_TODEVICE); - - /* Free SKB, if any, for this chunk */ - if (txq->txb[txq->q.read_ptr].skb[i]) { - struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i]; - - dev_kfree_skb(skb); - txq->txb[txq->q.read_ptr].skb[i] = NULL; - } - } - return 0; -} - /* set card power command */ static int iwl4965_set_power(struct iwl_priv *priv, void *cmd) @@ -2186,7 +2004,7 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags); } -int iwl4965_hw_get_rx_read(struct iwl_priv *priv) +static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv) { struct iwl4965_shared *s = priv->shared_virt; return le32_to_cpu(s->rb_closed) & 0xFFF; @@ -2229,46 +2047,11 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, return (sizeof(*tx_beacon_cmd) + frame_size); } -/* - * Tell 4965 where to find circular buffer of Tx Frame Descriptors for - * given Tx queue, and enable the DMA channel used for that queue. - * - * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA - * channels supported in hardware. - */ -int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq) -{ - int rc; - unsigned long flags; - int txq_id = txq->q.id; - - spin_lock_irqsave(&priv->lock, flags); - rc = iwl_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } - - /* Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), - txq->q.dma_addr >> 8); - - /* Enable DMA channel, using same id as for TFD queue */ - iwl_write_direct32( - priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, dma_addr_t addr, u16 len) { int index, is_odd; - struct iwl4965_tfd_frame *tfd = ptr; + struct iwl_tfd_frame *tfd = ptr; u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs); /* Each TFD can point to a maximum 20 Tx buffers */ @@ -2298,18 +2081,6 @@ int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, return 0; } -static void iwl4965_hw_card_show_info(struct iwl_priv *priv) -{ - u16 hw_version = iwl_eeprom_query16(priv, EEPROM_4965_BOARD_REVISION); - - IWL_DEBUG_INFO("4965ABGN HW Version %u.%u.%u\n", - ((hw_version >> 8) & 0x0F), - ((hw_version >> 8) >> 4), (hw_version & 0x00FF)); - - IWL_DEBUG_INFO("4965ABGN PBA Number %.16s\n", - &priv->eeprom[EEPROM_4965_BOARD_PBA]); -} - static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) { priv->shared_virt = pci_alloc_consistent(priv->pci_dev, @@ -2320,6 +2091,8 @@ static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared)); + priv->rb_closed_offset = offsetof(struct iwl4965_shared, rb_closed); + return 0; } @@ -2336,7 +2109,7 @@ static void iwl4965_free_shared_mem(struct iwl_priv *priv) * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl4965_tx_queue *txq, + struct iwl_tx_queue *txq, u16 byte_cnt) { int len; @@ -2516,9 +2289,10 @@ static void iwl4965_rx_calc_noise(struct iwl_priv *priv) priv->last_rx_noise); } -void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) +void iwl4965_hw_rx_statistics(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { - struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; int change; s32 temp; @@ -2588,7 +2362,7 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv, struct ieee80211_rx_status *stats, u32 ampdu_status) { - s8 signal = stats->ssi; + s8 signal = stats->signal; s8 noise = 0; int rate = stats->rate_idx; u64 tsf = stats->mactime; @@ -2742,7 +2516,7 @@ static int iwl4965_set_decrypted_flag(struct iwl_p |