162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> 362306a36Sopenharmony_ci * Copyright (c) 2006 Sam Leffler, Errno Consulting 462306a36Sopenharmony_ci * Copyright (c) 2007 Christoph Hellwig <hch@lst.de> 562306a36Sopenharmony_ci * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> 662306a36Sopenharmony_ci * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 962306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 1062306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1362306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1462306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1562306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1662306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1762306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1862306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1962306a36Sopenharmony_ci */ 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define AR5523_FLAG_PRE_FIRMWARE (1 << 0) 2262306a36Sopenharmony_ci#define AR5523_FLAG_ABG (1 << 1) 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define AR5523_FIRMWARE_FILE "ar5523.bin" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define AR5523_CMD_TX_PIPE 0x01 2762306a36Sopenharmony_ci#define AR5523_DATA_TX_PIPE 0x02 2862306a36Sopenharmony_ci#define AR5523_CMD_RX_PIPE 0x81 2962306a36Sopenharmony_ci#define AR5523_DATA_RX_PIPE 0x82 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define ar5523_cmd_tx_pipe(dev) \ 3262306a36Sopenharmony_ci usb_sndbulkpipe((dev), AR5523_CMD_TX_PIPE) 3362306a36Sopenharmony_ci#define ar5523_data_tx_pipe(dev) \ 3462306a36Sopenharmony_ci usb_sndbulkpipe((dev), AR5523_DATA_TX_PIPE) 3562306a36Sopenharmony_ci#define ar5523_cmd_rx_pipe(dev) \ 3662306a36Sopenharmony_ci usb_rcvbulkpipe((dev), AR5523_CMD_RX_PIPE) 3762306a36Sopenharmony_ci#define ar5523_data_rx_pipe(dev) \ 3862306a36Sopenharmony_ci usb_rcvbulkpipe((dev), AR5523_DATA_RX_PIPE) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define AR5523_DATA_TIMEOUT 10000 4162306a36Sopenharmony_ci#define AR5523_CMD_TIMEOUT 1000 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define AR5523_TX_DATA_COUNT 8 4462306a36Sopenharmony_ci#define AR5523_TX_DATA_RESTART_COUNT 2 4562306a36Sopenharmony_ci#define AR5523_RX_DATA_COUNT 16 4662306a36Sopenharmony_ci#define AR5523_RX_DATA_REFILL_COUNT 8 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define AR5523_CMD_ID 1 4962306a36Sopenharmony_ci#define AR5523_DATA_ID 2 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define AR5523_TX_WD_TIMEOUT (HZ * 2) 5262306a36Sopenharmony_ci#define AR5523_FLUSH_TIMEOUT (HZ * 3) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cienum AR5523_flags { 5562306a36Sopenharmony_ci AR5523_HW_UP, 5662306a36Sopenharmony_ci AR5523_USB_DISCONNECTED, 5762306a36Sopenharmony_ci AR5523_CONNECTED 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistruct ar5523_tx_cmd { 6162306a36Sopenharmony_ci struct ar5523 *ar; 6262306a36Sopenharmony_ci struct urb *urb_tx; 6362306a36Sopenharmony_ci void *buf_tx; 6462306a36Sopenharmony_ci void *odata; 6562306a36Sopenharmony_ci int olen; 6662306a36Sopenharmony_ci int flags; 6762306a36Sopenharmony_ci int res; 6862306a36Sopenharmony_ci struct completion done; 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* This struct is placed in tx_info->driver_data. It must not be larger 7262306a36Sopenharmony_ci * than IEEE80211_TX_INFO_DRIVER_DATA_SIZE. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_cistruct ar5523_tx_data { 7562306a36Sopenharmony_ci struct list_head list; 7662306a36Sopenharmony_ci struct ar5523 *ar; 7762306a36Sopenharmony_ci struct urb *urb; 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistruct ar5523_rx_data { 8162306a36Sopenharmony_ci struct list_head list; 8262306a36Sopenharmony_ci struct ar5523 *ar; 8362306a36Sopenharmony_ci struct urb *urb; 8462306a36Sopenharmony_ci struct sk_buff *skb; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistruct ar5523 { 8862306a36Sopenharmony_ci struct usb_device *dev; 8962306a36Sopenharmony_ci struct ieee80211_hw *hw; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci unsigned long flags; 9262306a36Sopenharmony_ci struct mutex mutex; 9362306a36Sopenharmony_ci struct workqueue_struct *wq; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci struct ar5523_tx_cmd tx_cmd; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci struct delayed_work stat_work; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci struct timer_list tx_wd_timer; 10062306a36Sopenharmony_ci struct work_struct tx_wd_work; 10162306a36Sopenharmony_ci struct work_struct tx_work; 10262306a36Sopenharmony_ci struct list_head tx_queue_pending; 10362306a36Sopenharmony_ci struct list_head tx_queue_submitted; 10462306a36Sopenharmony_ci spinlock_t tx_data_list_lock; 10562306a36Sopenharmony_ci wait_queue_head_t tx_flush_waitq; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* Queued + Submitted TX frames */ 10862306a36Sopenharmony_ci atomic_t tx_nr_total; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* Submitted TX frames */ 11162306a36Sopenharmony_ci atomic_t tx_nr_pending; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci void *rx_cmd_buf; 11462306a36Sopenharmony_ci struct urb *rx_cmd_urb; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci struct ar5523_rx_data rx_data[AR5523_RX_DATA_COUNT]; 11762306a36Sopenharmony_ci spinlock_t rx_data_list_lock; 11862306a36Sopenharmony_ci struct list_head rx_data_free; 11962306a36Sopenharmony_ci struct list_head rx_data_used; 12062306a36Sopenharmony_ci atomic_t rx_data_free_cnt; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci struct work_struct rx_refill_work; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci unsigned int rxbufsz; 12562306a36Sopenharmony_ci u8 serial[16]; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci struct ieee80211_channel channels[14]; 12862306a36Sopenharmony_ci struct ieee80211_rate rates[12]; 12962306a36Sopenharmony_ci struct ieee80211_supported_band band; 13062306a36Sopenharmony_ci struct ieee80211_vif *vif; 13162306a36Sopenharmony_ci}; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* flags for sending firmware commands */ 13462306a36Sopenharmony_ci#define AR5523_CMD_FLAG_READ (1 << 1) 13562306a36Sopenharmony_ci#define AR5523_CMD_FLAG_MAGIC (1 << 2) 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#define ar5523_dbg(ar, format, arg...) \ 13862306a36Sopenharmony_ci dev_dbg(&(ar)->dev->dev, format, ## arg) 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/* On USB hot-unplug there can be a lot of URBs in flight and they'll all 14162306a36Sopenharmony_ci * fail. Instead of dealing with them in every possible place just surpress 14262306a36Sopenharmony_ci * any messages on USB disconnect. 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ci#define ar5523_err(ar, format, arg...) \ 14562306a36Sopenharmony_cido { \ 14662306a36Sopenharmony_ci if (!test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) { \ 14762306a36Sopenharmony_ci dev_err(&(ar)->dev->dev, format, ## arg); \ 14862306a36Sopenharmony_ci } \ 14962306a36Sopenharmony_ci} while (0) 15062306a36Sopenharmony_ci#define ar5523_info(ar, format, arg...) \ 15162306a36Sopenharmony_ci dev_info(&(ar)->dev->dev, format, ## arg) 152