1a84fab3cSChristian Lamparter /* 2a84fab3cSChristian Lamparter * Atheros CARL9170 driver 3a84fab3cSChristian Lamparter * 4a84fab3cSChristian Lamparter * USB - frontend 5a84fab3cSChristian Lamparter * 6a84fab3cSChristian Lamparter * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> 7a84fab3cSChristian Lamparter * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> 8a84fab3cSChristian Lamparter * 9a84fab3cSChristian Lamparter * This program is free software; you can redistribute it and/or modify 10a84fab3cSChristian Lamparter * it under the terms of the GNU General Public License as published by 11a84fab3cSChristian Lamparter * the Free Software Foundation; either version 2 of the License, or 12a84fab3cSChristian Lamparter * (at your option) any later version. 13a84fab3cSChristian Lamparter * 14a84fab3cSChristian Lamparter * This program is distributed in the hope that it will be useful, 15a84fab3cSChristian Lamparter * but WITHOUT ANY WARRANTY; without even the implied warranty of 16a84fab3cSChristian Lamparter * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17a84fab3cSChristian Lamparter * GNU General Public License for more details. 18a84fab3cSChristian Lamparter * 19a84fab3cSChristian Lamparter * You should have received a copy of the GNU General Public License 20a84fab3cSChristian Lamparter * along with this program; see the file COPYING. If not, see 21a84fab3cSChristian Lamparter * http://www.gnu.org/licenses/. 22a84fab3cSChristian Lamparter * 23a84fab3cSChristian Lamparter * This file incorporates work covered by the following copyright and 24a84fab3cSChristian Lamparter * permission notice: 25a84fab3cSChristian Lamparter * Copyright (c) 2007-2008 Atheros Communications, Inc. 26a84fab3cSChristian Lamparter * 27a84fab3cSChristian Lamparter * Permission to use, copy, modify, and/or distribute this software for any 28a84fab3cSChristian Lamparter * purpose with or without fee is hereby granted, provided that the above 29a84fab3cSChristian Lamparter * copyright notice and this permission notice appear in all copies. 30a84fab3cSChristian Lamparter * 31a84fab3cSChristian Lamparter * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 32a84fab3cSChristian Lamparter * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 33a84fab3cSChristian Lamparter * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 34a84fab3cSChristian Lamparter * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 35a84fab3cSChristian Lamparter * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 36a84fab3cSChristian Lamparter * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 37a84fab3cSChristian Lamparter * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 38a84fab3cSChristian Lamparter */ 39a84fab3cSChristian Lamparter 40a84fab3cSChristian Lamparter #include <linux/module.h> 41a84fab3cSChristian Lamparter #include <linux/slab.h> 42a84fab3cSChristian Lamparter #include <linux/usb.h> 43a84fab3cSChristian Lamparter #include <linux/firmware.h> 44a84fab3cSChristian Lamparter #include <linux/etherdevice.h> 45a84fab3cSChristian Lamparter #include <linux/device.h> 46a84fab3cSChristian Lamparter #include <net/mac80211.h> 47a84fab3cSChristian Lamparter #include "carl9170.h" 48a84fab3cSChristian Lamparter #include "cmd.h" 49a84fab3cSChristian Lamparter #include "hw.h" 50a84fab3cSChristian Lamparter #include "fwcmd.h" 51a84fab3cSChristian Lamparter 52a84fab3cSChristian Lamparter MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); 53a84fab3cSChristian Lamparter MODULE_AUTHOR("Christian Lamparter <chunkeey@googlemail.com>"); 54a84fab3cSChristian Lamparter MODULE_LICENSE("GPL"); 55a84fab3cSChristian Lamparter MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); 56a84fab3cSChristian Lamparter MODULE_FIRMWARE(CARL9170FW_NAME); 57a84fab3cSChristian Lamparter MODULE_ALIAS("ar9170usb"); 58a84fab3cSChristian Lamparter MODULE_ALIAS("arusb_lnx"); 59a84fab3cSChristian Lamparter 60a84fab3cSChristian Lamparter /* 61a84fab3cSChristian Lamparter * Note: 62a84fab3cSChristian Lamparter * 63a84fab3cSChristian Lamparter * Always update our wiki's device list (located at: 641141215cSFlavio Suligoi * https://wireless.wiki.kernel.org/en/users/Drivers/ar9170/devices ), 65a84fab3cSChristian Lamparter * whenever you add a new device. 66a84fab3cSChristian Lamparter */ 6776f6a5c8SArvind Yadav static const struct usb_device_id carl9170_usb_ids[] = { 68a84fab3cSChristian Lamparter /* Atheros 9170 */ 69a84fab3cSChristian Lamparter { USB_DEVICE(0x0cf3, 0x9170) }, 70a84fab3cSChristian Lamparter /* Atheros TG121N */ 71a84fab3cSChristian Lamparter { USB_DEVICE(0x0cf3, 0x1001) }, 72a84fab3cSChristian Lamparter /* TP-Link TL-WN821N v2 */ 73a84fab3cSChristian Lamparter { USB_DEVICE(0x0cf3, 0x1002), .driver_info = CARL9170_WPS_BUTTON | 74a84fab3cSChristian Lamparter CARL9170_ONE_LED }, 75a84fab3cSChristian Lamparter /* 3Com Dual Band 802.11n USB Adapter */ 76a84fab3cSChristian Lamparter { USB_DEVICE(0x0cf3, 0x1010) }, 77a84fab3cSChristian Lamparter /* H3C Dual Band 802.11n USB Adapter */ 78a84fab3cSChristian Lamparter { USB_DEVICE(0x0cf3, 0x1011) }, 79a84fab3cSChristian Lamparter /* Cace Airpcap NX */ 80a84fab3cSChristian Lamparter { USB_DEVICE(0xcace, 0x0300) }, 81a84fab3cSChristian Lamparter /* D-Link DWA 160 A1 */ 82a84fab3cSChristian Lamparter { USB_DEVICE(0x07d1, 0x3c10) }, 83a84fab3cSChristian Lamparter /* D-Link DWA 160 A2 */ 84a84fab3cSChristian Lamparter { USB_DEVICE(0x07d1, 0x3a09) }, 858df86db9SChristian Lamparter /* D-Link DWA 130 D */ 868df86db9SChristian Lamparter { USB_DEVICE(0x07d1, 0x3a0f) }, 87a84fab3cSChristian Lamparter /* Netgear WNA1000 */ 88a84fab3cSChristian Lamparter { USB_DEVICE(0x0846, 0x9040) }, 898df86db9SChristian Lamparter /* Netgear WNDA3100 (v1) */ 90a84fab3cSChristian Lamparter { USB_DEVICE(0x0846, 0x9010) }, 91a84fab3cSChristian Lamparter /* Netgear WN111 v2 */ 92a84fab3cSChristian Lamparter { USB_DEVICE(0x0846, 0x9001), .driver_info = CARL9170_ONE_LED }, 93a84fab3cSChristian Lamparter /* Zydas ZD1221 */ 94a84fab3cSChristian Lamparter { USB_DEVICE(0x0ace, 0x1221) }, 95a84fab3cSChristian Lamparter /* Proxim ORiNOCO 802.11n USB */ 96a84fab3cSChristian Lamparter { USB_DEVICE(0x1435, 0x0804) }, 97a84fab3cSChristian Lamparter /* WNC Generic 11n USB Dongle */ 98a84fab3cSChristian Lamparter { USB_DEVICE(0x1435, 0x0326) }, 99a84fab3cSChristian Lamparter /* ZyXEL NWD271N */ 100a84fab3cSChristian Lamparter { USB_DEVICE(0x0586, 0x3417) }, 101a84fab3cSChristian Lamparter /* Z-Com UB81 BG */ 102a84fab3cSChristian Lamparter { USB_DEVICE(0x0cde, 0x0023) }, 103a84fab3cSChristian Lamparter /* Z-Com UB82 ABG */ 104a84fab3cSChristian Lamparter { USB_DEVICE(0x0cde, 0x0026) }, 105a84fab3cSChristian Lamparter /* Sphairon Homelink 1202 */ 106a84fab3cSChristian Lamparter { USB_DEVICE(0x0cde, 0x0027) }, 107a84fab3cSChristian Lamparter /* Arcadyan WN7512 */ 108a84fab3cSChristian Lamparter { USB_DEVICE(0x083a, 0xf522) }, 109a84fab3cSChristian Lamparter /* Planex GWUS300 */ 110a84fab3cSChristian Lamparter { USB_DEVICE(0x2019, 0x5304) }, 111a84fab3cSChristian Lamparter /* IO-Data WNGDNUS2 */ 112a84fab3cSChristian Lamparter { USB_DEVICE(0x04bb, 0x093f) }, 113a84fab3cSChristian Lamparter /* NEC WL300NU-G */ 114a84fab3cSChristian Lamparter { USB_DEVICE(0x0409, 0x0249) }, 11506a86ddbSChristian Lamparter /* NEC WL300NU-AG */ 11606a86ddbSChristian Lamparter { USB_DEVICE(0x0409, 0x02b4) }, 117a84fab3cSChristian Lamparter /* AVM FRITZ!WLAN USB Stick N */ 118a84fab3cSChristian Lamparter { USB_DEVICE(0x057c, 0x8401) }, 119a84fab3cSChristian Lamparter /* AVM FRITZ!WLAN USB Stick N 2.4 */ 120a84fab3cSChristian Lamparter { USB_DEVICE(0x057c, 0x8402) }, 121a84fab3cSChristian Lamparter /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */ 122a84fab3cSChristian Lamparter { USB_DEVICE(0x1668, 0x1200) }, 123c86664e5SJan Puk /* Airlive X.USB a/b/g/n */ 124c86664e5SJan Puk { USB_DEVICE(0x1b75, 0x9170) }, 125a84fab3cSChristian Lamparter 126a84fab3cSChristian Lamparter /* terminate */ 127a84fab3cSChristian Lamparter {} 128a84fab3cSChristian Lamparter }; 129a84fab3cSChristian Lamparter MODULE_DEVICE_TABLE(usb, carl9170_usb_ids); 130a84fab3cSChristian Lamparter 131feb09b29SChristian Lamparter static struct usb_driver carl9170_driver; 132feb09b29SChristian Lamparter 133a84fab3cSChristian Lamparter static void carl9170_usb_submit_data_urb(struct ar9170 *ar) 134a84fab3cSChristian Lamparter { 135a84fab3cSChristian Lamparter struct urb *urb; 136a84fab3cSChristian Lamparter int err; 137a84fab3cSChristian Lamparter 138a84fab3cSChristian Lamparter if (atomic_inc_return(&ar->tx_anch_urbs) > AR9170_NUM_TX_URBS) 139a84fab3cSChristian Lamparter goto err_acc; 140a84fab3cSChristian Lamparter 141a84fab3cSChristian Lamparter urb = usb_get_from_anchor(&ar->tx_wait); 142a84fab3cSChristian Lamparter if (!urb) 143a84fab3cSChristian Lamparter goto err_acc; 144a84fab3cSChristian Lamparter 145a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->tx_anch); 146a84fab3cSChristian Lamparter 147a84fab3cSChristian Lamparter err = usb_submit_urb(urb, GFP_ATOMIC); 148a84fab3cSChristian Lamparter if (unlikely(err)) { 149a84fab3cSChristian Lamparter if (net_ratelimit()) { 150a84fab3cSChristian Lamparter dev_err(&ar->udev->dev, "tx submit failed (%d)\n", 151a84fab3cSChristian Lamparter urb->status); 152a84fab3cSChristian Lamparter } 153a84fab3cSChristian Lamparter 154a84fab3cSChristian Lamparter usb_unanchor_urb(urb); 155a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->tx_err); 156a84fab3cSChristian Lamparter } 157a84fab3cSChristian Lamparter 158a84fab3cSChristian Lamparter usb_free_urb(urb); 159a84fab3cSChristian Lamparter 160a84fab3cSChristian Lamparter if (likely(err == 0)) 161a84fab3cSChristian Lamparter return; 162a84fab3cSChristian Lamparter 163a84fab3cSChristian Lamparter err_acc: 164a84fab3cSChristian Lamparter atomic_dec(&ar->tx_anch_urbs); 165a84fab3cSChristian Lamparter } 166a84fab3cSChristian Lamparter 167a84fab3cSChristian Lamparter static void carl9170_usb_tx_data_complete(struct urb *urb) 168a84fab3cSChristian Lamparter { 169b2767363SJoe Perches struct ar9170 *ar = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); 170a84fab3cSChristian Lamparter 171a84fab3cSChristian Lamparter if (WARN_ON_ONCE(!ar)) { 172a84fab3cSChristian Lamparter dev_kfree_skb_irq(urb->context); 173a84fab3cSChristian Lamparter return; 174a84fab3cSChristian Lamparter } 175a84fab3cSChristian Lamparter 176a84fab3cSChristian Lamparter atomic_dec(&ar->tx_anch_urbs); 177a84fab3cSChristian Lamparter 178a84fab3cSChristian Lamparter switch (urb->status) { 179a84fab3cSChristian Lamparter /* everything is fine */ 180a84fab3cSChristian Lamparter case 0: 181a84fab3cSChristian Lamparter carl9170_tx_callback(ar, (void *)urb->context); 182a84fab3cSChristian Lamparter break; 183a84fab3cSChristian Lamparter 184a84fab3cSChristian Lamparter /* disconnect */ 185a84fab3cSChristian Lamparter case -ENOENT: 186a84fab3cSChristian Lamparter case -ECONNRESET: 187a84fab3cSChristian Lamparter case -ENODEV: 188a84fab3cSChristian Lamparter case -ESHUTDOWN: 189a84fab3cSChristian Lamparter /* 190a84fab3cSChristian Lamparter * Defer the frame clean-up to the tasklet worker. 191a84fab3cSChristian Lamparter * This is necessary, because carl9170_tx_drop 192a84fab3cSChristian Lamparter * does not work in an irqsave context. 193a84fab3cSChristian Lamparter */ 194a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->tx_err); 195a84fab3cSChristian Lamparter return; 196a84fab3cSChristian Lamparter 197a84fab3cSChristian Lamparter /* a random transmission error has occurred? */ 198a84fab3cSChristian Lamparter default: 199a84fab3cSChristian Lamparter if (net_ratelimit()) { 200a84fab3cSChristian Lamparter dev_err(&ar->udev->dev, "tx failed (%d)\n", 201a84fab3cSChristian Lamparter urb->status); 202a84fab3cSChristian Lamparter } 203a84fab3cSChristian Lamparter 204a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->tx_err); 205a84fab3cSChristian Lamparter break; 206a84fab3cSChristian Lamparter } 207a84fab3cSChristian Lamparter 208a84fab3cSChristian Lamparter if (likely(IS_STARTED(ar))) 209a84fab3cSChristian Lamparter carl9170_usb_submit_data_urb(ar); 210a84fab3cSChristian Lamparter } 211a84fab3cSChristian Lamparter 212a84fab3cSChristian Lamparter static int carl9170_usb_submit_cmd_urb(struct ar9170 *ar) 213a84fab3cSChristian Lamparter { 214a84fab3cSChristian Lamparter struct urb *urb; 215a84fab3cSChristian Lamparter int err; 216a84fab3cSChristian Lamparter 217a84fab3cSChristian Lamparter if (atomic_inc_return(&ar->tx_cmd_urbs) != 1) { 218a84fab3cSChristian Lamparter atomic_dec(&ar->tx_cmd_urbs); 219a84fab3cSChristian Lamparter return 0; 220a84fab3cSChristian Lamparter } 221a84fab3cSChristian Lamparter 222a84fab3cSChristian Lamparter urb = usb_get_from_anchor(&ar->tx_cmd); 223a84fab3cSChristian Lamparter if (!urb) { 224a84fab3cSChristian Lamparter atomic_dec(&ar->tx_cmd_urbs); 225a84fab3cSChristian Lamparter return 0; 226a84fab3cSChristian Lamparter } 227a84fab3cSChristian Lamparter 228a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->tx_anch); 229a84fab3cSChristian Lamparter err = usb_submit_urb(urb, GFP_ATOMIC); 230a84fab3cSChristian Lamparter if (unlikely(err)) { 231a84fab3cSChristian Lamparter usb_unanchor_urb(urb); 232a84fab3cSChristian Lamparter atomic_dec(&ar->tx_cmd_urbs); 233a84fab3cSChristian Lamparter } 234a84fab3cSChristian Lamparter usb_free_urb(urb); 235a84fab3cSChristian Lamparter 236a84fab3cSChristian Lamparter return err; 237a84fab3cSChristian Lamparter } 238a84fab3cSChristian Lamparter 239a84fab3cSChristian Lamparter static void carl9170_usb_cmd_complete(struct urb *urb) 240a84fab3cSChristian Lamparter { 241a84fab3cSChristian Lamparter struct ar9170 *ar = urb->context; 242a84fab3cSChristian Lamparter int err = 0; 243a84fab3cSChristian Lamparter 244a84fab3cSChristian Lamparter if (WARN_ON_ONCE(!ar)) 245a84fab3cSChristian Lamparter return; 246a84fab3cSChristian Lamparter 247a84fab3cSChristian Lamparter atomic_dec(&ar->tx_cmd_urbs); 248a84fab3cSChristian Lamparter 249a84fab3cSChristian Lamparter switch (urb->status) { 250a84fab3cSChristian Lamparter /* everything is fine */ 251a84fab3cSChristian Lamparter case 0: 252a84fab3cSChristian Lamparter break; 253a84fab3cSChristian Lamparter 254a84fab3cSChristian Lamparter /* disconnect */ 255a84fab3cSChristian Lamparter case -ENOENT: 256a84fab3cSChristian Lamparter case -ECONNRESET: 257a84fab3cSChristian Lamparter case -ENODEV: 258a84fab3cSChristian Lamparter case -ESHUTDOWN: 259a84fab3cSChristian Lamparter return; 260a84fab3cSChristian Lamparter 261a84fab3cSChristian Lamparter default: 262a84fab3cSChristian Lamparter err = urb->status; 263a84fab3cSChristian Lamparter break; 264a84fab3cSChristian Lamparter } 265a84fab3cSChristian Lamparter 266a84fab3cSChristian Lamparter if (!IS_INITIALIZED(ar)) 267a84fab3cSChristian Lamparter return; 268a84fab3cSChristian Lamparter 269a84fab3cSChristian Lamparter if (err) 270a84fab3cSChristian Lamparter dev_err(&ar->udev->dev, "submit cmd cb failed (%d).\n", err); 271a84fab3cSChristian Lamparter 272a84fab3cSChristian Lamparter err = carl9170_usb_submit_cmd_urb(ar); 273a84fab3cSChristian Lamparter if (err) 274a84fab3cSChristian Lamparter dev_err(&ar->udev->dev, "submit cmd failed (%d).\n", err); 275a84fab3cSChristian Lamparter } 276a84fab3cSChristian Lamparter 277a84fab3cSChristian Lamparter static void carl9170_usb_rx_irq_complete(struct urb *urb) 278a84fab3cSChristian Lamparter { 279a84fab3cSChristian Lamparter struct ar9170 *ar = urb->context; 280a84fab3cSChristian Lamparter 281a84fab3cSChristian Lamparter if (WARN_ON_ONCE(!ar)) 282a84fab3cSChristian Lamparter return; 283a84fab3cSChristian Lamparter 284a84fab3cSChristian Lamparter switch (urb->status) { 285a84fab3cSChristian Lamparter /* everything is fine */ 286a84fab3cSChristian Lamparter case 0: 287a84fab3cSChristian Lamparter break; 288a84fab3cSChristian Lamparter 289a84fab3cSChristian Lamparter /* disconnect */ 290a84fab3cSChristian Lamparter case -ENOENT: 291a84fab3cSChristian Lamparter case -ECONNRESET: 292a84fab3cSChristian Lamparter case -ENODEV: 293a84fab3cSChristian Lamparter case -ESHUTDOWN: 294a84fab3cSChristian Lamparter return; 295a84fab3cSChristian Lamparter 296a84fab3cSChristian Lamparter default: 297a84fab3cSChristian Lamparter goto resubmit; 298a84fab3cSChristian Lamparter } 299a84fab3cSChristian Lamparter 300b4764c80SChristian Lamparter /* 301b4764c80SChristian Lamparter * While the carl9170 firmware does not use this EP, the 302b4764c80SChristian Lamparter * firmware loader in the EEPROM unfortunately does. 303b4764c80SChristian Lamparter * Therefore we need to be ready to handle out-of-band 304b4764c80SChristian Lamparter * responses and traps in case the firmware crashed and 305b4764c80SChristian Lamparter * the loader took over again. 306b4764c80SChristian Lamparter */ 307a84fab3cSChristian Lamparter carl9170_handle_command_response(ar, urb->transfer_buffer, 308a84fab3cSChristian Lamparter urb->actual_length); 309a84fab3cSChristian Lamparter 310a84fab3cSChristian Lamparter resubmit: 311a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->rx_anch); 312a84fab3cSChristian Lamparter if (unlikely(usb_submit_urb(urb, GFP_ATOMIC))) 313a84fab3cSChristian Lamparter usb_unanchor_urb(urb); 314a84fab3cSChristian Lamparter } 315a84fab3cSChristian Lamparter 316a84fab3cSChristian Lamparter static int carl9170_usb_submit_rx_urb(struct ar9170 *ar, gfp_t gfp) 317a84fab3cSChristian Lamparter { 318a84fab3cSChristian Lamparter struct urb *urb; 319a84fab3cSChristian Lamparter int err = 0, runs = 0; 320a84fab3cSChristian Lamparter 321a84fab3cSChristian Lamparter while ((atomic_read(&ar->rx_anch_urbs) < AR9170_NUM_RX_URBS) && 322a84fab3cSChristian Lamparter (runs++ < AR9170_NUM_RX_URBS)) { 323a84fab3cSChristian Lamparter err = -ENOSPC; 324a84fab3cSChristian Lamparter urb = usb_get_from_anchor(&ar->rx_pool); 325a84fab3cSChristian Lamparter if (urb) { 326a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->rx_anch); 327a84fab3cSChristian Lamparter err = usb_submit_urb(urb, gfp); 328a84fab3cSChristian Lamparter if (unlikely(err)) { 329a84fab3cSChristian Lamparter usb_unanchor_urb(urb); 330a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->rx_pool); 331a84fab3cSChristian Lamparter } else { 332a84fab3cSChristian Lamparter atomic_dec(&ar->rx_pool_urbs); 333a84fab3cSChristian Lamparter atomic_inc(&ar->rx_anch_urbs); 334a84fab3cSChristian Lamparter } 335a84fab3cSChristian Lamparter usb_free_urb(urb); 336a84fab3cSChristian Lamparter } 337a84fab3cSChristian Lamparter } 338a84fab3cSChristian Lamparter 339a84fab3cSChristian Lamparter return err; 340a84fab3cSChristian Lamparter } 341a84fab3cSChristian Lamparter 342a84fab3cSChristian Lamparter static void carl9170_usb_rx_work(struct ar9170 *ar) 343a84fab3cSChristian Lamparter { 344a84fab3cSChristian Lamparter struct urb *urb; 345a84fab3cSChristian Lamparter int i; 346a84fab3cSChristian Lamparter 347a84fab3cSChristian Lamparter for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) { 348a84fab3cSChristian Lamparter urb = usb_get_from_anchor(&ar->rx_work); 349a84fab3cSChristian Lamparter if (!urb) 350a84fab3cSChristian Lamparter break; 351a84fab3cSChristian Lamparter 352a84fab3cSChristian Lamparter atomic_dec(&ar->rx_work_urbs); 353a84fab3cSChristian Lamparter if (IS_INITIALIZED(ar)) { 354a84fab3cSChristian Lamparter carl9170_rx(ar, urb->transfer_buffer, 355a84fab3cSChristian Lamparter urb->actual_length); 356a84fab3cSChristian Lamparter } 357a84fab3cSChristian Lamparter 358a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->rx_pool); 359a84fab3cSChristian Lamparter atomic_inc(&ar->rx_pool_urbs); 360a84fab3cSChristian Lamparter 361a84fab3cSChristian Lamparter usb_free_urb(urb); 362a84fab3cSChristian Lamparter 363a84fab3cSChristian Lamparter carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC); 364a84fab3cSChristian Lamparter } 365a84fab3cSChristian Lamparter } 366a84fab3cSChristian Lamparter 367a84fab3cSChristian Lamparter void carl9170_usb_handle_tx_err(struct ar9170 *ar) 368a84fab3cSChristian Lamparter { 369a84fab3cSChristian Lamparter struct urb *urb; 370a84fab3cSChristian Lamparter 371a84fab3cSChristian Lamparter while ((urb = usb_get_from_anchor(&ar->tx_err))) { 372a84fab3cSChristian Lamparter struct sk_buff *skb = (void *)urb->context; 373a84fab3cSChristian Lamparter 374a84fab3cSChristian Lamparter carl9170_tx_drop(ar, skb); 375a84fab3cSChristian Lamparter carl9170_tx_callback(ar, skb); 376a84fab3cSChristian Lamparter usb_free_urb(urb); 377a84fab3cSChristian Lamparter } 378a84fab3cSChristian Lamparter } 379a84fab3cSChristian Lamparter 380*de7dbc2dSAllen Pais static void carl9170_usb_tasklet(struct tasklet_struct *t) 381a84fab3cSChristian Lamparter { 382*de7dbc2dSAllen Pais struct ar9170 *ar = from_tasklet(ar, t, usb_tasklet); 383a84fab3cSChristian Lamparter 384cf6487d0SChristian Lamparter if (!IS_INITIALIZED(ar)) 385cf6487d0SChristian Lamparter return; 386cf6487d0SChristian Lamparter 387a84fab3cSChristian Lamparter carl9170_usb_rx_work(ar); 388a84fab3cSChristian Lamparter 389a84fab3cSChristian Lamparter /* 390a84fab3cSChristian Lamparter * Strictly speaking: The tx scheduler is not part of the USB system. 391a84fab3cSChristian Lamparter * But the rx worker returns frames back to the mac80211-stack and 392a84fab3cSChristian Lamparter * this is the _perfect_ place to generate the next transmissions. 393a84fab3cSChristian Lamparter */ 394a84fab3cSChristian Lamparter if (IS_STARTED(ar)) 395a84fab3cSChristian Lamparter carl9170_tx_scheduler(ar); 396a84fab3cSChristian Lamparter } 397a84fab3cSChristian Lamparter 398a84fab3cSChristian Lamparter static void carl9170_usb_rx_complete(struct urb *urb) 399a84fab3cSChristian Lamparter { 400a84fab3cSChristian Lamparter struct ar9170 *ar = (struct ar9170 *)urb->context; 401a84fab3cSChristian Lamparter int err; 402a84fab3cSChristian Lamparter 403a84fab3cSChristian Lamparter if (WARN_ON_ONCE(!ar)) 404a84fab3cSChristian Lamparter return; 405a84fab3cSChristian Lamparter 406a84fab3cSChristian Lamparter atomic_dec(&ar->rx_anch_urbs); 407a84fab3cSChristian Lamparter 408a84fab3cSChristian Lamparter switch (urb->status) { 409a84fab3cSChristian Lamparter case 0: 410a84fab3cSChristian Lamparter /* rx path */ 411a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->rx_work); 412a84fab3cSChristian Lamparter atomic_inc(&ar->rx_work_urbs); 413a84fab3cSChristian Lamparter break; 414a84fab3cSChristian Lamparter 415a84fab3cSChristian Lamparter case -ENOENT: 416a84fab3cSChristian Lamparter case -ECONNRESET: 417a84fab3cSChristian Lamparter case -ENODEV: 418a84fab3cSChristian Lamparter case -ESHUTDOWN: 419a84fab3cSChristian Lamparter /* handle disconnect events*/ 420a84fab3cSChristian Lamparter return; 421a84fab3cSChristian Lamparter 422a84fab3cSChristian Lamparter default: 423a84fab3cSChristian Lamparter /* handle all other errors */ 424a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->rx_pool); 425a84fab3cSChristian Lamparter atomic_inc(&ar->rx_pool_urbs); 426a84fab3cSChristian Lamparter break; 427a84fab3cSChristian Lamparter } 428a84fab3cSChristian Lamparter 429a84fab3cSChristian Lamparter err = carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC); 430a84fab3cSChristian Lamparter if (unlikely(err)) { 431a84fab3cSChristian Lamparter /* 432a84fab3cSChristian Lamparter * usb_submit_rx_urb reported a problem. 433a84fab3cSChristian Lamparter * In case this is due to a rx buffer shortage, 434a84fab3cSChristian Lamparter * elevate the tasklet worker priority to 435a84fab3cSChristian Lamparter * the highest available level. 436a84fab3cSChristian Lamparter */ 437a84fab3cSChristian Lamparter tasklet_hi_schedule(&ar->usb_tasklet); 438a84fab3cSChristian Lamparter 439a84fab3cSChristian Lamparter if (atomic_read(&ar->rx_anch_urbs) == 0) { 440a84fab3cSChristian Lamparter /* 441a84fab3cSChristian Lamparter * The system is too slow to cope with 442a84fab3cSChristian Lamparter * the enormous workload. We have simply 443a84fab3cSChristian Lamparter * run out of active rx urbs and this 44425985edcSLucas De Marchi * unfortunately leads to an unpredictable 445a84fab3cSChristian Lamparter * device. 446a84fab3cSChristian Lamparter */ 447a84fab3cSChristian Lamparter 448e4a668c5SChristian Lamparter ieee80211_queue_work(ar->hw, &ar->ping_work); 449a84fab3cSChristian Lamparter } 450a84fab3cSChristian Lamparter } else { 451a84fab3cSChristian Lamparter /* 452a84fab3cSChristian Lamparter * Using anything less than _high_ priority absolutely 453a84fab3cSChristian Lamparter * kills the rx performance my UP-System... 454a84fab3cSChristian Lamparter */ 455a84fab3cSChristian Lamparter tasklet_hi_schedule(&ar->usb_tasklet); 456a84fab3cSChristian Lamparter } 457a84fab3cSChristian Lamparter } 458a84fab3cSChristian Lamparter 459a84fab3cSChristian Lamparter static struct urb *carl9170_usb_alloc_rx_urb(struct ar9170 *ar, gfp_t gfp) 460a84fab3cSChristian Lamparter { 461a84fab3cSChristian Lamparter struct urb *urb; 462a84fab3cSChristian Lamparter void *buf; 463a84fab3cSChristian Lamparter 464a84fab3cSChristian Lamparter buf = kmalloc(ar->fw.rx_size, gfp); 465a84fab3cSChristian Lamparter if (!buf) 466a84fab3cSChristian Lamparter return NULL; 467a84fab3cSChristian Lamparter 468a84fab3cSChristian Lamparter urb = usb_alloc_urb(0, gfp); 469a84fab3cSChristian Lamparter if (!urb) { 470a84fab3cSChristian Lamparter kfree(buf); 471a84fab3cSChristian Lamparter return NULL; 472a84fab3cSChristian Lamparter } 473a84fab3cSChristian Lamparter 474a84fab3cSChristian Lamparter usb_fill_bulk_urb(urb, ar->udev, usb_rcvbulkpipe(ar->udev, 475a84fab3cSChristian Lamparter AR9170_USB_EP_RX), buf, ar->fw.rx_size, 476a84fab3cSChristian Lamparter carl9170_usb_rx_complete, ar); 477a84fab3cSChristian Lamparter 478a84fab3cSChristian Lamparter urb->transfer_flags |= URB_FREE_BUFFER; 479a84fab3cSChristian Lamparter 480a84fab3cSChristian Lamparter return urb; 481a84fab3cSChristian Lamparter } 482a84fab3cSChristian Lamparter 483a84fab3cSChristian Lamparter static int carl9170_usb_send_rx_irq_urb(struct ar9170 *ar) 484a84fab3cSChristian Lamparter { 485a84fab3cSChristian Lamparter struct urb *urb = NULL; 486a84fab3cSChristian Lamparter void *ibuf; 487a84fab3cSChristian Lamparter int err = -ENOMEM; 488a84fab3cSChristian Lamparter 489a84fab3cSChristian Lamparter urb = usb_alloc_urb(0, GFP_KERNEL); 490a84fab3cSChristian Lamparter if (!urb) 491a84fab3cSChristian Lamparter goto out; 492a84fab3cSChristian Lamparter 493a84fab3cSChristian Lamparter ibuf = kmalloc(AR9170_USB_EP_CTRL_MAX, GFP_KERNEL); 494a84fab3cSChristian Lamparter if (!ibuf) 495a84fab3cSChristian Lamparter goto out; 496a84fab3cSChristian Lamparter 497a84fab3cSChristian Lamparter usb_fill_int_urb(urb, ar->udev, usb_rcvintpipe(ar->udev, 498a84fab3cSChristian Lamparter AR9170_USB_EP_IRQ), ibuf, AR9170_USB_EP_CTRL_MAX, 499a84fab3cSChristian Lamparter carl9170_usb_rx_irq_complete, ar, 1); 500a84fab3cSChristian Lamparter 501a84fab3cSChristian Lamparter urb->transfer_flags |= URB_FREE_BUFFER; 502a84fab3cSChristian Lamparter 503a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->rx_anch); 504a84fab3cSChristian Lamparter err = usb_submit_urb(urb, GFP_KERNEL); 505a84fab3cSChristian Lamparter if (err) 506a84fab3cSChristian Lamparter usb_unanchor_urb(urb); 507a84fab3cSChristian Lamparter 508a84fab3cSChristian Lamparter out: 509a84fab3cSChristian Lamparter usb_free_urb(urb); 510a84fab3cSChristian Lamparter return err; 511a84fab3cSChristian Lamparter } 512a84fab3cSChristian Lamparter 513a84fab3cSChristian Lamparter static int carl9170_usb_init_rx_bulk_urbs(struct ar9170 *ar) 514a84fab3cSChristian Lamparter { 515a84fab3cSChristian Lamparter struct urb *urb; 516a84fab3cSChristian Lamparter int i, err = -EINVAL; 517a84fab3cSChristian Lamparter 518a84fab3cSChristian Lamparter /* 519a84fab3cSChristian Lamparter * The driver actively maintains a second shadow 520a84fab3cSChristian Lamparter * pool for inactive, but fully-prepared rx urbs. 521a84fab3cSChristian Lamparter * 522a84fab3cSChristian Lamparter * The pool should help the driver to master huge 523a84fab3cSChristian Lamparter * workload spikes without running the risk of 524a84fab3cSChristian Lamparter * undersupplying the hardware or wasting time by 525a84fab3cSChristian Lamparter * processing rx data (streams) inside the urb 526a84fab3cSChristian Lamparter * completion (hardirq context). 527a84fab3cSChristian Lamparter */ 528a84fab3cSChristian Lamparter for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) { 529a84fab3cSChristian Lamparter urb = carl9170_usb_alloc_rx_urb(ar, GFP_KERNEL); 530a84fab3cSChristian Lamparter if (!urb) { 531a84fab3cSChristian Lamparter err = -ENOMEM; 532a84fab3cSChristian Lamparter goto err_out; 533a84fab3cSChristian Lamparter } 534a84fab3cSChristian Lamparter 535a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->rx_pool); 536a84fab3cSChristian Lamparter atomic_inc(&ar->rx_pool_urbs); 537a84fab3cSChristian Lamparter usb_free_urb(urb); 538a84fab3cSChristian Lamparter } 539a84fab3cSChristian Lamparter 540a84fab3cSChristian Lamparter err = carl9170_usb_submit_rx_urb(ar, GFP_KERNEL); 541a84fab3cSChristian Lamparter if (err) 542a84fab3cSChristian Lamparter goto err_out; 543a84fab3cSChristian Lamparter 544a84fab3cSChristian Lamparter /* the device now waiting for the firmware. */ 545a84fab3cSChristian Lamparter carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE); 546a84fab3cSChristian Lamparter return 0; 547a84fab3cSChristian Lamparter 548a84fab3cSChristian Lamparter err_out: 549a84fab3cSChristian Lamparter 550a84fab3cSChristian Lamparter usb_scuttle_anchored_urbs(&ar->rx_pool); 551a84fab3cSChristian Lamparter usb_scuttle_anchored_urbs(&ar->rx_work); 552a84fab3cSChristian Lamparter usb_kill_anchored_urbs(&ar->rx_anch); 553a84fab3cSChristian Lamparter return err; 554a84fab3cSChristian Lamparter } 555a84fab3cSChristian Lamparter 556a84fab3cSChristian Lamparter static int carl9170_usb_flush(struct ar9170 *ar) 557a84fab3cSChristian Lamparter { 558a84fab3cSChristian Lamparter struct urb *urb; 559a84fab3cSChristian Lamparter int ret, err = 0; 560a84fab3cSChristian Lamparter 561a84fab3cSChristian Lamparter while ((urb = usb_get_from_anchor(&ar->tx_wait))) { 562a84fab3cSChristian Lamparter struct sk_buff *skb = (void *)urb->context; 563a84fab3cSChristian Lamparter carl9170_tx_drop(ar, skb); 564a84fab3cSChristian Lamparter carl9170_tx_callback(ar, skb); 565a84fab3cSChristian Lamparter usb_free_urb(urb); 566a84fab3cSChristian Lamparter } 567a84fab3cSChristian Lamparter 568dfa31fefSChristian Lamparter ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, 1000); 569a84fab3cSChristian Lamparter if (ret == 0) 570a84fab3cSChristian Lamparter err = -ETIMEDOUT; 571a84fab3cSChristian Lamparter 572a84fab3cSChristian Lamparter /* lets wait a while until the tx - queues are dried out */ 573dfa31fefSChristian Lamparter ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, 1000); 574a84fab3cSChristian Lamparter if (ret == 0) 575a84fab3cSChristian Lamparter err = -ETIMEDOUT; 576a84fab3cSChristian Lamparter 577a84fab3cSChristian Lamparter usb_kill_anchored_urbs(&ar->tx_anch); 578a84fab3cSChristian Lamparter carl9170_usb_handle_tx_err(ar); 579a84fab3cSChristian Lamparter 580a84fab3cSChristian Lamparter return err; 581a84fab3cSChristian Lamparter } 582a84fab3cSChristian Lamparter 583a84fab3cSChristian Lamparter static void carl9170_usb_cancel_urbs(struct ar9170 *ar) 584a84fab3cSChristian Lamparter { 585a84fab3cSChristian Lamparter int err; 586a84fab3cSChristian Lamparter 587a84fab3cSChristian Lamparter carl9170_set_state(ar, CARL9170_UNKNOWN_STATE); 588a84fab3cSChristian Lamparter 589a84fab3cSChristian Lamparter err = carl9170_usb_flush(ar); 590a84fab3cSChristian Lamparter if (err) 591a84fab3cSChristian Lamparter dev_err(&ar->udev->dev, "stuck tx urbs!\n"); 592a84fab3cSChristian Lamparter 593a84fab3cSChristian Lamparter usb_poison_anchored_urbs(&ar->tx_anch); 594a84fab3cSChristian Lamparter carl9170_usb_handle_tx_err(ar); 595a84fab3cSChristian Lamparter usb_poison_anchored_urbs(&ar->rx_anch); 596a84fab3cSChristian Lamparter 597a84fab3cSChristian Lamparter tasklet_kill(&ar->usb_tasklet); 598a84fab3cSChristian Lamparter 599a84fab3cSChristian Lamparter usb_scuttle_anchored_urbs(&ar->rx_work); 600a84fab3cSChristian Lamparter usb_scuttle_anchored_urbs(&ar->rx_pool); 601a84fab3cSChristian Lamparter usb_scuttle_anchored_urbs(&ar->tx_cmd); 602a84fab3cSChristian Lamparter } 603a84fab3cSChristian Lamparter 604a84fab3cSChristian Lamparter int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd, 605a84fab3cSChristian Lamparter const bool free_buf) 606a84fab3cSChristian Lamparter { 607a84fab3cSChristian Lamparter struct urb *urb; 608cae7f953SChristian Lamparter int err = 0; 609a84fab3cSChristian Lamparter 610cae7f953SChristian Lamparter if (!IS_INITIALIZED(ar)) { 611cae7f953SChristian Lamparter err = -EPERM; 612cae7f953SChristian Lamparter goto err_free; 613cae7f953SChristian Lamparter } 614a84fab3cSChristian Lamparter 615cae7f953SChristian Lamparter if (WARN_ON(cmd->hdr.len > CARL9170_MAX_CMD_LEN - 4)) { 616cae7f953SChristian Lamparter err = -EINVAL; 617cae7f953SChristian Lamparter goto err_free; 618cae7f953SChristian Lamparter } 619a84fab3cSChristian Lamparter 620a84fab3cSChristian Lamparter urb = usb_alloc_urb(0, GFP_ATOMIC); 621cae7f953SChristian Lamparter if (!urb) { 622cae7f953SChristian Lamparter err = -ENOMEM; 623cae7f953SChristian Lamparter goto err_free; 624cae7f953SChristian Lamparter } 625a84fab3cSChristian Lamparter 626671796ddSRonald Wahl if (ar->usb_ep_cmd_is_bulk) 627671796ddSRonald Wahl usb_fill_bulk_urb(urb, ar->udev, 628671796ddSRonald Wahl usb_sndbulkpipe(ar->udev, AR9170_USB_EP_CMD), 629671796ddSRonald Wahl cmd, cmd->hdr.len + 4, 630671796ddSRonald Wahl carl9170_usb_cmd_complete, ar); 631671796ddSRonald Wahl else 632671796ddSRonald Wahl usb_fill_int_urb(urb, ar->udev, 633671796ddSRonald Wahl usb_sndintpipe(ar->udev, AR9170_USB_EP_CMD), 634671796ddSRonald Wahl cmd, cmd->hdr.len + 4, 635a84fab3cSChristian Lamparter carl9170_usb_cmd_complete, ar, 1); 636a84fab3cSChristian Lamparter 637a84fab3cSChristian Lamparter if (free_buf) 638a84fab3cSChristian Lamparter urb->transfer_flags |= URB_FREE_BUFFER; 639a84fab3cSChristian Lamparter 640a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->tx_cmd); 641a84fab3cSChristian Lamparter usb_free_urb(urb); 642a84fab3cSChristian Lamparter 643a84fab3cSChristian Lamparter return carl9170_usb_submit_cmd_urb(ar); 644cae7f953SChristian Lamparter 645cae7f953SChristian Lamparter err_free: 646cae7f953SChristian Lamparter if (free_buf) 647cae7f953SChristian Lamparter kfree(cmd); 648cae7f953SChristian Lamparter 649cae7f953SChristian Lamparter return err; 650a84fab3cSChristian Lamparter } 651a84fab3cSChristian Lamparter 652a84fab3cSChristian Lamparter int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd, 653a84fab3cSChristian Lamparter unsigned int plen, void *payload, unsigned int outlen, void *out) 654a84fab3cSChristian Lamparter { 655a84fab3cSChristian Lamparter int err = -ENOMEM; 6564b3e845aSNicholas Mc Guire unsigned long time_left; 657a84fab3cSChristian Lamparter 658a84fab3cSChristian Lamparter if (!IS_ACCEPTING_CMD(ar)) 659a84fab3cSChristian Lamparter return -EIO; 660a84fab3cSChristian Lamparter 661a84fab3cSChristian Lamparter if (!(cmd & CARL9170_CMD_ASYNC_FLAG)) 662a84fab3cSChristian Lamparter might_sleep(); 663a84fab3cSChristian Lamparter 664a84fab3cSChristian Lamparter ar->cmd.hdr.len = plen; 665a84fab3cSChristian Lamparter ar->cmd.hdr.cmd = cmd; 666a84fab3cSChristian Lamparter /* writing multiple regs fills this buffer already */ 667a84fab3cSChristian Lamparter if (plen && payload != (u8 *)(ar->cmd.data)) 668a84fab3cSChristian Lamparter memcpy(ar->cmd.data, payload, plen); 669a84fab3cSChristian Lamparter 670a84fab3cSChristian Lamparter spin_lock_bh(&ar->cmd_lock); 671a84fab3cSChristian Lamparter ar->readbuf = (u8 *)out; 672a84fab3cSChristian Lamparter ar->readlen = outlen; 673a84fab3cSChristian Lamparter spin_unlock_bh(&ar->cmd_lock); 674a84fab3cSChristian Lamparter 67578a9e170SDaniel Wagner reinit_completion(&ar->cmd_wait); 676a84fab3cSChristian Lamparter err = __carl9170_exec_cmd(ar, &ar->cmd, false); 677a84fab3cSChristian Lamparter 678a84fab3cSChristian Lamparter if (!(cmd & CARL9170_CMD_ASYNC_FLAG)) { 6794b3e845aSNicholas Mc Guire time_left = wait_for_completion_timeout(&ar->cmd_wait, HZ); 6804b3e845aSNicholas Mc Guire if (time_left == 0) { 681a84fab3cSChristian Lamparter err = -ETIMEDOUT; 682a84fab3cSChristian Lamparter goto err_unbuf; 683a84fab3cSChristian Lamparter } 684a84fab3cSChristian Lamparter 685a84fab3cSChristian Lamparter if (ar->readlen != outlen) { 686a84fab3cSChristian Lamparter err = -EMSGSIZE; 687a84fab3cSChristian Lamparter goto err_unbuf; 688a84fab3cSChristian Lamparter } 689a84fab3cSChristian Lamparter } 690a84fab3cSChristian Lamparter 691a84fab3cSChristian Lamparter return 0; 692a84fab3cSChristian Lamparter 693a84fab3cSChristian Lamparter err_unbuf: 694a84fab3cSChristian Lamparter /* Maybe the device was removed in the moment we were waiting? */ 695a84fab3cSChristian Lamparter if (IS_STARTED(ar)) { 696a84fab3cSChristian Lamparter dev_err(&ar->udev->dev, "no command feedback " 697a84fab3cSChristian Lamparter "received (%d).\n", err); 698a84fab3cSChristian Lamparter 699a84fab3cSChristian Lamparter /* provide some maybe useful debug information */ 700a84fab3cSChristian Lamparter print_hex_dump_bytes("carl9170 cmd: ", DUMP_PREFIX_NONE, 701a84fab3cSChristian Lamparter &ar->cmd, plen + 4); 702a84fab3cSChristian Lamparter 703a84fab3cSChristian Lamparter carl9170_restart(ar, CARL9170_RR_COMMAND_TIMEOUT); 704a84fab3cSChristian Lamparter } 705a84fab3cSChristian Lamparter 706a84fab3cSChristian Lamparter /* invalidate to avoid completing the next command prematurely */ 707a84fab3cSChristian Lamparter spin_lock_bh(&ar->cmd_lock); 708a84fab3cSChristian Lamparter ar->readbuf = NULL; 709a84fab3cSChristian Lamparter ar->readlen = 0; 710a84fab3cSChristian Lamparter spin_unlock_bh(&ar->cmd_lock); 711a84fab3cSChristian Lamparter 712a84fab3cSChristian Lamparter return err; 713a84fab3cSChristian Lamparter } 714a84fab3cSChristian Lamparter 715a84fab3cSChristian Lamparter void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) 716a84fab3cSChristian Lamparter { 717a84fab3cSChristian Lamparter struct urb *urb; 718a84fab3cSChristian Lamparter struct ar9170_stream *tx_stream; 719a84fab3cSChristian Lamparter void *data; 720a84fab3cSChristian Lamparter unsigned int len; 721a84fab3cSChristian Lamparter 722a84fab3cSChristian Lamparter if (!IS_STARTED(ar)) 723a84fab3cSChristian Lamparter goto err_drop; 724a84fab3cSChristian Lamparter 725a84fab3cSChristian Lamparter urb = usb_alloc_urb(0, GFP_ATOMIC); 726a84fab3cSChristian Lamparter if (!urb) 727a84fab3cSChristian Lamparter goto err_drop; 728a84fab3cSChristian Lamparter 729a84fab3cSChristian Lamparter if (ar->fw.tx_stream) { 730a84fab3cSChristian Lamparter tx_stream = (void *) (skb->data - sizeof(*tx_stream)); 731a84fab3cSChristian Lamparter 732a84fab3cSChristian Lamparter len = skb->len + sizeof(*tx_stream); 733a84fab3cSChristian Lamparter tx_stream->length = cpu_to_le16(len); 734a84fab3cSChristian Lamparter tx_stream->tag = cpu_to_le16(AR9170_TX_STREAM_TAG); 735a84fab3cSChristian Lamparter data = tx_stream; 736a84fab3cSChristian Lamparter } else { 737a84fab3cSChristian Lamparter data = skb->data; 738a84fab3cSChristian Lamparter len = skb->len; 739a84fab3cSChristian Lamparter } 740a84fab3cSChristian Lamparter 741a84fab3cSChristian Lamparter usb_fill_bulk_urb(urb, ar->udev, usb_sndbulkpipe(ar->udev, 742a84fab3cSChristian Lamparter AR9170_USB_EP_TX), data, len, 743a84fab3cSChristian Lamparter carl9170_usb_tx_data_complete, skb); 744a84fab3cSChristian Lamparter 745a84fab3cSChristian Lamparter urb->transfer_flags |= URB_ZERO_PACKET; 746a84fab3cSChristian Lamparter 747a84fab3cSChristian Lamparter usb_anchor_urb(urb, &ar->tx_wait); 748a84fab3cSChristian Lamparter 749a84fab3cSChristian Lamparter usb_free_urb(urb); 750a84fab3cSChristian Lamparter 751a84fab3cSChristian Lamparter carl9170_usb_submit_data_urb(ar); 752a84fab3cSChristian Lamparter return; 753a84fab3cSChristian Lamparter 754a84fab3cSChristian Lamparter err_drop: 755a84fab3cSChristian Lamparter carl9170_tx_drop(ar, skb); 756a84fab3cSChristian Lamparter carl9170_tx_callback(ar, skb); 757a84fab3cSChristian Lamparter } 758a84fab3cSChristian Lamparter 759a84fab3cSChristian Lamparter static void carl9170_release_firmware(struct ar9170 *ar) 760a84fab3cSChristian Lamparter { 761a84fab3cSChristian Lamparter if (ar->fw.fw) { 762a84fab3cSChristian Lamparter release_firmware(ar->fw.fw); 763a84fab3cSChristian Lamparter memset(&ar->fw, 0, sizeof(ar->fw)); 764a84fab3cSChristian Lamparter } 765a84fab3cSChristian Lamparter } 766a84fab3cSChristian Lamparter 767a84fab3cSChristian Lamparter void carl9170_usb_stop(struct ar9170 *ar) 768a84fab3cSChristian Lamparter { 769a84fab3cSChristian Lamparter int ret; 770a84fab3cSChristian Lamparter 771a84fab3cSChristian Lamparter carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STOPPED); 772a84fab3cSChristian Lamparter 773a84fab3cSChristian Lamparter ret = carl9170_usb_flush(ar); 774a84fab3cSChristian Lamparter if (ret) 775a84fab3cSChristian Lamparter dev_err(&ar->udev->dev, "kill pending tx urbs.\n"); 776a84fab3cSChristian Lamparter 777a84fab3cSChristian Lamparter usb_poison_anchored_urbs(&ar->tx_anch); 778a84fab3cSChristian Lamparter carl9170_usb_handle_tx_err(ar); 779a84fab3cSChristian Lamparter 780a84fab3cSChristian Lamparter /* kill any pending command */ 781a84fab3cSChristian Lamparter spin_lock_bh(&ar->cmd_lock); 782a84fab3cSChristian Lamparter ar->readlen = 0; 783a84fab3cSChristian Lamparter spin_unlock_bh(&ar->cmd_lock); 78478a9e170SDaniel Wagner complete(&ar->cmd_wait); 785a84fab3cSChristian Lamparter 786a84fab3cSChristian Lamparter /* 787a84fab3cSChristian Lamparter * Note: 788a84fab3cSChristian Lamparter * So far we freed all tx urbs, but we won't dare to touch any rx urbs. 789a84fab3cSChristian Lamparter * Else we would end up with a unresponsive device... 790a84fab3cSChristian Lamparter */ 791a84fab3cSChristian Lamparter } 792a84fab3cSChristian Lamparter 793a84fab3cSChristian Lamparter int carl9170_usb_open(struct ar9170 *ar) 794a84fab3cSChristian Lamparter { 795a84fab3cSChristian Lamparter usb_unpoison_anchored_urbs(&ar->tx_anch); 796a84fab3cSChristian Lamparter 797a84fab3cSChristian Lamparter carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE); 798a84fab3cSChristian Lamparter return 0; 799a84fab3cSChristian Lamparter } 800a84fab3cSChristian Lamparter 801a84fab3cSChristian Lamparter static int carl9170_usb_load_firmware(struct ar9170 *ar) 802a84fab3cSChristian Lamparter { 803a84fab3cSChristian Lamparter const u8 *data; 804a84fab3cSChristian Lamparter u8 *buf; 805a84fab3cSChristian Lamparter unsigned int transfer; 806a84fab3cSChristian Lamparter size_t len; 807a84fab3cSChristian Lamparter u32 addr; 808a84fab3cSChristian Lamparter int err = 0; 809a84fab3cSChristian Lamparter 810a84fab3cSChristian Lamparter buf = kmalloc(4096, GFP_KERNEL); 811a84fab3cSChristian Lamparter if (!buf) { 812a84fab3cSChristian Lamparter err = -ENOMEM; 813a84fab3cSChristian Lamparter goto err_out; 814a84fab3cSChristian Lamparter } 815a84fab3cSChristian Lamparter 816a84fab3cSChristian Lamparter data = ar->fw.fw->data; 817a84fab3cSChristian Lamparter len = ar->fw.fw->size; 818a84fab3cSChristian Lamparter addr = ar->fw.address; 819a84fab3cSChristian Lamparter 820a84fab3cSChristian Lamparter /* this removes the miniboot image */ 821a84fab3cSChristian Lamparter data += ar->fw.offset; 822a84fab3cSChristian Lamparter len -= ar->fw.offset; 823a84fab3cSChristian Lamparter 824a84fab3cSChristian Lamparter while (len) { 825a84fab3cSChristian Lamparter transfer = min_t(unsigned int, len, 4096u); 826a84fab3cSChristian Lamparter memcpy(buf, data, transfer); 827a84fab3cSChristian Lamparter 828a84fab3cSChristian Lamparter err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0), 829a84fab3cSChristian Lamparter 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, 830a84fab3cSChristian Lamparter addr >> 8, 0, buf, transfer, 100); 831a84fab3cSChristian Lamparter 832a84fab3cSChristian Lamparter if (err < 0) { 833a84fab3cSChristian Lamparter kfree(buf); 834a84fab3cSChristian Lamparter goto err_out; 835a84fab3cSChristian Lamparter } 836a84fab3cSChristian Lamparter 837a84fab3cSChristian Lamparter len -= transfer; 838a84fab3cSChristian Lamparter data += transfer; 839a84fab3cSChristian Lamparter addr += transfer; 840a84fab3cSChristian Lamparter } 841a84fab3cSChristian Lamparter kfree(buf); 842a84fab3cSChristian Lamparter 843a84fab3cSChristian Lamparter err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0), 844a84fab3cSChristian Lamparter 0x31 /* FW DL COMPLETE */, 845a84fab3cSChristian Lamparter 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 200); 846a84fab3cSChristian Lamparter 847a84fab3cSChristian Lamparter if (wait_for_completion_timeout(&ar->fw_boot_wait, HZ) == 0) { 848a84fab3cSChristian Lamparter err = -ETIMEDOUT; 849a84fab3cSChristian Lamparter goto err_out; 850a84fab3cSChristian Lamparter } 851a84fab3cSChristian Lamparter 852a84fab3cSChristian Lamparter err = carl9170_echo_test(ar, 0x4a110123); 853a84fab3cSChristian Lamparter if (err) 854a84fab3cSChristian Lamparter goto err_out; 855a84fab3cSChristian Lamparter 85697e2c402SChristian Lamparter /* now, start the command response counter */ 857a84fab3cSChristian Lamparter ar->cmd_seq = -1; 858a84fab3cSChristian Lamparter 859a84fab3cSChristian Lamparter return 0; 860a84fab3cSChristian Lamparter 861a84fab3cSChristian Lamparter err_out: 862a84fab3cSChristian Lamparter dev_err(&ar->udev->dev, "firmware upload failed (%d).\n", err); 863a84fab3cSChristian Lamparter return err; 864a84fab3cSChristian Lamparter } 865a84fab3cSChristian Lamparter 866a84fab3cSChristian Lamparter int carl9170_usb_restart(struct ar9170 *ar) 867a84fab3cSChristian Lamparter { 868a84fab3cSChristian Lamparter int err = 0; 869a84fab3cSChristian Lamparter 870a84fab3cSChristian Lamparter if (ar->intf->condition != USB_INTERFACE_BOUND) 871a84fab3cSChristian Lamparter return 0; 872a84fab3cSChristian Lamparter 87397e2c402SChristian Lamparter /* 87497e2c402SChristian Lamparter * Disable the command response sequence counter check. 87597e2c402SChristian Lamparter * We already know that the device/firmware is in a bad state. 87697e2c402SChristian Lamparter * So, no extra points are awarded to anyone who reminds the 87797e2c402SChristian Lamparter * driver about that. 87897e2c402SChristian Lamparter */ 879a84fab3cSChristian Lamparter ar->cmd_seq = -2; 880a84fab3cSChristian Lamparter 881a84fab3cSChristian Lamparter err = carl9170_reboot(ar); 882a84fab3cSChristian Lamparter 883a84fab3cSChristian Lamparter carl9170_usb_stop(ar); 884a84fab3cSChristian Lamparter 885a84fab3cSChristian Lamparter if (err) 886a84fab3cSChristian Lamparter goto err_out; 887a84fab3cSChristian Lamparter 888a84fab3cSChristian Lamparter tasklet_schedule(&ar->usb_tasklet); 889a84fab3cSChristian Lamparter 890a84fab3cSChristian Lamparter /* The reboot procedure can take quite a while to complete. */ 891a84fab3cSChristian Lamparter msleep(1100); 892a84fab3cSChristian Lamparter 893a84fab3cSChristian Lamparter err = carl9170_usb_open(ar); 894a84fab3cSChristian Lamparter if (err) 895a84fab3cSChristian Lamparter goto err_out; 896a84fab3cSChristian Lamparter 897a84fab3cSChristian Lamparter err = carl9170_usb_load_firmware(ar); 898a84fab3cSChristian Lamparter if (err) 899a84fab3cSChristian Lamparter goto err_out; 900a84fab3cSChristian Lamparter 901a84fab3cSChristian Lamparter return 0; 902a84fab3cSChristian Lamparter 903a84fab3cSChristian Lamparter err_out: 904a84fab3cSChristian Lamparter carl9170_usb_cancel_urbs(ar); 905a84fab3cSChristian Lamparter return err; 906a84fab3cSChristian Lamparter } 907a84fab3cSChristian Lamparter 908a84fab3cSChristian Lamparter void carl9170_usb_reset(struct ar9170 *ar) 909a84fab3cSChristian Lamparter { 910a84fab3cSChristian Lamparter /* 911a84fab3cSChristian Lamparter * This is the last resort to get the device going again 912a84fab3cSChristian Lamparter * without any *user replugging action*. 913a84fab3cSChristian Lamparter * 914a84fab3cSChristian Lamparter * But there is a catch: usb_reset really is like a physical 915a84fab3cSChristian Lamparter * *reconnect*. The mac80211 state will be lost in the process. 916a84fab3cSChristian Lamparter * Therefore a userspace application, which is monitoring 917a84fab3cSChristian Lamparter * the link must step in. 918a84fab3cSChristian Lamparter */ 919a84fab3cSChristian Lamparter carl9170_usb_cancel_urbs(ar); 920a84fab3cSChristian Lamparter 921a84fab3cSChristian Lamparter carl9170_usb_stop(ar); 922a84fab3cSChristian Lamparter 923a84fab3cSChristian Lamparter usb_queue_reset_device(ar->intf); 924a84fab3cSChristian Lamparter } 925a84fab3cSChristian Lamparter 926a84fab3cSChristian Lamparter static int carl9170_usb_init_device(struct ar9170 *ar) 927a84fab3cSChristian Lamparter { 928a84fab3cSChristian Lamparter int err; 929a84fab3cSChristian Lamparter 93097e2c402SChristian Lamparter /* 93197e2c402SChristian Lamparter * The carl9170 firmware let's the driver know when it's 93297e2c402SChristian Lamparter * ready for action. But we have to be prepared to gracefully 93397e2c402SChristian Lamparter * handle all spurious [flushed] messages after each (re-)boot. 93497e2c402SChristian Lamparter * Thus the command response counter remains disabled until it 93597e2c402SChristian Lamparter * can be safely synchronized. 93697e2c402SChristian Lamparter */ 93797e2c402SChristian Lamparter ar->cmd_seq = -2; 93897e2c402SChristian Lamparter 939a84fab3cSChristian Lamparter err = carl9170_usb_send_rx_irq_urb(ar); 940a84fab3cSChristian Lamparter if (err) 941a84fab3cSChristian Lamparter goto err_out; 942a84fab3cSChristian Lamparter 943a84fab3cSChristian Lamparter err = carl9170_usb_init_rx_bulk_urbs(ar); 944a84fab3cSChristian Lamparter if (err) 945a84fab3cSChristian Lamparter goto err_unrx; 946a84fab3cSChristian Lamparter 94797e2c402SChristian Lamparter err = carl9170_usb_open(ar); 94897e2c402SChristian Lamparter if (err) 94997e2c402SChristian Lamparter goto err_unrx; 95097e2c402SChristian Lamparter 951a84fab3cSChristian Lamparter mutex_lock(&ar->mutex); 952a84fab3cSChristian Lamparter err = carl9170_usb_load_firmware(ar); 953a84fab3cSChristian Lamparter mutex_unlock(&ar->mutex); 954a84fab3cSChristian Lamparter if (err) 95597e2c402SChristian Lamparter goto err_stop; 956a84fab3cSChristian Lamparter 957a84fab3cSChristian Lamparter return 0; 958a84fab3cSChristian Lamparter 95997e2c402SChristian Lamparter err_stop: 96097e2c402SChristian Lamparter carl9170_usb_stop(ar); 96197e2c402SChristian Lamparter 962a84fab3cSChristian Lamparter err_unrx: 963a84fab3cSChristian Lamparter carl9170_usb_cancel_urbs(ar); 964a84fab3cSChristian Lamparter 965a84fab3cSChristian Lamparter err_out: 966a84fab3cSChristian Lamparter return err; 967a84fab3cSChristian Lamparter } 968a84fab3cSChristian Lamparter 969a84fab3cSChristian Lamparter static void carl9170_usb_firmware_failed(struct ar9170 *ar) 970a84fab3cSChristian Lamparter { 971feb09b29SChristian Lamparter /* Store a copies of the usb_interface and usb_device pointer locally. 972feb09b29SChristian Lamparter * This is because release_driver initiates carl9170_usb_disconnect, 973feb09b29SChristian Lamparter * which in turn frees our driver context (ar). 974a84fab3cSChristian Lamparter */ 975feb09b29SChristian Lamparter struct usb_interface *intf = ar->intf; 976feb09b29SChristian Lamparter struct usb_device *udev = ar->udev; 977a84fab3cSChristian Lamparter 978a84fab3cSChristian Lamparter complete(&ar->fw_load_wait); 979feb09b29SChristian Lamparter /* at this point 'ar' could be already freed. Don't use it anymore */ 980feb09b29SChristian Lamparter ar = NULL; 981a84fab3cSChristian Lamparter 982a84fab3cSChristian Lamparter /* unbind anything failed */ 983feb09b29SChristian Lamparter usb_lock_device(udev); 984feb09b29SChristian Lamparter usb_driver_release_interface(&carl9170_driver, intf); 985feb09b29SChristian Lamparter usb_unlock_device(udev); 986a84fab3cSChristian Lamparter 987feb09b29SChristian Lamparter usb_put_intf(intf); 988a84fab3cSChristian Lamparter } 989a84fab3cSChristian Lamparter 990a84fab3cSChristian Lamparter static void carl9170_usb_firmware_finish(struct ar9170 *ar) 991a84fab3cSChristian Lamparter { 992feb09b29SChristian Lamparter struct usb_interface *intf = ar->intf; 993a84fab3cSChristian Lamparter int err; 994a84fab3cSChristian Lamparter 995a84fab3cSChristian Lamparter err = carl9170_parse_firmware(ar); 996a84fab3cSChristian Lamparter if (err) 997a84fab3cSChristian Lamparter goto err_freefw; 998a84fab3cSChristian Lamparter 999a84fab3cSChristian Lamparter err = carl9170_usb_init_device(ar); 1000a84fab3cSChristian Lamparter if (err) 1001a84fab3cSChristian Lamparter goto err_freefw; 1002a84fab3cSChristian Lamparter 1003a84fab3cSChristian Lamparter err = carl9170_register(ar); 1004a84fab3cSChristian Lamparter 1005a84fab3cSChristian Lamparter carl9170_usb_stop(ar); 1006a84fab3cSChristian Lamparter if (err) 1007a84fab3cSChristian Lamparter goto err_unrx; 1008a84fab3cSChristian Lamparter 1009a84fab3cSChristian Lamparter complete(&ar->fw_load_wait); 1010feb09b29SChristian Lamparter usb_put_intf(intf); 1011a84fab3cSChristian Lamparter return; 1012a84fab3cSChristian Lamparter 1013a84fab3cSChristian Lamparter err_unrx: 1014a84fab3cSChristian Lamparter carl9170_usb_cancel_urbs(ar); 1015a84fab3cSChristian Lamparter 1016a84fab3cSChristian Lamparter err_freefw: 1017a84fab3cSChristian Lamparter carl9170_release_firmware(ar); 1018a84fab3cSChristian Lamparter carl9170_usb_firmware_failed(ar); 1019a84fab3cSChristian Lamparter } 1020a84fab3cSChristian Lamparter 1021a84fab3cSChristian Lamparter static void carl9170_usb_firmware_step2(const struct firmware *fw, 1022a84fab3cSChristian Lamparter void *context) 1023a84fab3cSChristian Lamparter { 1024a84fab3cSChristian Lamparter struct ar9170 *ar = context; 1025a84fab3cSChristian Lamparter 1026a84fab3cSChristian Lamparter if (fw) { 1027a84fab3cSChristian Lamparter ar->fw.fw = fw; 1028a84fab3cSChristian Lamparter carl9170_usb_firmware_finish(ar); 1029a84fab3cSChristian Lamparter return; 1030a84fab3cSChristian Lamparter } 1031a84fab3cSChristian Lamparter 1032a84fab3cSChristian Lamparter dev_err(&ar->udev->dev, "firmware not found.\n"); 1033a84fab3cSChristian Lamparter carl9170_usb_firmware_failed(ar); 1034a84fab3cSChristian Lamparter } 1035a84fab3cSChristian Lamparter 1036a84fab3cSChristian Lamparter static int carl9170_usb_probe(struct usb_interface *intf, 1037a84fab3cSChristian Lamparter const struct usb_device_id *id) 1038a84fab3cSChristian Lamparter { 1039671796ddSRonald Wahl struct usb_endpoint_descriptor *ep; 1040a84fab3cSChristian Lamparter struct ar9170 *ar; 1041a84fab3cSChristian Lamparter struct usb_device *udev; 1042671796ddSRonald Wahl int i, err; 1043a84fab3cSChristian Lamparter 1044a84fab3cSChristian Lamparter err = usb_reset_device(interface_to_usbdev(intf)); 1045a84fab3cSChristian Lamparter if (err) 1046a84fab3cSChristian Lamparter return err; 1047a84fab3cSChristian Lamparter 1048a84fab3cSChristian Lamparter ar = carl9170_alloc(sizeof(*ar)); 1049a84fab3cSChristian Lamparter if (IS_ERR(ar)) 1050a84fab3cSChristian Lamparter return PTR_ERR(ar); 1051a84fab3cSChristian Lamparter 1052a84fab3cSChristian Lamparter udev = interface_to_usbdev(intf); 1053a84fab3cSChristian Lamparter ar->udev = udev; 1054a84fab3cSChristian Lamparter ar->intf = intf; 1055a84fab3cSChristian Lamparter ar->features = id->driver_info; 1056a84fab3cSChristian Lamparter 1057671796ddSRonald Wahl /* We need to remember the type of endpoint 4 because it differs 1058671796ddSRonald Wahl * between high- and full-speed configuration. The high-speed 1059671796ddSRonald Wahl * configuration specifies it as interrupt and the full-speed 1060671796ddSRonald Wahl * configuration as bulk endpoint. This information is required 1061671796ddSRonald Wahl * later when sending urbs to that endpoint. 1062671796ddSRonald Wahl */ 1063671796ddSRonald Wahl for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; ++i) { 1064671796ddSRonald Wahl ep = &intf->cur_altsetting->endpoint[i].desc; 1065671796ddSRonald Wahl 1066671796ddSRonald Wahl if (usb_endpoint_num(ep) == AR9170_USB_EP_CMD && 1067671796ddSRonald Wahl usb_endpoint_dir_out(ep) && 1068671796ddSRonald Wahl usb_endpoint_type(ep) == USB_ENDPOINT_XFER_BULK) 1069671796ddSRonald Wahl ar->usb_ep_cmd_is_bulk = true; 1070671796ddSRonald Wahl } 1071671796ddSRonald Wahl 1072a84fab3cSChristian Lamparter usb_set_intfdata(intf, ar); 1073a84fab3cSChristian Lamparter SET_IEEE80211_DEV(ar->hw, &intf->dev); 1074a84fab3cSChristian Lamparter 1075a84fab3cSChristian Lamparter init_usb_anchor(&ar->rx_anch); 1076a84fab3cSChristian Lamparter init_usb_anchor(&ar->rx_pool); 1077a84fab3cSChristian Lamparter init_usb_anchor(&ar->rx_work); 1078a84fab3cSChristian Lamparter init_usb_anchor(&ar->tx_wait); 1079a84fab3cSChristian Lamparter init_usb_anchor(&ar->tx_anch); 1080a84fab3cSChristian Lamparter init_usb_anchor(&ar->tx_cmd); 1081a84fab3cSChristian Lamparter init_usb_anchor(&ar->tx_err); 1082a84fab3cSChristian Lamparter init_completion(&ar->cmd_wait); 1083a84fab3cSChristian Lamparter init_completion(&ar->fw_boot_wait); 1084a84fab3cSChristian Lamparter init_completion(&ar->fw_load_wait); 1085*de7dbc2dSAllen Pais tasklet_setup(&ar->usb_tasklet, carl9170_usb_tasklet); 1086a84fab3cSChristian Lamparter 1087a84fab3cSChristian Lamparter atomic_set(&ar->tx_cmd_urbs, 0); 1088a84fab3cSChristian Lamparter atomic_set(&ar->tx_anch_urbs, 0); 1089a84fab3cSChristian Lamparter atomic_set(&ar->rx_work_urbs, 0); 1090a84fab3cSChristian Lamparter atomic_set(&ar->rx_anch_urbs, 0); 1091a84fab3cSChristian Lamparter atomic_set(&ar->rx_pool_urbs, 0); 1092a84fab3cSChristian Lamparter 1093feb09b29SChristian Lamparter usb_get_intf(intf); 1094a84fab3cSChristian Lamparter 1095a84fab3cSChristian Lamparter carl9170_set_state(ar, CARL9170_STOPPED); 1096a84fab3cSChristian Lamparter 10975c2b6078SAlexey Khoroshilov err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, 1098a84fab3cSChristian Lamparter &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2); 10995c2b6078SAlexey Khoroshilov if (err) { 1100feb09b29SChristian Lamparter usb_put_intf(intf); 11015c2b6078SAlexey Khoroshilov carl9170_free(ar); 11025c2b6078SAlexey Khoroshilov } 11035c2b6078SAlexey Khoroshilov return err; 1104a84fab3cSChristian Lamparter } 1105a84fab3cSChristian Lamparter 1106a84fab3cSChristian Lamparter static void carl9170_usb_disconnect(struct usb_interface *intf) 1107a84fab3cSChristian Lamparter { 1108a84fab3cSChristian Lamparter struct ar9170 *ar = usb_get_intfdata(intf); 1109a84fab3cSChristian Lamparter 1110a84fab3cSChristian Lamparter if (WARN_ON(!ar)) 1111a84fab3cSChristian Lamparter return; 1112a84fab3cSChristian Lamparter 1113a84fab3cSChristian Lamparter wait_for_completion(&ar->fw_load_wait); 1114a84fab3cSChristian Lamparter 1115a84fab3cSChristian Lamparter if (IS_INITIALIZED(ar)) { 1116a84fab3cSChristian Lamparter carl9170_reboot(ar); 1117a84fab3cSChristian Lamparter carl9170_usb_stop(ar); 1118a84fab3cSChristian Lamparter } 1119a84fab3cSChristian Lamparter 1120a84fab3cSChristian Lamparter carl9170_usb_cancel_urbs(ar); 1121a84fab3cSChristian Lamparter carl9170_unregister(ar); 1122a84fab3cSChristian Lamparter 1123a84fab3cSChristian Lamparter usb_set_intfdata(intf, NULL); 1124a84fab3cSChristian Lamparter 1125a84fab3cSChristian Lamparter carl9170_release_firmware(ar); 1126a84fab3cSChristian Lamparter carl9170_free(ar); 1127a84fab3cSChristian Lamparter } 1128a84fab3cSChristian Lamparter 1129a84fab3cSChristian Lamparter #ifdef CONFIG_PM 1130a84fab3cSChristian Lamparter static int carl9170_usb_suspend(struct usb_interface *intf, 1131a84fab3cSChristian Lamparter pm_message_t message) 1132a84fab3cSChristian Lamparter { 1133a84fab3cSChristian Lamparter struct ar9170 *ar = usb_get_intfdata(intf); 1134a84fab3cSChristian Lamparter 1135a84fab3cSChristian Lamparter if (!ar) 1136a84fab3cSChristian Lamparter return -ENODEV; 1137a84fab3cSChristian Lamparter 1138a84fab3cSChristian Lamparter carl9170_usb_cancel_urbs(ar); 1139a84fab3cSChristian Lamparter 1140a84fab3cSChristian Lamparter return 0; 1141a84fab3cSChristian Lamparter } 1142a84fab3cSChristian Lamparter 1143a84fab3cSChristian Lamparter static int carl9170_usb_resume(struct usb_interface *intf) 1144a84fab3cSChristian Lamparter { 1145a84fab3cSChristian Lamparter struct ar9170 *ar = usb_get_intfdata(intf); 1146a84fab3cSChristian Lamparter int err; 1147a84fab3cSChristian Lamparter 1148a84fab3cSChristian Lamparter if (!ar) 1149a84fab3cSChristian Lamparter return -ENODEV; 1150a84fab3cSChristian Lamparter 1151a84fab3cSChristian Lamparter usb_unpoison_anchored_urbs(&ar->rx_anch); 115297e2c402SChristian Lamparter carl9170_set_state(ar, CARL9170_STOPPED); 115397e2c402SChristian Lamparter 115497e2c402SChristian Lamparter /* 115597e2c402SChristian Lamparter * The USB documentation demands that [for suspend] all traffic 115697e2c402SChristian Lamparter * to and from the device has to stop. This would be fine, but 115797e2c402SChristian Lamparter * there's a catch: the device[usb phy] does not come back. 115897e2c402SChristian Lamparter * 115997e2c402SChristian Lamparter * Upon resume the firmware will "kill" itself and the 116097e2c402SChristian Lamparter * boot-code sorts out the magic voodoo. 116197e2c402SChristian Lamparter * Not very nice, but there's not much what could go wrong. 116297e2c402SChristian Lamparter */ 116397e2c402SChristian Lamparter msleep(1100); 1164a84fab3cSChristian Lamparter 1165a84fab3cSChristian Lamparter err = carl9170_usb_init_device(ar); 1166a84fab3cSChristian Lamparter if (err) 1167a84fab3cSChristian Lamparter goto err_unrx; 1168a84fab3cSChristian Lamparter 1169a84fab3cSChristian Lamparter return 0; 1170a84fab3cSChristian Lamparter 1171a84fab3cSChristian Lamparter err_unrx: 1172a84fab3cSChristian Lamparter carl9170_usb_cancel_urbs(ar); 1173a84fab3cSChristian Lamparter 1174a84fab3cSChristian Lamparter return err; 1175a84fab3cSChristian Lamparter } 1176a84fab3cSChristian Lamparter #endif /* CONFIG_PM */ 1177a84fab3cSChristian Lamparter 1178a84fab3cSChristian Lamparter static struct usb_driver carl9170_driver = { 1179a84fab3cSChristian Lamparter .name = KBUILD_MODNAME, 1180a84fab3cSChristian Lamparter .probe = carl9170_usb_probe, 1181a84fab3cSChristian Lamparter .disconnect = carl9170_usb_disconnect, 1182a84fab3cSChristian Lamparter .id_table = carl9170_usb_ids, 1183a84fab3cSChristian Lamparter .soft_unbind = 1, 1184a84fab3cSChristian Lamparter #ifdef CONFIG_PM 1185a84fab3cSChristian Lamparter .suspend = carl9170_usb_suspend, 1186a84fab3cSChristian Lamparter .resume = carl9170_usb_resume, 118797e2c402SChristian Lamparter .reset_resume = carl9170_usb_resume, 1188a84fab3cSChristian Lamparter #endif /* CONFIG_PM */ 1189e1f12eb6SSarah Sharp .disable_hub_initiated_lpm = 1, 1190a84fab3cSChristian Lamparter }; 1191a84fab3cSChristian Lamparter 1192d632eb1bSGreg Kroah-Hartman module_usb_driver(carl9170_driver); 1193