Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ba87956 authored by Tomas Winkler's avatar Tomas Winkler Committed by John W. Linville
Browse files

iwlwifi: refactor pci prob flow



This patch refactores pci prob flow. It moves mac80211 registration
to the end, otherwise there is a race between error path in pci_probe
and mac_start.

Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 445c2dff
Loading
Loading
Loading
Loading
+33 −28
Original line number Original line Diff line number Diff line
@@ -518,12 +518,6 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
	       priv->bands[IEEE80211_BAND_2GHZ].n_channels,
	       priv->bands[IEEE80211_BAND_2GHZ].n_channels,
	       priv->bands[IEEE80211_BAND_5GHZ].n_channels);
	       priv->bands[IEEE80211_BAND_5GHZ].n_channels);


	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
			&priv->bands[IEEE80211_BAND_2GHZ];
	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
			&priv->bands[IEEE80211_BAND_5GHZ];


	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
	set_bit(STATUS_GEO_CONFIGURED, &priv->status);


@@ -533,13 +527,12 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
/*
/*
 * iwlcore_free_geos - undo allocations in iwlcore_init_geos
 * iwlcore_free_geos - undo allocations in iwlcore_init_geos
 */
 */
void iwlcore_free_geos(struct iwl_priv *priv)
static void iwlcore_free_geos(struct iwl_priv *priv)
{
{
	kfree(priv->ieee_channels);
	kfree(priv->ieee_channels);
	kfree(priv->ieee_rates);
	kfree(priv->ieee_rates);
	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
}
}
EXPORT_SYMBOL(iwlcore_free_geos);


#ifdef CONFIG_IWL4965_HT
#ifdef CONFIG_IWL4965_HT
static u8 is_single_rx_stream(struct iwl_priv *priv)
static u8 is_single_rx_stream(struct iwl_priv *priv)
@@ -767,8 +760,9 @@ int iwl_set_rxon_channel(struct iwl_priv *priv,
}
}
EXPORT_SYMBOL(iwl_set_rxon_channel);
EXPORT_SYMBOL(iwl_set_rxon_channel);


static void iwlcore_init_hw(struct iwl_priv *priv)
int iwl_setup_mac(struct iwl_priv *priv)
{
{
	int ret;
	struct ieee80211_hw *hw = priv->hw;
	struct ieee80211_hw *hw = priv->hw;
	hw->rate_control_algorithm = "iwl-4965-rs";
	hw->rate_control_algorithm = "iwl-4965-rs";


@@ -782,9 +776,29 @@ static void iwlcore_init_hw(struct iwl_priv *priv)
	/* Enhanced value; more queues, to support 11n aggregation */
	/* Enhanced value; more queues, to support 11n aggregation */
	hw->ampdu_queues = 12;
	hw->ampdu_queues = 12;
#endif /* CONFIG_IWL4965_HT */
#endif /* CONFIG_IWL4965_HT */

	hw->conf.beacon_int = 100;

	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
			&priv->bands[IEEE80211_BAND_2GHZ];
	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
			&priv->bands[IEEE80211_BAND_5GHZ];

	ret = ieee80211_register_hw(priv->hw);
	if (ret) {
		IWL_ERROR("Failed to register hw (error %d)\n", ret);
		return ret;
	}
	}
	priv->mac80211_registered = 1;

	return 0;
}
EXPORT_SYMBOL(iwl_setup_mac);



static int iwlcore_init_drv(struct iwl_priv *priv)
int iwl_init_drv(struct iwl_priv *priv)
{
{
	int ret;
	int ret;
	int i;
	int i;
@@ -821,6 +835,9 @@ static int iwlcore_init_drv(struct iwl_priv *priv)
	/* Choose which receivers/antennas to use */
	/* Choose which receivers/antennas to use */
	iwl_set_rxon_chain(priv);
	iwl_set_rxon_chain(priv);


	if (priv->cfg->mod_params->enable_qos)
		priv->qos_data.qos_enable = 1;

	iwl_reset_qos(priv);
	iwl_reset_qos(priv);


	priv->qos_data.qos_active = 0;
	priv->qos_data.qos_active = 0;
@@ -845,34 +862,22 @@ static int iwlcore_init_drv(struct iwl_priv *priv)
		goto err_free_channel_map;
		goto err_free_channel_map;
	}
	}


	ret = ieee80211_register_hw(priv->hw);
	if (ret) {
		IWL_ERROR("Failed to register network device (error %d)\n",
				ret);
		goto err_free_geos;
	}

	priv->hw->conf.beacon_int = 100;
	priv->mac80211_registered = 1;

	return 0;
	return 0;


err_free_geos:
	iwlcore_free_geos(priv);
err_free_channel_map:
err_free_channel_map:
	iwl_free_channel_map(priv);
	iwl_free_channel_map(priv);
err:
err:
	return ret;
	return ret;
}
}
EXPORT_SYMBOL(iwl_init_drv);



