1b7d572e1SPontus Fuchs /* 2b7d572e1SPontus Fuchs * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> 3b7d572e1SPontus Fuchs * Copyright (c) 2006 Sam Leffler, Errno Consulting 4b7d572e1SPontus Fuchs * Copyright (c) 2007 Christoph Hellwig <hch@lst.de> 5b7d572e1SPontus Fuchs * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> 6b7d572e1SPontus Fuchs * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com> 7b7d572e1SPontus Fuchs * 8b7d572e1SPontus Fuchs * Permission to use, copy, modify, and/or distribute this software for any 9b7d572e1SPontus Fuchs * purpose with or without fee is hereby granted, provided that the above 10b7d572e1SPontus Fuchs * copyright notice and this permission notice appear in all copies. 11b7d572e1SPontus Fuchs * 12b7d572e1SPontus Fuchs * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13b7d572e1SPontus Fuchs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14b7d572e1SPontus Fuchs * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15b7d572e1SPontus Fuchs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16b7d572e1SPontus Fuchs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17b7d572e1SPontus Fuchs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18b7d572e1SPontus Fuchs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19b7d572e1SPontus Fuchs */ 20b7d572e1SPontus Fuchs 21b7d572e1SPontus Fuchs #define AR5523_FLAG_PRE_FIRMWARE (1 << 0) 22b7d572e1SPontus Fuchs #define AR5523_FLAG_ABG (1 << 1) 23b7d572e1SPontus Fuchs 24b7d572e1SPontus Fuchs #define AR5523_FIRMWARE_FILE "ar5523.bin" 25b7d572e1SPontus Fuchs 26b7d572e1SPontus Fuchs #define AR5523_CMD_TX_PIPE 0x01 27b7d572e1SPontus Fuchs #define AR5523_DATA_TX_PIPE 0x02 28b7d572e1SPontus Fuchs #define AR5523_CMD_RX_PIPE 0x81 29b7d572e1SPontus Fuchs #define AR5523_DATA_RX_PIPE 0x82 30b7d572e1SPontus Fuchs 31b7d572e1SPontus Fuchs #define ar5523_cmd_tx_pipe(dev) \ 32b7d572e1SPontus Fuchs usb_sndbulkpipe((dev), AR5523_CMD_TX_PIPE) 33b7d572e1SPontus Fuchs #define ar5523_data_tx_pipe(dev) \ 34b7d572e1SPontus Fuchs usb_sndbulkpipe((dev), AR5523_DATA_TX_PIPE) 35b7d572e1SPontus Fuchs #define ar5523_cmd_rx_pipe(dev) \ 36b7d572e1SPontus Fuchs usb_rcvbulkpipe((dev), AR5523_CMD_RX_PIPE) 37b7d572e1SPontus Fuchs #define ar5523_data_rx_pipe(dev) \ 38b7d572e1SPontus Fuchs usb_rcvbulkpipe((dev), AR5523_DATA_RX_PIPE) 39b7d572e1SPontus Fuchs 40b7d572e1SPontus Fuchs #define AR5523_DATA_TIMEOUT 10000 41b7d572e1SPontus Fuchs #define AR5523_CMD_TIMEOUT 1000 42b7d572e1SPontus Fuchs 43b7d572e1SPontus Fuchs #define AR5523_TX_DATA_COUNT 8 44b7d572e1SPontus Fuchs #define AR5523_TX_DATA_RESTART_COUNT 2 45b7d572e1SPontus Fuchs #define AR5523_RX_DATA_COUNT 16 46b7d572e1SPontus Fuchs #define AR5523_RX_DATA_REFILL_COUNT 8 47b7d572e1SPontus Fuchs 48b7d572e1SPontus Fuchs #define AR5523_CMD_ID 1 49b7d572e1SPontus Fuchs #define AR5523_DATA_ID 2 50b7d572e1SPontus Fuchs 51b7d572e1SPontus Fuchs #define AR5523_TX_WD_TIMEOUT (HZ * 2) 52b7d572e1SPontus Fuchs #define AR5523_FLUSH_TIMEOUT (HZ * 3) 53b7d572e1SPontus Fuchs 54b7d572e1SPontus Fuchs enum AR5523_flags { 55b7d572e1SPontus Fuchs AR5523_HW_UP, 56b7d572e1SPontus Fuchs AR5523_USB_DISCONNECTED, 57b7d572e1SPontus Fuchs AR5523_CONNECTED 58b7d572e1SPontus Fuchs }; 59b7d572e1SPontus Fuchs 60b7d572e1SPontus Fuchs struct ar5523_tx_cmd { 61b7d572e1SPontus Fuchs struct ar5523 *ar; 62b7d572e1SPontus Fuchs struct urb *urb_tx; 63b7d572e1SPontus Fuchs void *buf_tx; 64b7d572e1SPontus Fuchs void *odata; 65b7d572e1SPontus Fuchs int olen; 66b7d572e1SPontus Fuchs int flags; 67b7d572e1SPontus Fuchs int res; 68b7d572e1SPontus Fuchs struct completion done; 69b7d572e1SPontus Fuchs }; 70b7d572e1SPontus Fuchs 71b7d572e1SPontus Fuchs /* This struct is placed in tx_info->driver_data. It must not be larger 72b7d572e1SPontus Fuchs * than IEEE80211_TX_INFO_DRIVER_DATA_SIZE. 73b7d572e1SPontus Fuchs */ 74b7d572e1SPontus Fuchs struct ar5523_tx_data { 75b7d572e1SPontus Fuchs struct list_head list; 76b7d572e1SPontus Fuchs struct ar5523 *ar; 77b7d572e1SPontus Fuchs struct sk_buff *skb; 78b7d572e1SPontus Fuchs struct urb *urb; 79b7d572e1SPontus Fuchs }; 80b7d572e1SPontus Fuchs 81b7d572e1SPontus Fuchs struct ar5523_rx_data { 82b7d572e1SPontus Fuchs struct list_head list; 83b7d572e1SPontus Fuchs struct ar5523 *ar; 84b7d572e1SPontus Fuchs struct urb *urb; 85b7d572e1SPontus Fuchs struct sk_buff *skb; 86b7d572e1SPontus Fuchs }; 87b7d572e1SPontus Fuchs 88b7d572e1SPontus Fuchs struct ar5523 { 89b7d572e1SPontus Fuchs struct usb_device *dev; 90b7d572e1SPontus Fuchs struct ieee80211_hw *hw; 91b7d572e1SPontus Fuchs 92b7d572e1SPontus Fuchs unsigned long flags; 93b7d572e1SPontus Fuchs struct mutex mutex; 94b7d572e1SPontus Fuchs struct workqueue_struct *wq; 95b7d572e1SPontus Fuchs 96b7d572e1SPontus Fuchs struct ar5523_tx_cmd tx_cmd; 97b7d572e1SPontus Fuchs 98b7d572e1SPontus Fuchs struct delayed_work stat_work; 99b7d572e1SPontus Fuchs 100b7d572e1SPontus Fuchs struct timer_list tx_wd_timer; 101b7d572e1SPontus Fuchs struct work_struct tx_wd_work; 102b7d572e1SPontus Fuchs struct work_struct tx_work; 103b7d572e1SPontus Fuchs struct list_head tx_queue_pending; 104b7d572e1SPontus Fuchs struct list_head tx_queue_submitted; 105b7d572e1SPontus Fuchs spinlock_t tx_data_list_lock; 106b7d572e1SPontus Fuchs wait_queue_head_t tx_flush_waitq; 107b7d572e1SPontus Fuchs 108b7d572e1SPontus Fuchs /* Queued + Submitted TX frames */ 109b7d572e1SPontus Fuchs atomic_t tx_nr_total; 110b7d572e1SPontus Fuchs 111b7d572e1SPontus Fuchs /* Submitted TX frames */ 112b7d572e1SPontus Fuchs atomic_t tx_nr_pending; 113b7d572e1SPontus Fuchs 114b7d572e1SPontus Fuchs void *rx_cmd_buf; 115b7d572e1SPontus Fuchs struct urb *rx_cmd_urb; 116b7d572e1SPontus Fuchs 117b7d572e1SPontus Fuchs struct ar5523_rx_data rx_data[AR5523_RX_DATA_COUNT]; 118b7d572e1SPontus Fuchs spinlock_t rx_data_list_lock; 119b7d572e1SPontus Fuchs struct list_head rx_data_free; 120b7d572e1SPontus Fuchs struct list_head rx_data_used; 121b7d572e1SPontus Fuchs atomic_t rx_data_free_cnt; 122b7d572e1SPontus Fuchs 123b7d572e1SPontus Fuchs struct work_struct rx_refill_work; 124b7d572e1SPontus Fuchs 12538141fcfSDan Carpenter unsigned int rxbufsz; 126b7d572e1SPontus Fuchs u8 serial[16]; 127b7d572e1SPontus Fuchs 128b7d572e1SPontus Fuchs struct ieee80211_channel channels[14]; 129b7d572e1SPontus Fuchs struct ieee80211_rate rates[12]; 130b7d572e1SPontus Fuchs struct ieee80211_supported_band band; 131b7d572e1SPontus Fuchs struct ieee80211_vif *vif; 132b7d572e1SPontus Fuchs }; 133b7d572e1SPontus Fuchs 134b7d572e1SPontus Fuchs /* flags for sending firmware commands */ 135b7d572e1SPontus Fuchs #define AR5523_CMD_FLAG_READ (1 << 1) 136b7d572e1SPontus Fuchs #define AR5523_CMD_FLAG_MAGIC (1 << 2) 137b7d572e1SPontus Fuchs 138b7d572e1SPontus Fuchs #define ar5523_dbg(ar, format, arg...) \ 139b7d572e1SPontus Fuchs dev_dbg(&(ar)->dev->dev, format, ## arg) 140b7d572e1SPontus Fuchs 141b7d572e1SPontus Fuchs /* On USB hot-unplug there can be a lot of URBs in flight and they'll all 142b7d572e1SPontus Fuchs * fail. Instead of dealing with them in every possible place just surpress 143b7d572e1SPontus Fuchs * any messages on USB disconnect. 144b7d572e1SPontus Fuchs */ 145b7d572e1SPontus Fuchs #define ar5523_err(ar, format, arg...) \ 146b7d572e1SPontus Fuchs do { \ 147b7d572e1SPontus Fuchs if (!test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) { \ 148b7d572e1SPontus Fuchs dev_err(&(ar)->dev->dev, format, ## arg); \ 149b7d572e1SPontus Fuchs } \ 150b7d572e1SPontus Fuchs } while (0) 151b7d572e1SPontus Fuchs #define ar5523_info(ar, format, arg...) \ 152b7d572e1SPontus Fuchs dev_info(&(ar)->dev->dev, format, ## arg) 153