aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-4965.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-10-29 05:47:13 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-29 05:47:13 -0400
commited3f2e40f3d438f4a1ec0a898173116cb26f106a (patch)
treef50e1c5f5f3511539084d9529e592e3fb0352607 /drivers/net/wireless/iwlwifi/iwl-4965.c
parentfb699dfd426a189fe33b91586c15176a75c8aed0 (diff)
parentbd6b4442ff3cee73f73987cf0c0e66ea677aa075 (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/iwl-4965.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c172
1 files changed, 40 insertions, 132 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index f8eed9a4abc1..1ff465ad40d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -62,8 +62,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
62 62
63/* module parameters */ 63/* module parameters */
64static struct iwl_mod_params iwl4965_mod_params = { 64static struct iwl_mod_params iwl4965_mod_params = {
65 .num_of_queues = IWL49_NUM_QUEUES,
66 .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
67 .amsdu_size_8K = 1, 65 .amsdu_size_8K = 1,
68 .restart_fw = 1, 66 .restart_fw = 1,
69 /* the rest are 0 by default */ 67 /* the rest are 0 by default */
@@ -319,64 +317,13 @@ static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
319 iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); 317 iwl_write_prph(priv, IWL49_SCD_TXFACT, mask);
320} 318}
321 319
322static int iwl4965_apm_init(struct iwl_priv *priv)
323{
324 int ret = 0;
325
326 iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
327 CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
328
329 /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */
330 iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
331 CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
332
333 /* set "initialization complete" bit to move adapter
334 * D0U* --> D0A* state */
335 iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
336
337 /* wait for clock stabilization */
338 ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
339 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
340 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
341 if (ret < 0) {
342 IWL_DEBUG_INFO(priv, "Failed to init the card\n");
343 goto out;
344 }
345
346 /* enable DMA */
347 iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT |
348 APMG_CLK_VAL_BSM_CLK_RQT);
349
350 udelay(20);
351
352 /* disable L1-Active */
353 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
354 APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
355
356out:
357 return ret;
358}
359
360
361static void iwl4965_nic_config(struct iwl_priv *priv) 320static void iwl4965_nic_config(struct iwl_priv *priv)
362{ 321{
363 unsigned long flags; 322 unsigned long flags;
364 u16 radio_cfg; 323 u16 radio_cfg;
365 u16 lctl;
366 324
367 spin_lock_irqsave(&priv->lock, flags); 325 spin_lock_irqsave(&priv->lock, flags);
368 326
369 lctl = iwl_pcie_link_ctl(priv);
370
371 /* HW bug W/A - negligible power consumption */
372 /* L1-ASPM is enabled by BIOS */
373 if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN)
374 /* L1-ASPM enabled: disable L0S */
375 iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
376 else
377 /* L1-ASPM disabled: enable L0S */
378 iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
379
380 radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); 327 radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
381 328
382 /* write radio config values to register */ 329 /* write radio config values to register */
@@ -397,46 +344,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
397 spin_unlock_irqrestore(&priv->lock, flags); 344 spin_unlock_irqrestore(&priv->lock, flags);
398} 345}
399 346
400static int iwl4965_apm_reset(struct iwl_priv *priv)
401{
402 int ret = 0;
403
404 iwl_apm_stop_master(priv);
405
406
407 iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
408
409 udelay(10);
410
411 /* FIXME: put here L1A -L0S w/a */
412
413 iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
414
415 ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
416 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
417 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
418 if (ret < 0)
419 goto out;
420
421 udelay(10);
422
423 /* Enable DMA and BSM Clock */
424 iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT |
425 APMG_CLK_VAL_BSM_CLK_RQT);
426
427 udelay(10);
428
429 /* disable L1A */
430 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
431 APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
432
433 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
434 wake_up_interruptible(&priv->wait_command_queue);
435
436out:
437 return ret;
438}
439
440/* Reset differential Rx gains in NIC to prepare for chain noise calibration. 347/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
441 * Called after every association, but this runs only once! 348 * Called after every association, but this runs only once!
442 * ... once chain noise is calibrated the first time, it's good forever. */ 349 * ... once chain noise is calibrated the first time, it's good forever. */
@@ -526,18 +433,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv,
526 data->beacon_count = 0; 433 data->beacon_count = 0;
527} 434}
528 435
529static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
530 __le32 *tx_flags)
531{
532 if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
533 *tx_flags |= TX_CMD_FLG_RTS_MSK;
534 *tx_flags &= ~TX_CMD_FLG_CTS_MSK;
535 } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
536 *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
537 *tx_flags |= TX_CMD_FLG_CTS_MSK;
538 }
539}
540
541static void iwl4965_bg_txpower_work(struct work_struct *work) 436static void iwl4965_bg_txpower_work(struct work_struct *work)
542{ 437{
543 struct iwl_priv *priv = container_of(work, struct iwl_priv, 438 struct iwl_priv *priv = container_of(work, struct iwl_priv,
@@ -718,6 +613,10 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
718 613
719 .nrg_th_cck = 100, 614 .nrg_th_cck = 100,
720 .nrg_th_ofdm = 100, 615 .nrg_th_ofdm = 100,
616
617 .barker_corr_th_min = 190,
618 .barker_corr_th_min_mrc = 390,
619 .nrg_th_cca = 62,
721}; 620};
722 621
723static void iwl4965_set_ct_threshold(struct iwl_priv *priv) 622static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
@@ -734,19 +633,16 @@ static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
734 */ 633 */
735static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) 634static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
736{ 635{
636 if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
637 priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
638 priv->cfg->num_of_queues =
639 priv->cfg->mod_params->num_of_queues;
737 640
738 if ((priv->cfg->mod_params->num_of_queues > IWL49_NUM_QUEUES) || 641 priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
739 (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
740 IWL_ERR(priv,
741 "invalid queues_num, should be between %d and %d\n",
742 IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES);
743 return -EINVAL;
744 }
745
746 priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
747 priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; 642 priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
748 priv->hw_params.scd_bc_tbls_size = 643 priv->hw_params.scd_bc_tbls_size =
749 IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); 644 priv->cfg->num_of_queues *
645 sizeof(struct iwl4965_scd_bc_tbl);
750 priv->hw_params.tfd_size = sizeof(struct iwl_tfd); 646 priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
751 priv->hw_params.max_stations = IWL4965_STATION_COUNT; 647 priv->hw_params.max_stations = IWL4965_STATION_COUNT;
752 priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; 648 priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
@@ -757,10 +653,10 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
757 653
758 priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; 654 priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
759 655
760 priv->hw_params.tx_chains_num = 2; 656 priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
761 priv->hw_params.rx_chains_num = 2; 657 priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
762 priv->hw_params.valid_tx_ant = ANT_A | ANT_B; 658 priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
763 priv->hw_params.valid_rx_ant = ANT_A | ANT_B; 659 priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
764 if (priv->cfg->ops->lib->temp_ops.set_ct_kill) 660 if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
765 priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); 661 priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
766 662
@@ -1537,14 +1433,13 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
1537 return ret; 1433 return ret;
1538} 1434}
1539 1435
1540#ifdef IEEE80211_CONF_CHANNEL_SWITCH
1541static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) 1436static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1542{ 1437{
1543 int rc; 1438 int rc;
1544 u8 band = 0; 1439 u8 band = 0;
1545 bool is_ht40 = false; 1440 bool is_ht40 = false;
1546 u8 ctrl_chan_high = 0; 1441 u8 ctrl_chan_high = 0;
1547 struct iwl4965_channel_switch_cmd cmd = { 0 }; 1442 struct iwl4965_channel_switch_cmd cmd;
1548 const struct iwl_channel_info *ch_info; 1443 const struct iwl_channel_info *ch_info;
1549 1444
1550 band = priv->band == IEEE80211_BAND_2GHZ; 1445 band = priv->band == IEEE80211_BAND_2GHZ;
@@ -1565,8 +1460,11 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1565 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); 1460 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
1566 if (ch_info) 1461 if (ch_info)
1567 cmd.expect_beacon = is_channel_radar(ch_info); 1462 cmd.expect_beacon = is_channel_radar(ch_info);
1568 else 1463 else {
1569 cmd.expect_beacon = 1; 1464 IWL_ERR(priv, "invalid channel switch from %u to %u\n",
1465 priv->active_rxon.channel, channel);
1466 return -EFAULT;
1467 }
1570 1468
1571 rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, 1469 rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40,
1572 ctrl_chan_high, &cmd.tx_power); 1470 ctrl_chan_high, &cmd.tx_power);
@@ -1578,7 +1476,6 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1578 rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); 1476 rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
1579 return rc; 1477 return rc;
1580} 1478}
1581#endif
1582 1479
1583/** 1480/**
1584 * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array 1481 * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
@@ -1775,11 +1672,13 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
1775 u16 ssn_idx, u8 tx_fifo) 1672 u16 ssn_idx, u8 tx_fifo)
1776{ 1673{
1777 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || 1674 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
1778 (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { 1675 (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
1676 <= txq_id)) {
1779 IWL_WARN(priv, 1677 IWL_WARN(priv,
1780 "queue number out of range: %d, must be %d to %d\n", 1678 "queue number out of range: %d, must be %d to %d\n",
1781 txq_id, IWL49_FIRST_AMPDU_QUEUE, 1679 txq_id, IWL49_FIRST_AMPDU_QUEUE,
1782 IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); 1680 IWL49_FIRST_AMPDU_QUEUE +
1681 priv->cfg->num_of_ampdu_queues - 1);
1783 return -EINVAL; 1682 return -EINVAL;
1784 } 1683 }
1785 1684
@@ -1840,11 +1739,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1840 u16 ra_tid; 1739 u16 ra_tid;
1841 1740
1842 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || 1741 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
1843 (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { 1742 (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
1743 <= txq_id)) {
1844 IWL_WARN(priv, 1744 IWL_WARN(priv,
1845 "queue number out of range: %d, must be %d to %d\n", 1745 "queue number out of range: %d, must be %d to %d\n",
1846 txq_id, IWL49_FIRST_AMPDU_QUEUE, 1746 txq_id, IWL49_FIRST_AMPDU_QUEUE,
1847 IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); 1747 IWL49_FIRST_AMPDU_QUEUE +
1748 priv->cfg->num_of_ampdu_queues - 1);
1848 return -EINVAL; 1749 return -EINVAL;
1849 } 1750 }
1850 1751
@@ -2048,7 +1949,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
2048static void iwl4965_rx_reply_tx(struct iwl_priv *priv, 1949static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2049 struct iwl_rx_mem_buffer *rxb) 1950 struct iwl_rx_mem_buffer *rxb)
2050{ 1951{
2051 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; 1952 struct iwl_rx_packet *pkt = rxb_addr(rxb);
2052 u16 sequence = le16_to_cpu(pkt->hdr.sequence); 1953 u16 sequence = le16_to_cpu(pkt->hdr.sequence);
2053 int txq_id = SEQ_TO_QUEUE(sequence); 1954 int txq_id = SEQ_TO_QUEUE(sequence);
2054 int index = SEQ_TO_INDEX(sequence); 1955 int index = SEQ_TO_INDEX(sequence);
@@ -2249,7 +2150,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
2249 .build_addsta_hcmd = iwl4965_build_addsta_hcmd, 2150 .build_addsta_hcmd = iwl4965_build_addsta_hcmd,
2250 .chain_noise_reset = iwl4965_chain_noise_reset, 2151 .chain_noise_reset = iwl4965_chain_noise_reset,
2251 .gain_computation = iwl4965_gain_computation, 2152 .gain_computation = iwl4965_gain_computation,
2252 .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, 2153 .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
2253 .calc_rssi = iwl4965_calc_rssi, 2154 .calc_rssi = iwl4965_calc_rssi,
2254}; 2155};
2255 2156
@@ -2271,9 +2172,9 @@ static struct iwl_lib_ops iwl4965_lib = {
2271 .load_ucode = iwl4965_load_bsm, 2172 .load_ucode = iwl4965_load_bsm,
2272 .dump_nic_event_log = iwl_dump_nic_event_log, 2173 .dump_nic_event_log = iwl_dump_nic_event_log,
2273 .dump_nic_error_log = iwl_dump_nic_error_log, 2174 .dump_nic_error_log = iwl_dump_nic_error_log,
2175 .set_channel_switch = iwl4965_hw_channel_switch,
2274 .apm_ops = { 2176 .apm_ops = {
2275 .init = iwl4965_apm_init, 2177 .init = iwl_apm_init,
2276 .reset = iwl4965_apm_reset,
2277 .stop = iwl_apm_stop, 2178 .stop = iwl_apm_stop,
2278 .config = iwl4965_nic_config, 2179 .config = iwl4965_nic_config,
2279 .set_pwr_src = iwl_set_pwr_src, 2180 .set_pwr_src = iwl_set_pwr_src,
@@ -2323,7 +2224,14 @@ struct iwl_cfg iwl4965_agn_cfg = {
2323 .eeprom_ver = EEPROM_4965_EEPROM_VERSION, 2224 .eeprom_ver = EEPROM_4965_EEPROM_VERSION,
2324 .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, 2225 .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
2325 .ops = &iwl4965_ops, 2226 .ops = &iwl4965_ops,
2227 .num_of_queues = IWL49_NUM_QUEUES,
2228 .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
2326 .mod_params = &iwl4965_mod_params, 2229 .mod_params = &iwl4965_mod_params,
2230 .valid_tx_ant = ANT_AB,
2231 .valid_rx_ant = ANT_AB,
2232 .pll_cfg_val = 0,
2233 .set_l0s = true,
2234 .use_bsm = true,
2327 .use_isr_legacy = true, 2235 .use_isr_legacy = true,
2328 .ht_greenfield_support = false, 2236 .ht_greenfield_support = false,
2329 .broken_powersave = true, 2237 .broken_powersave = true,