int iwl_setup(struct iwl_priv *priv)
void iwl_uninit_drv(struct iwl_priv *priv)
{
{
	int ret = 0;
	iwlcore_free_geos(priv);
	iwlcore_init_hw(priv);
	iwl_free_channel_map(priv);
	ret = iwlcore_init_drv(priv);
	return ret;
}
}
EXPORT_SYMBOL(iwl_setup);
EXPORT_SYMBOL(iwl_uninit_drv);


/* Low level driver call this function to update iwlcore with
/* Low level driver call this function to update iwlcore with
 * driver status.
 * driver status.
+3 −3
Original line number Original line Diff line number Diff line
@@ -175,13 +175,13 @@ void iwl_set_rxon_chain(struct iwl_priv *priv);
int iwl_set_rxon_channel(struct iwl_priv *priv,
int iwl_set_rxon_channel(struct iwl_priv *priv,
				enum ieee80211_band band,
				enum ieee80211_band band,
				u16 channel);
				u16 channel);
void iwlcore_free_geos(struct iwl_priv *priv);
int iwl_setup(struct iwl_priv *priv);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
			 struct ieee80211_ht_info *sta_ht_inf);
			 struct ieee80211_ht_info *sta_ht_inf);
int iwl_hw_nic_init(struct iwl_priv *priv);
int iwl_hw_nic_init(struct iwl_priv *priv);

int iwl_setup_mac(struct iwl_priv *priv);
int iwl_init_drv(struct iwl_priv *priv);
void iwl_uninit_drv(struct iwl_priv *priv);
/* "keep warm" functions */
/* "keep warm" functions */
int iwl_kw_init(struct iwl_priv *priv);
int iwl_kw_init(struct iwl_priv *priv);
int iwl_kw_alloc(struct iwl_priv *priv);
int iwl_kw_alloc(struct iwl_priv *priv);
+0 −1
Original line number Original line Diff line number Diff line
@@ -567,7 +567,6 @@ void iwl_free_channel_map(struct iwl_priv *priv)
	kfree(priv->channel_info);
	kfree(priv->channel_info);
	priv->channel_count = 0;
	priv->channel_count = 0;
}
}
EXPORT_SYMBOL(iwl_free_channel_map);


/**
/**
 * iwl_get_channel_info - Find driver's private channel info
 * iwl_get_channel_info - Find driver's private channel info
+18 −13
Original line number Original line Diff line number Diff line
@@ -5878,10 +5878,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
	}
	}


	/*******************
	/*******************
	 * 6. Setup hw/priv
	 * 6. Setup priv
	 *******************/
	 *******************/


	err = iwl_setup(priv);
	err = iwl_init_drv(priv);
	if (err)
	if (err)
		goto out_free_eeprom;
		goto out_free_eeprom;
	/* At this point both hw and priv are initialized. */
	/* At this point both hw and priv are initialized. */
@@ -5896,9 +5896,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
		IWL_DEBUG_INFO("Radio disabled.\n");
		IWL_DEBUG_INFO("Radio disabled.\n");
	}
	}


	if (priv->cfg->mod_params->enable_qos)
		priv->qos_data.qos_enable = 1;

	/********************
	/********************
	 * 8. Setup services
	 * 8. Setup services
	 ********************/
	 ********************/
@@ -5909,14 +5906,9 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
	err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
	err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
	if (err) {
	if (err) {
		IWL_ERROR("failed to create sysfs device attributes\n");
		IWL_ERROR("failed to create sysfs device attributes\n");
		goto out_free_eeprom;
		goto out_uninit_drv;
	}
	}


	err = iwl_dbgfs_register(priv, DRV_NAME);
	if (err) {
		IWL_ERROR("failed to create debugfs files\n");
		goto out_remove_sysfs;
	}


	iwl4965_setup_deferred_work(priv);
	iwl4965_setup_deferred_work(priv);
	iwl4965_setup_rx_handlers(priv);
	iwl4965_setup_rx_handlers(priv);
@@ -5927,12 +5919,26 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
	pci_save_state(pdev);
	pci_save_state(pdev);
	pci_disable_device(pdev);
	pci_disable_device(pdev);


	/**********************************
	 * 10. Setup and register mac80211
	 **********************************/

	err = iwl_setup_mac(priv);
	if (err)
		goto out_remove_sysfs;

	err = iwl_dbgfs_register(priv, DRV_NAME);
	if (err)
		IWL_ERROR("failed to create debugfs files\n");

	/* notify iwlcore to init */
	/* notify iwlcore to init */
	iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT);
	iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT);
	return 0;
	return 0;


 out_remove_sysfs:
 out_remove_sysfs:
	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
 out_uninit_drv:
	iwl_uninit_drv(priv);
 out_free_eeprom:
 out_free_eeprom:
	iwl_eeprom_free(priv);
	iwl_eeprom_free(priv);
 out_iounmap:
 out_iounmap:
@@ -6014,8 +6020,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
	pci_disable_device(pdev);
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);
	pci_set_drvdata(pdev, NULL);


	iwl_free_channel_map(priv);
	iwl_uninit_drv(priv);
	iwlcore_free_geos(priv);


	if (priv->ibss_beacon)
	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);
		dev_kfree_skb(priv->ibss_beacon);