18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> 38c2ecf20Sopenharmony_ci * Copyright (c) 2006 Sam Leffler, Errno Consulting 48c2ecf20Sopenharmony_ci * Copyright (c) 2007 Christoph Hellwig <hch@lst.de> 58c2ecf20Sopenharmony_ci * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> 68c2ecf20Sopenharmony_ci * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 98c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 108c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 138c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 148c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 158c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 168c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 178c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 188c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define AR5523_FLAG_PRE_FIRMWARE (1 << 0) 228c2ecf20Sopenharmony_ci#define AR5523_FLAG_ABG (1 << 1) 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define AR5523_FIRMWARE_FILE "ar5523.bin" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define AR5523_CMD_TX_PIPE 0x01 278c2ecf20Sopenharmony_ci#define AR5523_DATA_TX_PIPE 0x02 288c2ecf20Sopenharmony_ci#define AR5523_CMD_RX_PIPE 0x81 298c2ecf20Sopenharmony_ci#define AR5523_DATA_RX_PIPE 0x82 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define ar5523_cmd_tx_pipe(dev) \ 328c2ecf20Sopenharmony_ci usb_sndbulkpipe((dev), AR5523_CMD_TX_PIPE) 338c2ecf20Sopenharmony_ci#define ar5523_data_tx_pipe(dev) \ 348c2ecf20Sopenharmony_ci usb_sndbulkpipe((dev), AR5523_DATA_TX_PIPE) 358c2ecf20Sopenharmony_ci#define ar5523_cmd_rx_pipe(dev) \ 368c2ecf20Sopenharmony_ci usb_rcvbulkpipe((dev), AR5523_CMD_RX_PIPE) 378c2ecf20Sopenharmony_ci#define ar5523_data_rx_pipe(dev) \ 388c2ecf20Sopenharmony_ci usb_rcvbulkpipe((dev), AR5523_DATA_RX_PIPE) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define AR5523_DATA_TIMEOUT 10000 418c2ecf20Sopenharmony_ci#define AR5523_CMD_TIMEOUT 1000 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define AR5523_TX_DATA_COUNT 8 448c2ecf20Sopenharmony_ci#define AR5523_TX_DATA_RESTART_COUNT 2 458c2ecf20Sopenharmony_ci#define AR5523_RX_DATA_COUNT 16 468c2ecf20Sopenharmony_ci#define AR5523_RX_DATA_REFILL_COUNT 8 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define AR5523_CMD_ID 1 498c2ecf20Sopenharmony_ci#define AR5523_DATA_ID 2 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define AR5523_TX_WD_TIMEOUT (HZ * 2) 528c2ecf20Sopenharmony_ci#define AR5523_FLUSH_TIMEOUT (HZ * 3) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cienum AR5523_flags { 558c2ecf20Sopenharmony_ci AR5523_HW_UP, 568c2ecf20Sopenharmony_ci AR5523_USB_DISCONNECTED, 578c2ecf20Sopenharmony_ci AR5523_CONNECTED 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistruct ar5523_tx_cmd { 618c2ecf20Sopenharmony_ci struct ar5523 *ar; 628c2ecf20Sopenharmony_ci struct urb *urb_tx; 638c2ecf20Sopenharmony_ci void *buf_tx; 648c2ecf20Sopenharmony_ci void *odata; 658c2ecf20Sopenharmony_ci int olen; 668c2ecf20Sopenharmony_ci int flags; 678c2ecf20Sopenharmony_ci int res; 688c2ecf20Sopenharmony_ci struct completion done; 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* This struct is placed in tx_info->driver_data. It must not be larger 728c2ecf20Sopenharmony_ci * than IEEE80211_TX_INFO_DRIVER_DATA_SIZE. 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_cistruct ar5523_tx_data { 758c2ecf20Sopenharmony_ci struct list_head list; 768c2ecf20Sopenharmony_ci struct ar5523 *ar; 778c2ecf20Sopenharmony_ci struct urb *urb; 788c2ecf20Sopenharmony_ci}; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistruct ar5523_rx_data { 818c2ecf20Sopenharmony_ci struct list_head list; 828c2ecf20Sopenharmony_ci struct ar5523 *ar; 838c2ecf20Sopenharmony_ci struct urb *urb; 848c2ecf20Sopenharmony_ci struct sk_buff *skb; 858c2ecf20Sopenharmony_ci}; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistruct ar5523 { 888c2ecf20Sopenharmony_ci struct usb_device *dev; 898c2ecf20Sopenharmony_ci struct ieee80211_hw *hw; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci unsigned long flags; 928c2ecf20Sopenharmony_ci struct mutex mutex; 938c2ecf20Sopenharmony_ci struct workqueue_struct *wq; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci struct ar5523_tx_cmd tx_cmd; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci struct delayed_work stat_work; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci struct timer_list tx_wd_timer; 1008c2ecf20Sopenharmony_ci struct work_struct tx_wd_work; 1018c2ecf20Sopenharmony_ci struct work_struct tx_work; 1028c2ecf20Sopenharmony_ci struct list_head tx_queue_pending; 1038c2ecf20Sopenharmony_ci struct list_head tx_queue_submitted; 1048c2ecf20Sopenharmony_ci spinlock_t tx_data_list_lock; 1058c2ecf20Sopenharmony_ci wait_queue_head_t tx_flush_waitq; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* Queued + Submitted TX frames */ 1088c2ecf20Sopenharmony_ci atomic_t tx_nr_total; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* Submitted TX frames */ 1118c2ecf20Sopenharmony_ci atomic_t tx_nr_pending; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci void *rx_cmd_buf; 1148c2ecf20Sopenharmony_ci struct urb *rx_cmd_urb; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci struct ar5523_rx_data rx_data[AR5523_RX_DATA_COUNT]; 1178c2ecf20Sopenharmony_ci spinlock_t rx_data_list_lock; 1188c2ecf20Sopenharmony_ci struct list_head rx_data_free; 1198c2ecf20Sopenharmony_ci struct list_head rx_data_used; 1208c2ecf20Sopenharmony_ci atomic_t rx_data_free_cnt; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci struct work_struct rx_refill_work; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci unsigned int rxbufsz; 1258c2ecf20Sopenharmony_ci u8 serial[16]; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci struct ieee80211_channel channels[14]; 1288c2ecf20Sopenharmony_ci struct ieee80211_rate rates[12]; 1298c2ecf20Sopenharmony_ci struct ieee80211_supported_band band; 1308c2ecf20Sopenharmony_ci struct ieee80211_vif *vif; 1318c2ecf20Sopenharmony_ci}; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* flags for sending firmware commands */ 1348c2ecf20Sopenharmony_ci#define AR5523_CMD_FLAG_READ (1 << 1) 1358c2ecf20Sopenharmony_ci#define AR5523_CMD_FLAG_MAGIC (1 << 2) 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci#define ar5523_dbg(ar, format, arg...) \ 1388c2ecf20Sopenharmony_ci dev_dbg(&(ar)->dev->dev, format, ## arg) 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/* On USB hot-unplug there can be a lot of URBs in flight and they'll all 1418c2ecf20Sopenharmony_ci * fail. Instead of dealing with them in every possible place just surpress 1428c2ecf20Sopenharmony_ci * any messages on USB disconnect. 1438c2ecf20Sopenharmony_ci */ 1448c2ecf20Sopenharmony_ci#define ar5523_err(ar, format, arg...) \ 1458c2ecf20Sopenharmony_cido { \ 1468c2ecf20Sopenharmony_ci if (!test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) { \ 1478c2ecf20Sopenharmony_ci dev_err(&(ar)->dev->dev, format, ## arg); \ 1488c2ecf20Sopenharmony_ci } \ 1498c2ecf20Sopenharmony_ci} while (0) 1508c2ecf20Sopenharmony_ci#define ar5523_info(ar, format, arg...) \ 1518c2ecf20Sopenharmony_ci dev_info(&(ar)->dev->dev, format, ## arg) 152