diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/hif_usb.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/hif_usb.c | 38 | 
1 files changed, 25 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index aa327adcc3d..924c4616c3d 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -973,8 +973,8 @@ static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)  static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)  {  	int transfer, err; -	const void *data = hif_dev->firmware->data; -	size_t len = hif_dev->firmware->size; +	const void *data = hif_dev->fw_data; +	size_t len = hif_dev->fw_size;  	u32 addr = AR9271_FIRMWARE;  	u8 *buf = kzalloc(4096, GFP_KERNEL);  	u32 firm_offset; @@ -1017,7 +1017,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)  		return -EIO;  	dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n", -		 hif_dev->fw_name, (unsigned long) hif_dev->firmware->size); +		 hif_dev->fw_name, (unsigned long) hif_dev->fw_size);  	return 0;  } @@ -1072,14 +1072,15 @@ static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev)   */  static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev)  { -	struct device *parent = hif_dev->udev->dev.parent; +	struct device *dev = &hif_dev->udev->dev; +	struct device *parent = dev->parent;  	complete(&hif_dev->fw_done);  	if (parent)  		device_lock(parent); -	device_release_driver(&hif_dev->udev->dev); +	device_release_driver(dev);  	if (parent)  		device_unlock(parent); @@ -1099,11 +1100,11 @@ static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)  	hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb,  						 &hif_dev->udev->dev); -	if (hif_dev->htc_handle == NULL) { -		goto err_fw; -	} +	if (hif_dev->htc_handle == NULL) +		goto err_dev_alloc; -	hif_dev->firmware = fw; +	hif_dev->fw_data = fw->data; +	hif_dev->fw_size = fw->size;  	/* Proceed with initialization */ @@ -1121,6 +1122,8 @@ static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)  		goto err_htc_hw_init;  	} +	release_firmware(fw); +	hif_dev->flags |= HIF_USB_READY;  	complete(&hif_dev->fw_done);  	return; @@ -1129,8 +1132,8 @@ err_htc_hw_init:  	ath9k_hif_usb_dev_deinit(hif_dev);  err_dev_init:  	ath9k_htc_hw_free(hif_dev->htc_handle); +err_dev_alloc:  	release_firmware(fw); -	hif_dev->firmware = NULL;  err_fw:  	ath9k_hif_usb_firmware_fail(hif_dev);  } @@ -1277,11 +1280,10 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)  	wait_for_completion(&hif_dev->fw_done); -	if (hif_dev->firmware) { +	if (hif_dev->flags & HIF_USB_READY) {  		ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);  		ath9k_htc_hw_free(hif_dev->htc_handle);  		ath9k_hif_usb_dev_deinit(hif_dev); -		release_firmware(hif_dev->firmware);  	}  	usb_set_intfdata(interface, NULL); @@ -1317,13 +1319,23 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface)  	struct hif_device_usb *hif_dev = usb_get_intfdata(interface);  	struct htc_target *htc_handle = hif_dev->htc_handle;  	int ret; +	const struct firmware *fw;  	ret = ath9k_hif_usb_alloc_urbs(hif_dev);  	if (ret)  		return ret; -	if (hif_dev->firmware) { +	if (hif_dev->flags & HIF_USB_READY) { +		/* request cached firmware during suspend/resume cycle */ +		ret = request_firmware(&fw, hif_dev->fw_name, +				       &hif_dev->udev->dev); +		if (ret) +			goto fail_resume; + +		hif_dev->fw_data = fw->data; +		hif_dev->fw_size = fw->size;  		ret = ath9k_hif_usb_download_fw(hif_dev); +		release_firmware(fw);  		if (ret)  			goto fail_resume;  	} else {  |