aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-06 00:41:53 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-06 00:41:53 -0400
commitf3032be921cd126615ce3bfd7084e3d319f3f892 (patch)
treec2ce874f2ab7f107dddf7b854772e0f3b64d35a1 /drivers/net/wireless/iwlwifi/iwl3945-base.c
parent70c03b49b80ba3634958acc31853771019c0ebd3 (diff)
parent18d7260527ce7c0d0a177afdf92d8f868f50b067 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c245
1 files changed, 176 insertions, 69 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 92d1b2e312d4..3bc2644039f0 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -970,7 +970,7 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv)
970{ 970{
971 971
972 /* These items are only settable from the full RXON command */ 972 /* These items are only settable from the full RXON command */
973 if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) || 973 if (!(iwl3945_is_associated(priv)) ||
974 compare_ether_addr(priv->staging_rxon.bssid_addr, 974 compare_ether_addr(priv->staging_rxon.bssid_addr,
975 priv->active_rxon.bssid_addr) || 975 priv->active_rxon.bssid_addr) ||
976 compare_ether_addr(priv->staging_rxon.node_addr, 976 compare_ether_addr(priv->staging_rxon.node_addr,
@@ -2312,7 +2312,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
2312#endif 2312#endif
2313 2313
2314 ch_info = iwl3945_get_channel_info(priv, priv->band, 2314 ch_info = iwl3945_get_channel_info(priv, priv->band,
2315 le16_to_cpu(priv->staging_rxon.channel)); 2315 le16_to_cpu(priv->active_rxon.channel));
2316 2316
2317 if (!ch_info) 2317 if (!ch_info)
2318 ch_info = &priv->channel_info[0]; 2318 ch_info = &priv->channel_info[0];
@@ -2539,6 +2539,11 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
2539 iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); 2539 iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
2540 return priv->hw_setting.bcast_sta_id; 2540 return priv->hw_setting.bcast_sta_id;
2541 } 2541 }
2542 /* If we are in monitor mode, use BCAST. This is required for
2543 * packet injection. */
2544 case IEEE80211_IF_TYPE_MNTR:
2545 return priv->hw_setting.bcast_sta_id;
2546
2542 default: 2547 default:
2543 IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); 2548 IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
2544 return priv->hw_setting.bcast_sta_id; 2549 return priv->hw_setting.bcast_sta_id;
@@ -2578,11 +2583,6 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
2578 goto drop_unlock; 2583 goto drop_unlock;
2579 } 2584 }
2580 2585
2581 if (!priv->vif) {
2582 IWL_DEBUG_DROP("Dropping - !priv->vif\n");
2583 goto drop_unlock;
2584 }
2585
2586 if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) { 2586 if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
2587 IWL_ERROR("ERROR: No TX rate available.\n"); 2587 IWL_ERROR("ERROR: No TX rate available.\n");
2588 goto drop_unlock; 2588 goto drop_unlock;
@@ -2603,9 +2603,10 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
2603#endif 2603#endif
2604 2604
2605 /* drop all data frame if we are not associated */ 2605 /* drop all data frame if we are not associated */
2606 if ((!iwl3945_is_associated(priv) || 2606 if (ieee80211_is_data(fc) &&
2607 ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id)) && 2607 (priv->iw_mode != IEEE80211_IF_TYPE_MNTR) && /* packet injection */
2608 ieee80211_is_data(fc)) { 2608 (!iwl3945_is_associated(priv) ||
2609 ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id))) {
2609 IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); 2610 IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
2610 goto drop_unlock; 2611 goto drop_unlock;
2611 } 2612 }
@@ -5921,7 +5922,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
5921 test_bit(STATUS_GEO_CONFIGURED, &priv->status) << 5922 test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
5922 STATUS_GEO_CONFIGURED | 5923 STATUS_GEO_CONFIGURED |
5923 test_bit(STATUS_IN_SUSPEND, &priv->status) << 5924 test_bit(STATUS_IN_SUSPEND, &priv->status) <<
5924 STATUS_IN_SUSPEND; 5925 STATUS_IN_SUSPEND |
5926 test_bit(STATUS_EXIT_PENDING, &priv->status) <<
5927 STATUS_EXIT_PENDING;
5925 goto exit; 5928 goto exit;
5926 } 5929 }
5927 5930
@@ -5936,7 +5939,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
5936 test_bit(STATUS_IN_SUSPEND, &priv->status) << 5939 test_bit(STATUS_IN_SUSPEND, &priv->status) <<
5937 STATUS_IN_SUSPEND | 5940 STATUS_IN_SUSPEND |
5938 test_bit(STATUS_FW_ERROR, &priv->status) << 5941 test_bit(STATUS_FW_ERROR, &priv->status) <<
5939 STATUS_FW_ERROR; 5942 STATUS_FW_ERROR |
5943 test_bit(STATUS_EXIT_PENDING, &priv->status) <<
5944 STATUS_EXIT_PENDING;
5940 5945
5941 spin_lock_irqsave(&priv->lock, flags); 5946 spin_lock_irqsave(&priv->lock, flags);
5942 iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 5947 iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -6008,11 +6013,12 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
6008 else { 6013 else {
6009 set_bit(STATUS_RF_KILL_HW, &priv->status); 6014 set_bit(STATUS_RF_KILL_HW, &priv->status);
6010 if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { 6015 if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
6016 iwl3945_rfkill_set_hw_state(priv);
6011 IWL_WARNING("Radio disabled by HW RF Kill switch\n"); 6017 IWL_WARNING("Radio disabled by HW RF Kill switch\n");
6012 return -ENODEV; 6018 return -ENODEV;
6013 } 6019 }
6014 } 6020 }
6015 6021 iwl3945_rfkill_set_hw_state(priv);
6016 iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); 6022 iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
6017 6023
6018 rc = iwl3945_hw_nic_init(priv); 6024 rc = iwl3945_hw_nic_init(priv);
@@ -6068,6 +6074,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
6068 6074
6069 set_bit(STATUS_EXIT_PENDING, &priv->status); 6075 set_bit(STATUS_EXIT_PENDING, &priv->status);
6070 __iwl3945_down(priv); 6076 __iwl3945_down(priv);
6077 clear_bit(STATUS_EXIT_PENDING, &priv->status);
6071 6078
6072 /* tried to restart and config the device for as long as our 6079 /* tried to restart and config the device for as long as our
6073 * patience could withstand */ 6080 * patience could withstand */
@@ -6135,6 +6142,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
6135 "Kill switch must be turned off for " 6142 "Kill switch must be turned off for "
6136 "wireless networking to work.\n"); 6143 "wireless networking to work.\n");
6137 } 6144 }
6145
6146 iwl3945_rfkill_set_hw_state(priv);
6138 mutex_unlock(&priv->mutex); 6147 mutex_unlock(&priv->mutex);
6139} 6148}
6140 6149
@@ -6685,11 +6694,6 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
6685 6694
6686 IWL_DEBUG_MAC80211("enter\n"); 6695 IWL_DEBUG_MAC80211("enter\n");
6687 6696
6688 if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
6689 IWL_DEBUG_MAC80211("leave - monitor\n");
6690 return -1;
6691 }
6692
6693 IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, 6697 IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
6694 ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); 6698 ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
6695 6699
@@ -6836,7 +6840,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
6836 return; 6840 return;
6837 6841
6838 /* The following should be done only at AP bring up */ 6842 /* The following should be done only at AP bring up */
6839 if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) { 6843 if (!(iwl3945_is_associated(priv))) {
6840 6844
6841 /* RXON - unassoc (to set timing command) */ 6845 /* RXON - unassoc (to set timing command) */
6842 priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; 6846 priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@@ -6998,26 +7002,18 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
6998 unsigned int *total_flags, 7002 unsigned int *total_flags,
6999 int mc_count, struct dev_addr_list *mc_list) 7003 int mc_count, struct dev_addr_list *mc_list)
7000{ 7004{
7001 /*
7002 * XXX: dummy
7003 * see also iwl3945_connection_init_rx_config
7004 */
7005 struct iwl3945_priv *priv = hw->priv; 7005 struct iwl3945_priv *priv = hw->priv;
7006 int new_flags = 0; 7006
7007 if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { 7007 if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
7008 if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { 7008 IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
7009 IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", 7009 IEEE80211_IF_TYPE_MNTR,
7010 IEEE80211_IF_TYPE_MNTR, 7010 changed_flags, *total_flags);
7011 changed_flags, *total_flags); 7011 /* queue work 'cuz mac80211 is holding a lock which
7012 /* queue work 'cuz mac80211 is holding a lock which 7012 * prevents us from issuing (synchronous) f/w cmds */
7013 * prevents us from issuing (synchronous) f/w cmds */ 7013 queue_work(priv->workqueue, &priv->set_monitor);
7014 queue_work(priv->workqueue, &priv->set_monitor);
7015 new_flags &= FIF_PROMISC_IN_BSS |
7016 FIF_OTHER_BSS |
7017 FIF_ALLMULTI;
7018 }
7019 } 7014 }
7020 *total_flags = new_flags; 7015 *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
7016 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
7021} 7017}
7022 7018
7023static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, 7019static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
@@ -7412,37 +7408,6 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
7412 7408
7413#endif /* CONFIG_IWL3945_DEBUG */ 7409#endif /* CONFIG_IWL3945_DEBUG */
7414 7410
7415static ssize_t show_rf_kill(struct device *d,
7416 struct device_attribute *attr, char *buf)
7417{
7418 /*
7419 * 0 - RF kill not enabled
7420 * 1 - SW based RF kill active (sysfs)
7421 * 2 - HW based RF kill active
7422 * 3 - Both HW and SW based RF kill active
7423 */
7424 struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
7425 int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
7426 (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
7427
7428 return sprintf(buf, "%i\n", val);
7429}
7430
7431static ssize_t store_rf_kill(struct device *d,
7432 struct device_attribute *attr,
7433 const char *buf, size_t count)
7434{
7435 struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
7436
7437 mutex_lock(&priv->mutex);
7438 iwl3945_radio_kill_sw(priv, buf[0] == '1');
7439 mutex_unlock(&priv->mutex);
7440
7441 return count;
7442}
7443
7444static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
7445
7446static ssize_t show_temperature(struct device *d, 7411static ssize_t show_temperature(struct device *d,
7447 struct device_attribute *attr, char *buf) 7412 struct device_attribute *attr, char *buf)
7448{ 7413{
@@ -7928,7 +7893,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
7928#endif 7893#endif
7929 &dev_attr_power_level.attr, 7894 &dev_attr_power_level.attr,
7930 &dev_attr_retry_rate.attr, 7895 &dev_attr_retry_rate.attr,
7931 &dev_attr_rf_kill.attr,
7932 &dev_attr_rs_window.attr, 7896 &dev_attr_rs_window.attr,
7933 &dev_attr_statistics.attr, 7897 &dev_attr_statistics.attr,
7934 &dev_attr_status.attr, 7898 &dev_attr_status.attr,
@@ -8169,6 +8133,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8169 pci_save_state(pdev); 8133 pci_save_state(pdev);
8170 pci_disable_device(pdev); 8134 pci_disable_device(pdev);
8171 8135
8136 err = iwl3945_rfkill_init(priv);
8137 if (err)
8138 IWL_ERROR("Unable to initialize RFKILL system. "
8139 "Ignoring error: %d\n", err);
8140
8172 return 0; 8141 return 0;
8173 8142
8174 out_free_geos: 8143 out_free_geos:
@@ -8231,6 +8200,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
8231 8200
8232 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); 8201 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
8233 8202
8203 iwl3945_rfkill_unregister(priv);
8234 iwl3945_dealloc_ucode_pci(priv); 8204 iwl3945_dealloc_ucode_pci(priv);
8235 8205
8236 if (priv->rxq.bd) 8206 if (priv->rxq.bd)
@@ -8299,6 +8269,143 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
8299 8269
8300#endif /* CONFIG_PM */ 8270#endif /* CONFIG_PM */
8301 8271
8272/*************** RFKILL FUNCTIONS **********/
8273#ifdef CONFIG_IWLWIFI_RFKILL
8274/* software rf-kill from user */
8275static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
8276{
8277 struct iwl3945_priv *priv = data;
8278 int err = 0;
8279
8280 if (!priv->rfkill_mngr.rfkill)
8281 return 0;
8282
8283 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
8284 return 0;
8285
8286 IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
8287 mutex_lock(&priv->mutex);
8288
8289 switch (state) {
8290 case RFKILL_STATE_UNBLOCKED:
8291 iwl3945_radio_kill_sw(priv, 0);
8292 /* if HW rf-kill is set dont allow ON state */
8293 if (iwl3945_is_rfkill(priv))
8294 err = -EBUSY;
8295 break;
8296 case RFKILL_STATE_SOFT_BLOCKED:
8297 iwl3945_radio_kill_sw(priv, 1);
8298 if (!iwl3945_is_rfkill(priv))
8299 err = -EBUSY;
8300 break;
8301 default:
8302 IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
8303 break;
8304 }
8305 mutex_unlock(&priv->mutex);
8306
8307 return err;
8308}
8309
8310int iwl3945_rfkill_init(struct iwl3945_priv *priv)
8311{
8312 struct device *device = wiphy_dev(priv->hw->wiphy);
8313 int ret = 0;
8314
8315 BUG_ON(device == NULL);
8316
8317 IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
8318 priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
8319 if (!priv->rfkill_mngr.rfkill) {
8320 IWL_ERROR("Unable to allocate rfkill device.\n");
8321 ret = -ENOMEM;
8322 goto error;
8323 }
8324
8325 priv->rfkill_mngr.rfkill->name = priv->cfg->name;
8326 priv->rfkill_mngr.rfkill->data = priv;
8327 priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
8328 priv->rfkill_mngr.rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill;
8329 priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
8330
8331 priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
8332 priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
8333
8334 priv->rfkill_mngr.input_dev = input_allocate_device();
8335 if (!priv->rfkill_mngr.input_dev) {
8336 IWL_ERROR("Unable to allocate rfkill input device.\n");
8337 ret = -ENOMEM;
8338 goto freed_rfkill;
8339 }
8340
8341 priv->rfkill_mngr.input_dev->name = priv->cfg->name;
8342 priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy);
8343 priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST;
8344 priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor;
8345 priv->rfkill_mngr.input_dev->dev.parent = device;
8346 priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY);
8347 set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit);
8348
8349 ret = rfkill_register(priv->rfkill_mngr.rfkill);
8350 if (ret) {
8351 IWL_ERROR("Unable to register rfkill: %d\n", ret);
8352 goto free_input_dev;
8353 }
8354
8355 ret = input_register_device(priv->rfkill_mngr.input_dev);
8356 if (ret) {
8357 IWL_ERROR("Unable to register rfkill input device: %d\n", ret);
8358 goto unregister_rfkill;
8359 }
8360
8361 IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
8362 return ret;
8363
8364unregister_rfkill:
8365 rfkill_unregister(priv->rfkill_mngr.rfkill);
8366 priv->rfkill_mngr.rfkill = NULL;
8367
8368free_input_dev:
8369 input_free_device(priv->rfkill_mngr.input_dev);
8370 priv->rfkill_mngr.input_dev = NULL;
8371
8372freed_rfkill:
8373 if (priv->rfkill_mngr.rfkill != NULL)
8374 rfkill_free(priv->rfkill_mngr.rfkill);
8375 priv->rfkill_mngr.rfkill = NULL;
8376
8377error:
8378 IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
8379 return ret;
8380}
8381
8382void iwl3945_rfkill_unregister(struct iwl3945_priv *priv)
8383{
8384
8385 if (priv->rfkill_mngr.input_dev)
8386 input_unregister_device(priv->rfkill_mngr.input_dev);
8387
8388 if (priv->rfkill_mngr.rfkill)
8389 rfkill_unregister(priv->rfkill_mngr.rfkill);
8390
8391 priv->rfkill_mngr.input_dev = NULL;
8392 priv->rfkill_mngr.rfkill = NULL;
8393}
8394
8395/* set rf-kill to the right state. */
8396void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv)
8397{
8398
8399 if (!priv->rfkill_mngr.rfkill)
8400 return;
8401
8402 if (!iwl3945_is_rfkill(priv))
8403 priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
8404 else
8405 priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
8406}
8407#endif
8408
8302/***************************************************************************** 8409/*****************************************************************************
8303 * 8410 *
8304 * driver and module entry point 8411 * driver and module entry point