diff options
Diffstat (limited to 'drivers/net/wireless/ath/ar9170/usb.c')
| -rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 1010 | 
1 files changed, 0 insertions, 1010 deletions
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c deleted file mode 100644 index 5dbb5361fd5..00000000000 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ /dev/null @@ -1,1010 +0,0 @@ -/* - * Atheros AR9170 driver - * - * USB - frontend - * - * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> - * Copyright 2009, Christian Lamparter <chunkeey@web.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING.  If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - *    Copyright (c) 2007-2008 Atheros Communications, Inc. - * - *    Permission to use, copy, modify, and/or distribute this software for any - *    purpose with or without fee is hereby granted, provided that the above - *    copyright notice and this permission notice appear in all copies. - * - *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/firmware.h> -#include <linux/etherdevice.h> -#include <linux/device.h> -#include <net/mac80211.h> -#include "ar9170.h" -#include "cmd.h" -#include "hw.h" -#include "usb.h" - -MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); -MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); -MODULE_FIRMWARE("ar9170.fw"); - -enum ar9170_requirements { -	AR9170_REQ_FW1_ONLY = 1, -}; - -static struct usb_device_id ar9170_usb_ids[] = { -	/* Atheros 9170 */ -	{ USB_DEVICE(0x0cf3, 0x9170) }, -	/* Atheros TG121N */ -	{ USB_DEVICE(0x0cf3, 0x1001) }, -	/* TP-Link TL-WN821N v2 */ -	{ USB_DEVICE(0x0cf3, 0x1002) }, -	/* 3Com Dual Band 802.11n USB Adapter */ -	{ USB_DEVICE(0x0cf3, 0x1010) }, -	/* H3C Dual Band 802.11n USB Adapter */ -	{ USB_DEVICE(0x0cf3, 0x1011) }, -	/* Cace Airpcap NX */ -	{ USB_DEVICE(0xcace, 0x0300) }, -	/* D-Link DWA 160 A1 */ -	{ USB_DEVICE(0x07d1, 0x3c10) }, -	/* D-Link DWA 160 A2 */ -	{ USB_DEVICE(0x07d1, 0x3a09) }, -	/* Netgear WNA1000 */ -	{ USB_DEVICE(0x0846, 0x9040) }, -	/* Netgear WNDA3100 */ -	{ USB_DEVICE(0x0846, 0x9010) }, -	/* Netgear WN111 v2 */ -	{ USB_DEVICE(0x0846, 0x9001) }, -	/* Zydas ZD1221 */ -	{ USB_DEVICE(0x0ace, 0x1221) }, -	/* Proxim ORiNOCO 802.11n USB */ -	{ USB_DEVICE(0x1435, 0x0804) }, -	/* WNC Generic 11n USB Dongle */ -	{ USB_DEVICE(0x1435, 0x0326) }, -	/* ZyXEL NWD271N */ -	{ USB_DEVICE(0x0586, 0x3417) }, -	/* Z-Com UB81 BG */ -	{ USB_DEVICE(0x0cde, 0x0023) }, -	/* Z-Com UB82 ABG */ -	{ USB_DEVICE(0x0cde, 0x0026) }, -	/* Sphairon Homelink 1202 */ -	{ USB_DEVICE(0x0cde, 0x0027) }, -	/* Arcadyan WN7512 */ -	{ USB_DEVICE(0x083a, 0xf522) }, -	/* Planex GWUS300 */ -	{ USB_DEVICE(0x2019, 0x5304) }, -	/* IO-Data WNGDNUS2 */ -	{ USB_DEVICE(0x04bb, 0x093f) }, -	/* AVM FRITZ!WLAN USB Stick N */ -	{ USB_DEVICE(0x057C, 0x8401) }, -	/* NEC WL300NU-G */ -	{ USB_DEVICE(0x0409, 0x0249) }, -	/* AVM FRITZ!WLAN USB Stick N 2.4 */ -	{ USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, -	/* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */ -	{ USB_DEVICE(0x1668, 0x1200) }, - -	/* terminate */ -	{} -}; -MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); - -static void ar9170_usb_submit_urb(struct ar9170_usb *aru) -{ -	struct urb *urb; -	unsigned long flags; -	int err; - -	if (unlikely(!IS_STARTED(&aru->common))) -		return ; - -	spin_lock_irqsave(&aru->tx_urb_lock, flags); -	if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) { -		spin_unlock_irqrestore(&aru->tx_urb_lock, flags); -		return ; -	} -	atomic_inc(&aru->tx_submitted_urbs); - -	urb = usb_get_from_anchor(&aru->tx_pending); -	if (!urb) { -		atomic_dec(&aru->tx_submitted_urbs); -		spin_unlock_irqrestore(&aru->tx_urb_lock, flags); - -		return ; -	} -	spin_unlock_irqrestore(&aru->tx_urb_lock, flags); - -	aru->tx_pending_urbs--; -	usb_anchor_urb(urb, &aru->tx_submitted); - -	err = usb_submit_urb(urb, GFP_ATOMIC); -	if (unlikely(err)) { -		if (ar9170_nag_limiter(&aru->common)) -			dev_err(&aru->udev->dev, "submit_urb failed (%d).\n", -				err); - -		usb_unanchor_urb(urb); -		atomic_dec(&aru->tx_submitted_urbs); -		ar9170_tx_callback(&aru->common, urb->context); -	} - -	usb_free_urb(urb); -} - -static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) -{ -	struct sk_buff *skb = urb->context; -	struct ar9170_usb *aru = (struct ar9170_usb *) -	      usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - -	if (unlikely(!aru)) { -		dev_kfree_skb_irq(skb); -		return ; -	} - -	atomic_dec(&aru->tx_submitted_urbs); - -	ar9170_tx_callback(&aru->common, skb); - -	ar9170_usb_submit_urb(aru); -} - -static void ar9170_usb_tx_urb_complete(struct urb *urb) -{ -} - -static void ar9170_usb_irq_completed(struct urb *urb) -{ -	struct ar9170_usb *aru = urb->context; - -	switch (urb->status) { -	/* everything is fine */ -	case 0: -		break; - -	/* disconnect */ -	case -ENOENT: -	case -ECONNRESET: -	case -ENODEV: -	case -ESHUTDOWN: -		goto free; - -	default: -		goto resubmit; -	} - -	ar9170_handle_command_response(&aru->common, urb->transfer_buffer, -				       urb->actual_length); - -resubmit: -	usb_anchor_urb(urb, &aru->rx_submitted); -	if (usb_submit_urb(urb, GFP_ATOMIC)) { -		usb_unanchor_urb(urb); -		goto free; -	} - -	return; - -free: -	usb_free_coherent(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); -} - -static void ar9170_usb_rx_completed(struct urb *urb) -{ -	struct sk_buff *skb = urb->context; -	struct ar9170_usb *aru = (struct ar9170_usb *) -		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); -	int err; - -	if (!aru) -		goto free; - -	switch (urb->status) { -	/* everything is fine */ -	case 0: -		break; - -	/* disconnect */ -	case -ENOENT: -	case -ECONNRESET: -	case -ENODEV: -	case -ESHUTDOWN: -		goto free; - -	default: -		goto resubmit; -	} - -	skb_put(skb, urb->actual_length); -	ar9170_rx(&aru->common, skb); - -resubmit: -	skb_reset_tail_pointer(skb); -	skb_trim(skb, 0); - -	usb_anchor_urb(urb, &aru->rx_submitted); -	err = usb_submit_urb(urb, GFP_ATOMIC); -	if (unlikely(err)) { -		usb_unanchor_urb(urb); -		goto free; -	} - -	return ; - -free: -	dev_kfree_skb_irq(skb); -} - -static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, -				  struct urb *urb, gfp_t gfp) -{ -	struct sk_buff *skb; - -	skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp); -	if (!skb) -		return -ENOMEM; - -	/* reserve some space for mac80211's radiotap */ -	skb_reserve(skb, 32); - -	usb_fill_bulk_urb(urb, aru->udev, -			  usb_rcvbulkpipe(aru->udev, AR9170_EP_RX), -			  skb->data, min(skb_tailroom(skb), -			  AR9170_MAX_RX_BUFFER_SIZE), -			  ar9170_usb_rx_completed, skb); - -	return 0; -} - -static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) -{ -	struct urb *urb = NULL; -	void *ibuf; -	int err = -ENOMEM; - -	/* initialize interrupt endpoint */ -	urb = usb_alloc_urb(0, GFP_KERNEL); -	if (!urb) -		goto out; - -	ibuf = usb_alloc_coherent(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); -	if (!ibuf) -		goto out; - -	usb_fill_int_urb(urb, aru->udev, -			 usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf, -			 64, ar9170_usb_irq_completed, aru, 1); -	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - -	usb_anchor_urb(urb, &aru->rx_submitted); -	err = usb_submit_urb(urb, GFP_KERNEL); -	if (err) { -		usb_unanchor_urb(urb); -		usb_free_coherent(aru->udev, 64, urb->transfer_buffer, -				  urb->transfer_dma); -	} - -out: -	usb_free_urb(urb); -	return err; -} - -static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) -{ -	struct urb *urb; -	int i; -	int err = -EINVAL; - -	for (i = 0; i < AR9170_NUM_RX_URBS; i++) { -		err = -ENOMEM; -		urb = usb_alloc_urb(0, GFP_KERNEL); -		if (!urb) -			goto err_out; - -		err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL); -		if (err) { -			usb_free_urb(urb); -			goto err_out; -		} - -		usb_anchor_urb(urb, &aru->rx_submitted); -		err = usb_submit_urb(urb, GFP_KERNEL); -		if (err) { -			usb_unanchor_urb(urb); -			dev_kfree_skb_any((void *) urb->transfer_buffer); -			usb_free_urb(urb); -			goto err_out; -		} -		usb_free_urb(urb); -	} - -	/* the device now waiting for a firmware. */ -	aru->common.state = AR9170_IDLE; -	return 0; - -err_out: - -	usb_kill_anchored_urbs(&aru->rx_submitted); -	return err; -} - -static int ar9170_usb_flush(struct ar9170 *ar) -{ -	struct ar9170_usb *aru = (void *) ar; -	struct urb *urb; -	int ret, err = 0; - -	if (IS_STARTED(ar)) -		aru->common.state = AR9170_IDLE; - -	usb_wait_anchor_empty_timeout(&aru->tx_pending, -					    msecs_to_jiffies(800)); -	while ((urb = usb_get_from_anchor(&aru->tx_pending))) { -		ar9170_tx_callback(&aru->common, (void *) urb->context); -		usb_free_urb(urb); -	} - -	/* lets wait a while until the tx - queues are dried out */ -	ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, -					    msecs_to_jiffies(100)); -	if (ret == 0) -		err = -ETIMEDOUT; - -	usb_kill_anchored_urbs(&aru->tx_submitted); - -	if (IS_ACCEPTING_CMD(ar)) -		aru->common.state = AR9170_STARTED; - -	return err; -} - -static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) -{ -	int err; - -	aru->common.state = AR9170_UNKNOWN_STATE; - -	err = ar9170_usb_flush(&aru->common); -	if (err) -		dev_err(&aru->udev->dev, "stuck tx urbs!\n"); - -	usb_poison_anchored_urbs(&aru->tx_submitted); -	usb_poison_anchored_urbs(&aru->rx_submitted); -} - -static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, -			       unsigned int plen, void *payload, -			       unsigned int outlen, void *out) -{ -	struct ar9170_usb *aru = (void *) ar; -	struct urb *urb = NULL; -	unsigned long flags; -	int err = -ENOMEM; - -	if (unlikely(!IS_ACCEPTING_CMD(ar))) -		return -EPERM; - -	if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4)) -		return -EINVAL; - -	urb = usb_alloc_urb(0, GFP_ATOMIC); -	if (unlikely(!urb)) -		goto err_free; - -	ar->cmdbuf[0] = cpu_to_le32(plen); -	ar->cmdbuf[0] |= cpu_to_le32(cmd << 8); -	/* writing multiple regs fills this buffer already */ -	if (plen && payload != (u8 *)(&ar->cmdbuf[1])) -		memcpy(&ar->cmdbuf[1], payload, plen); - -	spin_lock_irqsave(&aru->common.cmdlock, flags); -	aru->readbuf = (u8 *)out; -	aru->readlen = outlen; -	spin_unlock_irqrestore(&aru->common.cmdlock, flags); - -	usb_fill_int_urb(urb, aru->udev, -			 usb_sndintpipe(aru->udev, AR9170_EP_CMD), -			 aru->common.cmdbuf, plen + 4, -			 ar9170_usb_tx_urb_complete, NULL, 1); - -	usb_anchor_urb(urb, &aru->tx_submitted); -	err = usb_submit_urb(urb, GFP_ATOMIC); -	if (unlikely(err)) { -		usb_unanchor_urb(urb); -		usb_free_urb(urb); -		goto err_unbuf; -	} -	usb_free_urb(urb); - -	err = wait_for_completion_timeout(&aru->cmd_wait, HZ); -	if (err == 0) { -		err = -ETIMEDOUT; -		goto err_unbuf; -	} - -	if (aru->readlen != outlen) { -		err = -EMSGSIZE; -		goto err_unbuf; -	} - -	return 0; - -err_unbuf: -	/* Maybe the device was removed in the second we were waiting? */ -	if (IS_STARTED(ar)) { -		dev_err(&aru->udev->dev, "no command feedback " -					 "received (%d).\n", err); - -		/* provide some maybe useful debug information */ -		print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE, -				     aru->common.cmdbuf, plen + 4); -		dump_stack(); -	} - -	/* invalidate to avoid completing the next prematurely */ -	spin_lock_irqsave(&aru->common.cmdlock, flags); -	aru->readbuf = NULL; -	aru->readlen = 0; -	spin_unlock_irqrestore(&aru->common.cmdlock, flags); - -err_free: - -	return err; -} - -static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) -{ -	struct ar9170_usb *aru = (struct ar9170_usb *) ar; -	struct urb *urb; - -	if (unlikely(!IS_STARTED(ar))) { -		/* Seriously, what were you drink... err... thinking!? */ -		return -EPERM; -	} - -	urb = usb_alloc_urb(0, GFP_ATOMIC); -	if (unlikely(!urb)) -		return -ENOMEM; - -	usb_fill_bulk_urb(urb, aru->udev, -			  usb_sndbulkpipe(aru->udev, AR9170_EP_TX), -			  skb->data, skb->len, -			  ar9170_usb_tx_urb_complete_frame, skb); -	urb->transfer_flags |= URB_ZERO_PACKET; - -	usb_anchor_urb(urb, &aru->tx_pending); -	aru->tx_pending_urbs++; - -	usb_free_urb(urb); - -	ar9170_usb_submit_urb(aru); -	return 0; -} - -static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) -{ -	struct ar9170_usb *aru = (void *) ar; -	unsigned long flags; -	u32 in, out; - -	if (unlikely(!buffer)) -		return ; - -	in = le32_to_cpup((__le32 *)buffer); -	out = le32_to_cpu(ar->cmdbuf[0]); - -	/* mask off length byte */ -	out &= ~0xFF; - -	if (aru->readlen >= 0) { -		/* add expected length */ -		out |= aru->readlen; -	} else { -		/* add obtained length */ -		out |= in & 0xFF; -	} - -	/* -	 * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response -	 * length and we cannot predict the correct length in advance. -	 * So we only check if we provided enough space for the data. -	 */ -	if (unlikely(out < in)) { -		dev_warn(&aru->udev->dev, "received invalid command response " -					  "got %d bytes, instead of %d bytes " -					  "and the resp length is %d bytes\n", -			 in, out, len); -		print_hex_dump_bytes("ar9170 invalid resp: ", -				     DUMP_PREFIX_OFFSET, buffer, len); -		/* -		 * Do not complete, then the command times out, -		 * and we get a stack trace from there. -		 */ -		return ; -	} - -	spin_lock_irqsave(&aru->common.cmdlock, flags); -	if (aru->readbuf && len > 0) { -		memcpy(aru->readbuf, buffer + 4, len - 4); -		aru->readbuf = NULL; -	} -	complete(&aru->cmd_wait); -	spin_unlock_irqrestore(&aru->common.cmdlock, flags); -} - -static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, -			     size_t len, u32 addr, bool complete) -{ -	int transfer, err; -	u8 *buf = kmalloc(4096, GFP_KERNEL); - -	if (!buf) -		return -ENOMEM; - -	while (len) { -		transfer = min_t(int, len, 4096); -		memcpy(buf, data, transfer); - -		err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), -				      0x30 /* FW DL */, 0x40 | USB_DIR_OUT, -				      addr >> 8, 0, buf, transfer, 1000); - -		if (err < 0) { -			kfree(buf); -			return err; -		} - -		len -= transfer; -		data += transfer; -		addr += transfer; -	} -	kfree(buf); - -	if (complete) { -		err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), -				      0x31 /* FW DL COMPLETE */, -				      0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000); -	} - -	return 0; -} - -static int ar9170_usb_reset(struct ar9170_usb *aru) -{ -	int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); - -	if (lock) { -		ret = usb_lock_device_for_reset(aru->udev, aru->intf); -		if (ret < 0) { -			dev_err(&aru->udev->dev, "unable to lock device " -				"for reset (%d).\n", ret); -			return ret; -		} -	} - -	ret = usb_reset_device(aru->udev); -	if (lock) -		usb_unlock_device(aru->udev); - -	/* let it rest - for a second - */ -	msleep(1000); - -	return ret; -} - -static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) -{ -	int err; - -	if (!aru->init_values) -		goto upload_fw_start; - -	/* First, upload initial values to device RAM */ -	err = ar9170_usb_upload(aru, aru->init_values->data, -				aru->init_values->size, 0x102800, false); -	if (err) { -		dev_err(&aru->udev->dev, "firmware part 1 " -			"upload failed (%d).\n", err); -		return err; -	} - -upload_fw_start: - -	/* Then, upload the firmware itself and start it */ -	return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, -				0x200000, true); -} - -static int ar9170_usb_init_transport(struct ar9170_usb *aru) -{ -	struct ar9170 *ar = (void *) &aru->common; -	int err; - -	ar9170_regwrite_begin(ar); - -	/* Set USB Rx stream mode MAX packet number to 2 */ -	ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4); - -	/* Set USB Rx stream mode timeout to 10us */ -	ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); - -	ar9170_regwrite_finish(); - -	err = ar9170_regwrite_result(); -	if (err) -		dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err); - -	return err; -} - -static void ar9170_usb_stop(struct ar9170 *ar) -{ -	struct ar9170_usb *aru = (void *) ar; -	int ret; - -	if (IS_ACCEPTING_CMD(ar)) -		aru->common.state = AR9170_STOPPED; - -	ret = ar9170_usb_flush(ar); -	if (ret) -		dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); - -	usb_poison_anchored_urbs(&aru->tx_submitted); - -	/* -	 * Note: -	 * So far we freed all tx urbs, but we won't dare to touch any rx urbs. -	 * Else we would end up with a unresponsive device... -	 */ -} - -static int ar9170_usb_open(struct ar9170 *ar) -{ -	struct ar9170_usb *aru = (void *) ar; -	int err; - -	usb_unpoison_anchored_urbs(&aru->tx_submitted); -	err = ar9170_usb_init_transport(aru); -	if (err) { -		usb_poison_anchored_urbs(&aru->tx_submitted); -		return err; -	} - -	aru->common.state = AR9170_IDLE; -	return 0; -} - -static int ar9170_usb_init_device(struct ar9170_usb *aru) -{ -	int err; - -	err = ar9170_usb_alloc_rx_irq_urb(aru); -	if (err) -		goto err_out; - -	err = ar9170_usb_alloc_rx_bulk_urbs(aru); -	if (err) -		goto err_unrx; - -	err = ar9170_usb_upload_firmware(aru); -	if (err) { -		err = ar9170_echo_test(&aru->common, 0x60d43110); -		if (err) { -			/* force user invention, by disabling the device */ -			err = usb_driver_set_configuration(aru->udev, -1); -			dev_err(&aru->udev->dev, "device is in a bad state. " -						 "please reconnect it!\n"); -			goto err_unrx; -		} -	} - -	return 0; - -err_unrx: -	ar9170_usb_cancel_urbs(aru); - -err_out: -	return err; -} - -static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) -{ -	struct device *parent = aru->udev->dev.parent; -	struct usb_device *udev; - -	/* -	 * Store a copy of the usb_device pointer locally. -	 * This is because device_release_driver initiates -	 * ar9170_usb_disconnect, which in turn frees our -	 * driver context (aru). -	 */ -	udev = aru->udev; - -	complete(&aru->firmware_loading_complete); - -	/* unbind anything failed */ -	if (parent) -		device_lock(parent); - -	device_release_driver(&udev->dev); -	if (parent) -		device_unlock(parent); - -	usb_put_dev(udev); -} - -static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) -{ -	struct ar9170_usb *aru = context; -	int err; - -	aru->firmware = fw; - -	if (!fw) { -		dev_err(&aru->udev->dev, "firmware file not found.\n"); -		goto err_freefw; -	} - -	err = ar9170_usb_init_device(aru); -	if (err) -		goto err_freefw; - -	err = ar9170_usb_open(&aru->common); -	if (err) -		goto err_unrx; - -	err = ar9170_register(&aru->common, &aru->udev->dev); - -	ar9170_usb_stop(&aru->common); -	if (err) -		goto err_unrx; - -	complete(&aru->firmware_loading_complete); -	usb_put_dev(aru->udev); -	return; - - err_unrx: -	ar9170_usb_cancel_urbs(aru); - - err_freefw: -	ar9170_usb_firmware_failed(aru); -} - -static void ar9170_usb_firmware_inits(const struct firmware *fw, -				      void *context) -{ -	struct ar9170_usb *aru = context; -	int err; - -	if (!fw) { -		dev_err(&aru->udev->dev, "file with init values not found.\n"); -		ar9170_usb_firmware_failed(aru); -		return; -	} - -	aru->init_values = fw; - -	/* ok so we have the init values -- get code for two-stage */ - -	err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", -				      &aru->udev->dev, GFP_KERNEL, aru, -				      ar9170_usb_firmware_finish); -	if (err) -		ar9170_usb_firmware_failed(aru); -} - -static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) -{ -	struct ar9170_usb *aru = context; -	int err; - -	if (fw) { -		ar9170_usb_firmware_finish(fw, context); -		return; -	} - -	if (aru->req_one_stage_fw) { -		dev_err(&aru->udev->dev, "ar9170.fw firmware file " -			"not found and is required for this device\n"); -		ar9170_usb_firmware_failed(aru); -		return; -	} - -	dev_err(&aru->udev->dev, "ar9170.fw firmware file " -		"not found, trying old firmware...\n"); - -	err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", -				      &aru->udev->dev, GFP_KERNEL, aru, -				      ar9170_usb_firmware_inits); -	if (err) -		ar9170_usb_firmware_failed(aru); -} - -static bool ar9170_requires_one_stage(const struct usb_device_id *id) -{ -	if (!id->driver_info) -		return false; -	if (id->driver_info == AR9170_REQ_FW1_ONLY) -		return true; -	return false; -} - -static int ar9170_usb_probe(struct usb_interface *intf, -			const struct usb_device_id *id) -{ -	struct ar9170_usb *aru; -	struct ar9170 *ar; -	struct usb_device *udev; -	int err; - -	aru = ar9170_alloc(sizeof(*aru)); -	if (IS_ERR(aru)) { -		err = PTR_ERR(aru); -		goto out; -	} - -	udev = interface_to_usbdev(intf); -	usb_get_dev(udev); -	aru->udev = udev; -	aru->intf = intf; -	ar = &aru->common; - -	aru->req_one_stage_fw = ar9170_requires_one_stage(id); - -	usb_set_intfdata(intf, aru); -	SET_IEEE80211_DEV(ar->hw, &intf->dev); - -	init_usb_anchor(&aru->rx_submitted); -	init_usb_anchor(&aru->tx_pending); -	init_usb_anchor(&aru->tx_submitted); -	init_completion(&aru->cmd_wait); -	init_completion(&aru->firmware_loading_complete); -	spin_lock_init(&aru->tx_urb_lock); - -	aru->tx_pending_urbs = 0; -	atomic_set(&aru->tx_submitted_urbs, 0); - -	aru->common.stop = ar9170_usb_stop; -	aru->common.flush = ar9170_usb_flush; -	aru->common.open = ar9170_usb_open; -	aru->common.tx = ar9170_usb_tx; -	aru->common.exec_cmd = ar9170_usb_exec_cmd; -	aru->common.callback_cmd = ar9170_usb_callback_cmd; - -#ifdef CONFIG_PM -	udev->reset_resume = 1; -#endif /* CONFIG_PM */ -	err = ar9170_usb_reset(aru); -	if (err) -		goto err_freehw; - -	usb_get_dev(aru->udev); -	return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", -				       &aru->udev->dev, GFP_KERNEL, aru, -				       ar9170_usb_firmware_step2); -err_freehw: -	usb_set_intfdata(intf, NULL); -	usb_put_dev(udev); -	ieee80211_free_hw(ar->hw); -out: -	return err; -} - -static void ar9170_usb_disconnect(struct usb_interface *intf) -{ -	struct ar9170_usb *aru = usb_get_intfdata(intf); - -	if (!aru) -		return; - -	aru->common.state = AR9170_IDLE; - -	wait_for_completion(&aru->firmware_loading_complete); - -	ar9170_unregister(&aru->common); -	ar9170_usb_cancel_urbs(aru); - -	usb_put_dev(aru->udev); -	usb_set_intfdata(intf, NULL); -	ieee80211_free_hw(aru->common.hw); - -	release_firmware(aru->init_values); -	release_firmware(aru->firmware); -} - -#ifdef CONFIG_PM -static int ar9170_suspend(struct usb_interface *intf, -			  pm_message_t  message) -{ -	struct ar9170_usb *aru = usb_get_intfdata(intf); - -	if (!aru) -		return -ENODEV; - -	aru->common.state = AR9170_IDLE; -	ar9170_usb_cancel_urbs(aru); - -	return 0; -} - -static int ar9170_resume(struct usb_interface *intf) -{ -	struct ar9170_usb *aru = usb_get_intfdata(intf); -	int err; - -	if (!aru) -		return -ENODEV; - -	usb_unpoison_anchored_urbs(&aru->rx_submitted); -	usb_unpoison_anchored_urbs(&aru->tx_submitted); - -	err = ar9170_usb_init_device(aru); -	if (err) -		goto err_unrx; - -	err = ar9170_usb_open(&aru->common); -	if (err) -		goto err_unrx; - -	return 0; - -err_unrx: -	aru->common.state = AR9170_IDLE; -	ar9170_usb_cancel_urbs(aru); - -	return err; -} -#endif /* CONFIG_PM */ - -static struct usb_driver ar9170_driver = { -	.name = "ar9170usb", -	.probe = ar9170_usb_probe, -	.disconnect = ar9170_usb_disconnect, -	.id_table = ar9170_usb_ids, -	.soft_unbind = 1, -#ifdef CONFIG_PM -	.suspend = ar9170_suspend, -	.resume = ar9170_resume, -	.reset_resume = ar9170_resume, -#endif /* CONFIG_PM */ -}; - -static int __init ar9170_init(void) -{ -	return usb_register(&ar9170_driver); -} - -static void __exit ar9170_exit(void) -{ -	usb_deregister(&ar9170_driver); -} - -module_init(ar9170_init); -module_exit(ar9170_exit);  | 
