aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorReinette Chatre <reinette.chatre@intel.com>2008-01-23 13:15:18 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-31 22:26:41 -0500
commit849e0dcea6b28a900e4743c1ada6db752fced5a9 (patch)
tree91abfca69729ef1b633012412012b7bf64f7610f /drivers
parent75849d287ce5d75f3c79f153eaf74759ae95511f (diff)
iwlwifi: initialize geo/channel information during probe
The geo/channel information is obtained from the EEPROM, which is read during probe. We can thus set up channel information at this time. This helps us to support ioctl commands that rely on this before the interface is brought up. Clearly matches _init_channel_map with _free_channel_map and _init_geos with _free_geos to ensure functions calling these routines can also call their cleanup routines. Fixes a few bugs: - if channel information is not available when ioctl commands are issued then we get a NULL pointer oops. Having channel information set up during probe we can deal with ioctl commands without requiring interface to be brought up. This fixes bug: http://www.bughost.org/bugzilla/show_bug.cgi?id=1552 - Fix potential problem if user triggers probe/remove/probe sequence. The value of priv->channel_count was used to determine if channel map is set up. This value was never reset when channel map was removed. - Fix memory leak: priv->modes need to be freed when device removed. Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c54
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c54
2 files changed, 80 insertions, 28 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 0bfb925ebda8..f96a1a2e90f4 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5146,6 +5146,15 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
5146 return 0; 5146 return 0;
5147} 5147}
5148 5148
5149/*
5150 * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map
5151 */
5152static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
5153{
5154 kfree(priv->channel_info);
5155 priv->channel_count = 0;
5156}
5157
5149/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after 5158/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
5150 * sending probe req. This should be set long enough to hear probe responses 5159 * sending probe req. This should be set long enough to hear probe responses
5151 * from more than one AP. */ 5160 * from more than one AP. */
@@ -5471,6 +5480,17 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
5471 return 0; 5480 return 0;
5472} 5481}
5473 5482
5483/*
5484 * iwl3945_free_geos - undo allocations in iwl3945_init_geos
5485 */
5486static void iwl3945_free_geos(struct iwl3945_priv *priv)
5487{
5488 kfree(priv->modes);
5489 kfree(priv->ieee_channels);
5490 kfree(priv->ieee_rates);
5491 clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
5492}
5493
5474/****************************************************************************** 5494/******************************************************************************
5475 * 5495 *
5476 * uCode download functions 5496 * uCode download functions
@@ -6130,15 +6150,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
6130 /* Clear out the uCode error bit if it is set */ 6150 /* Clear out the uCode error bit if it is set */
6131 clear_bit(STATUS_FW_ERROR, &priv->status); 6151 clear_bit(STATUS_FW_ERROR, &priv->status);
6132 6152
6133 rc = iwl3945_init_channel_map(priv);
6134 if (rc) {
6135 IWL_ERROR("initializing regulatory failed: %d\n", rc);
6136 return;
6137 }
6138
6139 iwl3945_init_geos(priv);
6140 iwl3945_reset_channel_flag(priv);
6141
6142 if (iwl3945_is_rfkill(priv)) 6153 if (iwl3945_is_rfkill(priv))
6143 return; 6154 return;
6144 6155
@@ -8614,11 +8625,24 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8614 IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); 8625 IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
8615 SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); 8626 SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
8616 8627
8628 err = iwl3945_init_channel_map(priv);
8629 if (err) {
8630 IWL_ERROR("initializing regulatory failed: %d\n", err);
8631 goto out_remove_sysfs;
8632 }
8633
8634 err = iwl3945_init_geos(priv);
8635 if (err) {
8636 IWL_ERROR("initializing geos failed: %d\n", err);
8637 goto out_free_channel_map;
8638 }
8639 iwl3945_reset_channel_flag(priv);
8640
8617 iwl3945_rate_control_register(priv->hw); 8641 iwl3945_rate_control_register(priv->hw);
8618 err = ieee80211_register_hw(priv->hw); 8642 err = ieee80211_register_hw(priv->hw);
8619 if (err) { 8643 if (err) {
8620 IWL_ERROR("Failed to register network device (error %d)\n", err); 8644 IWL_ERROR("Failed to register network device (error %d)\n", err);
8621 goto out_remove_sysfs; 8645 goto out_free_geos;
8622 } 8646 }
8623 8647
8624 priv->hw->conf.beacon_int = 100; 8648 priv->hw->conf.beacon_int = 100;
@@ -8628,6 +8652,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8628 8652
8629 return 0; 8653 return 0;
8630 8654
8655 out_free_geos:
8656 iwl3945_free_geos(priv);
8657 out_free_channel_map:
8658 iwl3945_free_channel_map(priv);
8631 out_remove_sysfs: 8659 out_remove_sysfs:
8632 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); 8660 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
8633 8661
@@ -8702,10 +8730,8 @@ static void iwl3945_pci_remove(struct pci_dev *pdev)
8702 pci_disable_device(pdev); 8730 pci_disable_device(pdev);
8703 pci_set_drvdata(pdev, NULL); 8731 pci_set_drvdata(pdev, NULL);
8704 8732
8705 kfree(priv->channel_info); 8733 iwl3945_free_channel_map(priv);
8706 8734 iwl3945_free_geos(priv);
8707 kfree(priv->ieee_channels);
8708 kfree(priv->ieee_rates);
8709 8735
8710 if (priv->ibss_beacon) 8736 if (priv->ibss_beacon)
8711 dev_kfree_skb(priv->ibss_beacon); 8737 dev_kfree_skb(priv->ibss_beacon);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index ac8967bc7c59..77c635287035 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -5576,6 +5576,15 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv)
5576 return 0; 5576 return 0;
5577} 5577}
5578 5578
5579/*
5580 * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map
5581 */
5582static void iwl4965_free_channel_map(struct iwl4965_priv *priv)
5583{
5584 kfree(priv->channel_info);
5585 priv->channel_count = 0;
5586}
5587
5579/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after 5588/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
5580 * sending probe req. This should be set long enough to hear probe responses 5589 * sending probe req. This should be set long enough to hear probe responses
5581 * from more than one AP. */ 5590 * from more than one AP. */
@@ -5909,6 +5918,17 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv)
5909 return 0; 5918 return 0;
5910} 5919}
5911 5920
5921/*
5922 * iwl4965_free_geos - undo allocations in iwl4965_init_geos
5923 */
5924static void iwl4965_free_geos(struct iwl4965_priv *priv)
5925{
5926 kfree(priv->modes);
5927 kfree(priv->ieee_channels);
5928 kfree(priv->ieee_rates);
5929 clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
5930}
5931
5912/****************************************************************************** 5932/******************************************************************************
5913 * 5933 *
5914 * uCode download functions 5934 * uCode download functions
@@ -6560,15 +6580,6 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
6560 /* Clear out the uCode error bit if it is set */ 6580 /* Clear out the uCode error bit if it is set */
6561 clear_bit(STATUS_FW_ERROR, &priv->status); 6581 clear_bit(STATUS_FW_ERROR, &priv->status);
6562 6582
6563 rc = iwl4965_init_channel_map(priv);
6564 if (rc) {
6565 IWL_ERROR("initializing regulatory failed: %d\n", rc);
6566 return;
6567 }
6568
6569 iwl4965_init_geos(priv);
6570 iwl4965_reset_channel_flag(priv);
6571
6572 if (iwl4965_is_rfkill(priv)) 6583 if (iwl4965_is_rfkill(priv))
6573 return; 6584 return;
6574 6585
@@ -9198,11 +9209,24 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
9198 IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); 9209 IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
9199 SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); 9210 SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
9200 9211
9212 err = iwl4965_init_channel_map(priv);
9213 if (err) {
9214 IWL_ERROR("initializing regulatory failed: %d\n", err);
9215 goto out_remove_sysfs;
9216 }
9217
9218 err = iwl4965_init_geos(priv);
9219 if (err) {
9220 IWL_ERROR("initializing geos failed: %d\n", err);
9221 goto out_free_channel_map;
9222 }
9223 iwl4965_reset_channel_flag(priv);
9224
9201 iwl4965_rate_control_register(priv->hw); 9225 iwl4965_rate_control_register(priv->hw);
9202 err = ieee80211_register_hw(priv->hw); 9226 err = ieee80211_register_hw(priv->hw);
9203 if (err) { 9227 if (err) {
9204 IWL_ERROR("Failed to register network device (error %d)\n", err); 9228 IWL_ERROR("Failed to register network device (error %d)\n", err);
9205 goto out_remove_sysfs; 9229 goto out_free_geos;
9206 } 9230 }
9207 9231
9208 priv->hw->conf.beacon_int = 100; 9232 priv->hw->conf.beacon_int = 100;
@@ -9212,6 +9236,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
9212 9236
9213 return 0; 9237 return 0;
9214 9238
9239 out_free_geos:
9240 iwl4965_free_geos(priv);
9241 out_free_channel_map:
9242 iwl4965_free_channel_map(priv);
9215 out_remove_sysfs: 9243 out_remove_sysfs:
9216 sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); 9244 sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
9217 9245
@@ -9286,10 +9314,8 @@ static void iwl4965_pci_remove(struct pci_dev *pdev)
9286 pci_disable_device(pdev); 9314 pci_disable_device(pdev);
9287 pci_set_drvdata(pdev, NULL); 9315 pci_set_drvdata(pdev, NULL);
9288 9316
9289 kfree(priv->channel_info); 9317 iwl4965_free_channel_map(priv);
9290 9318 iwl4965_free_geos(priv);
9291 kfree(priv->ieee_channels);
9292 kfree(priv->ieee_rates);
9293 9319
9294 if (priv->ibss_beacon) 9320 if (priv->ibss_beacon)
9295 dev_kfree_skb(priv->ibss_beacon); 9321 dev_kfree_skb(priv->ibss_beacon);