Search Linux Wireless

Re: [PATCH for-3.9] brcmsmac: request firmware in .start() callback

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



  CC      drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.o
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c: In function ‘brcms_remove’:
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c:337:3: error: implicit declaration of function ‘brcms_led_unregister’ [-Werror=implicit-function-declaration]
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c: In function ‘brcms_request_fw’:
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c:385:2: error: implicit declaration of function ‘brcms_release_fw’ [-Werror=implicit-function-declaration]
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c: At top level:
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c:393:13: warning: conflicting types for ‘brcms_release_fw’ [enabled by default]
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c:393:13: error: static declaration of ‘brcms_release_fw’ follows non-static declaration
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c:385:2: note: previous implicit declaration of ‘brcms_release_fw’ was here
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c:393:13: warning: ‘brcms_release_fw’ defined but not used [-Wunused-function]
cc1: some warnings being treated as errors

On Wed, Apr 03, 2013 at 10:41:28AM +0200, Arend van Spriel wrote:
> The firmware is requested from user-space. To assure the request
> can be handled it is recommended to do the request upon IFF_UP.
> For a mac80211 driver the .start() callback can be considered
> the equivalent.
> 
> Reported-by: John Talbut <jt@xxxxxxxxxxx>
> Reviewed-by: Pieter-Paul Giesberts <pieterpg@xxxxxxxxxxxx>
> Reviewed-by: Piotr Haber <phaber@xxxxxxxxxxxx>
> Reviewed-by: Hante Meuleman <meuleman@xxxxxxxxxxxx>
> Signed-off-by: Arend van Spriel <arend@xxxxxxxxxxxx>
> ---
> Hi John,
> 
> Forgot this one for the 3.9 kernel, which was reported recently
> using a system with an encrypted root filesystem although the issue
> is more generic.
> 
> It applies to the master branch in the wireless repository.
> 
> Gr. AvS
> ---
>  .../net/wireless/brcm80211/brcmsmac/mac80211_if.c  |  267 ++++++++++----------
>  1 file changed, 134 insertions(+), 133 deletions(-)
> 
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> index c6451c6..2f063a2 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> @@ -274,6 +274,131 @@ static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br)
>  	}
>  }
>  
> +/**
> + * This function frees the WL per-device resources.
> + *
> + * This function frees resources owned by the WL device pointed to
> + * by the wl parameter.
> + *
> + * precondition: can both be called locked and unlocked
> + *
> + */
> +static void brcms_free(struct brcms_info *wl)
> +{
> +	struct brcms_timer *t, *next;
> +
> +	/* free ucode data */
> +	if (wl->fw.fw_cnt)
> +		brcms_ucode_data_free(&wl->ucode);
> +	if (wl->irq)
> +		free_irq(wl->irq, wl);
> +
> +	/* kill dpc */
> +	tasklet_kill(&wl->tasklet);
> +
> +	if (wl->pub) {
> +		brcms_debugfs_detach(wl->pub);
> +		brcms_c_module_unregister(wl->pub, "linux", wl);
> +	}
> +
> +	/* free common resources */
> +	if (wl->wlc) {
> +		brcms_c_detach(wl->wlc);
> +		wl->wlc = NULL;
> +		wl->pub = NULL;
> +	}
> +
> +	/* virtual interface deletion is deferred so we cannot spinwait */
> +
> +	/* wait for all pending callbacks to complete */
> +	while (atomic_read(&wl->callbacks) > 0)
> +		schedule();
> +
> +	/* free timers */
> +	for (t = wl->timers; t; t = next) {
> +		next = t->next;
> +#ifdef DEBUG
> +		kfree(t->name);
> +#endif
> +		kfree(t);
> +	}
> +}
> +
> +/*
> +* called from both kernel as from this kernel module (error flow on attach)
> +* precondition: perimeter lock is not acquired.
> +*/
> +static void brcms_remove(struct bcma_device *pdev)
> +{
> +	struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
> +	struct brcms_info *wl = hw->priv;
> +
> +	if (wl->wlc) {
> +		brcms_led_unregister(wl);
> +		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
> +		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
> +		ieee80211_unregister_hw(hw);
> +	}
> +
> +	brcms_free(wl);
> +
> +	bcma_set_drvdata(pdev, NULL);
> +	ieee80211_free_hw(hw);
> +}
> +
> +/*
> + * Precondition: Since this function is called in brcms_pci_probe() context,
> + * no locking is required.
> + */
> +static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
> +{
> +	int status;
> +	struct device *device = &pdev->dev;
> +	char fw_name[100];
> +	int i;
> +
> +	memset(&wl->fw, 0, sizeof(struct brcms_firmware));
> +	for (i = 0; i < MAX_FW_IMAGES; i++) {
> +		if (brcms_firmwares[i] == NULL)
> +			break;
> +		sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
> +			UCODE_LOADER_API_VER);
> +		status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
> +		if (status) {
> +			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
> +				  KBUILD_MODNAME, fw_name);
> +			return status;
> +		}
> +		sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
> +			UCODE_LOADER_API_VER);
> +		status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
> +		if (status) {
> +			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
> +				  KBUILD_MODNAME, fw_name);
> +			return status;
> +		}
> +		wl->fw.hdr_num_entries[i] =
> +		    wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
> +	}
> +	wl->fw.fw_cnt = i;
> +	status = brcms_ucode_data_init(wl, &wl->ucode);
> +	brcms_release_fw(wl);
> +	return status;
> +}
> +
> +/*
> + * Precondition: Since this function is called in brcms_pci_probe() context,
> + * no locking is required.
> + */
> +static void brcms_release_fw(struct brcms_info *wl)
> +{
> +	int i;
> +	for (i = 0; i < MAX_FW_IMAGES; i++) {
> +		release_firmware(wl->fw.fw_bin[i]);
> +		release_firmware(wl->fw.fw_hdr[i]);
> +	}
> +}
> +
>  static void brcms_ops_tx(struct ieee80211_hw *hw,
>  			 struct ieee80211_tx_control *control,
>  			 struct sk_buff *skb)
> @@ -297,7 +422,7 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
>  {
>  	struct brcms_info *wl = hw->priv;
>  	bool blocked;
> -	int err;
> +	int err = 0;
>  
>  	ieee80211_wake_queues(hw);
>  	spin_lock_bh(&wl->lock);
> @@ -306,6 +431,14 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
>  	if (!blocked)
>  		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
>  
> +	if (!wl->ucode.bcm43xx_bomminor) {
> +		err = brcms_request_fw(wl, wl->wlc->hw->d11core);
> +		if (err) {
> +			brcms_remove(wl->wlc->hw->d11core);
> +			return -ENOENT;
> +		}
> +	}
> +
>  	spin_lock_bh(&wl->lock);
>  	/* avoid acknowledging frames before a non-monitor device is added */
>  	wl->mute_tx = true;
> @@ -793,128 +926,6 @@ void brcms_dpc(unsigned long data)
>  	wake_up(&wl->tx_flush_wq);
>  }
>  
> -/*
> - * Precondition: Since this function is called in brcms_pci_probe() context,
> - * no locking is required.
> - */
> -static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
> -{
> -	int status;
> -	struct device *device = &pdev->dev;
> -	char fw_name[100];
> -	int i;
> -
> -	memset(&wl->fw, 0, sizeof(struct brcms_firmware));
> -	for (i = 0; i < MAX_FW_IMAGES; i++) {
> -		if (brcms_firmwares[i] == NULL)
> -			break;
> -		sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
> -			UCODE_LOADER_API_VER);
> -		status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
> -		if (status) {
> -			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
> -				  KBUILD_MODNAME, fw_name);
> -			return status;
> -		}
> -		sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
> -			UCODE_LOADER_API_VER);
> -		status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
> -		if (status) {
> -			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
> -				  KBUILD_MODNAME, fw_name);
> -			return status;
> -		}
> -		wl->fw.hdr_num_entries[i] =
> -		    wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
> -	}
> -	wl->fw.fw_cnt = i;
> -	return brcms_ucode_data_init(wl, &wl->ucode);
> -}
> -
> -/*
> - * Precondition: Since this function is called in brcms_pci_probe() context,
> - * no locking is required.
> - */
> -static void brcms_release_fw(struct brcms_info *wl)
> -{
> -	int i;
> -	for (i = 0; i < MAX_FW_IMAGES; i++) {
> -		release_firmware(wl->fw.fw_bin[i]);
> -		release_firmware(wl->fw.fw_hdr[i]);
> -	}
> -}
> -
> -/**
> - * This function frees the WL per-device resources.
> - *
> - * This function frees resources owned by the WL device pointed to
> - * by the wl parameter.
> - *
> - * precondition: can both be called locked and unlocked
> - *
> - */
> -static void brcms_free(struct brcms_info *wl)
> -{
> -	struct brcms_timer *t, *next;
> -
> -	/* free ucode data */
> -	if (wl->fw.fw_cnt)
> -		brcms_ucode_data_free(&wl->ucode);
> -	if (wl->irq)
> -		free_irq(wl->irq, wl);
> -
> -	/* kill dpc */
> -	tasklet_kill(&wl->tasklet);
> -
> -	if (wl->pub) {
> -		brcms_debugfs_detach(wl->pub);
> -		brcms_c_module_unregister(wl->pub, "linux", wl);
> -	}
> -
> -	/* free common resources */
> -	if (wl->wlc) {
> -		brcms_c_detach(wl->wlc);
> -		wl->wlc = NULL;
> -		wl->pub = NULL;
> -	}
> -
> -	/* virtual interface deletion is deferred so we cannot spinwait */
> -
> -	/* wait for all pending callbacks to complete */
> -	while (atomic_read(&wl->callbacks) > 0)
> -		schedule();
> -
> -	/* free timers */
> -	for (t = wl->timers; t; t = next) {
> -		next = t->next;
> -#ifdef DEBUG
> -		kfree(t->name);
> -#endif
> -		kfree(t);
> -	}
> -}
> -
> -/*
> -* called from both kernel as from this kernel module (error flow on attach)
> -* precondition: perimeter lock is not acquired.
> -*/
> -static void brcms_remove(struct bcma_device *pdev)
> -{
> -	struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
> -	struct brcms_info *wl = hw->priv;
> -
> -	if (wl->wlc) {
> -		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
> -		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
> -		ieee80211_unregister_hw(hw);
> -	}
> -
> -	brcms_free(wl);
> -
> -	bcma_set_drvdata(pdev, NULL);
> -	ieee80211_free_hw(hw);
> -}
> -
>  static irqreturn_t brcms_isr(int irq, void *dev_id)
>  {
>  	struct brcms_info *wl;
> @@ -1047,18 +1058,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
>  	spin_lock_init(&wl->lock);
>  	spin_lock_init(&wl->isr_lock);
>  
> -	/* prepare ucode */
> -	if (brcms_request_fw(wl, pdev) < 0) {
> -		wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
> -			  "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
> -		brcms_release_fw(wl);
> -		brcms_remove(pdev);
> -		return NULL;
> -	}
> -
>  	/* common load-time initialization */
>  	wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);
> -	brcms_release_fw(wl);
>  	if (!wl->wlc) {
>  		wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
>  			  KBUILD_MODNAME, err);
> -- 
> 1.7.10.4
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
John W. Linville		Someday the world will need a hero, and you
linville@xxxxxxxxxxxxx			might be all we have.  Be ready.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux