diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00.h')
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 885 |
1 files changed, 696 insertions, 189 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 84bd6f19acb..d13f25cd70d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1,5 +1,7 @@ /* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> + Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> + Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> <http://rt2x00.serialmonkey.com> This program is free software; you can redistribute it and/or modify @@ -13,9 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the - Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + along with this program; if not, see <http://www.gnu.org/licenses/>. */ /* @@ -27,6 +27,7 @@ #define RT2X00_H #include <linux/bitops.h> +#include <linux/interrupt.h> #include <linux/skbuff.h> #include <linux/workqueue.h> #include <linux/firmware.h> @@ -34,10 +35,14 @@ #include <linux/mutex.h> #include <linux/etherdevice.h> #include <linux/input-polldev.h> +#include <linux/kfifo.h> +#include <linux/hrtimer.h> +#include <linux/average.h> #include <net/mac80211.h> #include "rt2x00debug.h" +#include "rt2x00dump.h" #include "rt2x00leds.h" #include "rt2x00reg.h" #include "rt2x00queue.h" @@ -48,49 +53,36 @@ #define DRV_VERSION "2.3.0" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" -/* - * Debug definitions. +/* Debug definitions. * Debug output has to be enabled during compile time. */ -#define DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, __args...) \ - printk(__kernlvl "%s -> %s: %s - " __msg, \ - wiphy_name((__dev)->hw->wiphy), __func__, __lvl, ##__args) - -#define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...) \ - printk(__kernlvl "%s -> %s: %s - " __msg, \ - KBUILD_MODNAME, __func__, __lvl, ##__args) - #ifdef CONFIG_RT2X00_DEBUG -#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ - DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args); -#else -#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ - do { } while (0) +#define DEBUG #endif /* CONFIG_RT2X00_DEBUG */ -/* - * Various debug levels. - * The debug levels PANIC and ERROR both indicate serious problems, - * for this reason they should never be ignored. - * The special ERROR_PROBE message is for messages that are generated - * when the rt2x00_dev is not yet initialized. - */ -#define PANIC(__dev, __msg, __args...) \ - DEBUG_PRINTK_MSG(__dev, KERN_CRIT, "Panic", __msg, ##__args) -#define ERROR(__dev, __msg, __args...) \ - DEBUG_PRINTK_MSG(__dev, KERN_ERR, "Error", __msg, ##__args) -#define ERROR_PROBE(__msg, __args...) \ - DEBUG_PRINTK_PROBE(KERN_ERR, "Error", __msg, ##__args) -#define WARNING(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_WARNING, "Warning", __msg, ##__args) -#define NOTICE(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_NOTICE, "Notice", __msg, ##__args) -#define INFO(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_INFO, "Info", __msg, ##__args) -#define DEBUG(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_DEBUG, "Debug", __msg, ##__args) -#define EEPROM(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args) +/* Utility printing macros + * rt2x00_probe_err is for messages when rt2x00_dev is uninitialized + */ +#define rt2x00_probe_err(fmt, ...) \ + printk(KERN_ERR KBUILD_MODNAME ": %s: Error - " fmt, \ + __func__, ##__VA_ARGS__) +#define rt2x00_err(dev, fmt, ...) \ + wiphy_err((dev)->hw->wiphy, "%s: Error - " fmt, \ + __func__, ##__VA_ARGS__) +#define rt2x00_warn(dev, fmt, ...) \ + wiphy_warn((dev)->hw->wiphy, "%s: Warning - " fmt, \ + __func__, ##__VA_ARGS__) +#define rt2x00_info(dev, fmt, ...) \ + wiphy_info((dev)->hw->wiphy, "%s: Info - " fmt, \ + __func__, ##__VA_ARGS__) + +/* Various debug levels */ +#define rt2x00_dbg(dev, fmt, ...) \ + wiphy_dbg((dev)->hw->wiphy, "%s: Debug - " fmt, \ + __func__, ##__VA_ARGS__) +#define rt2x00_eeprom_dbg(dev, fmt, ...) \ + wiphy_dbg((dev)->hw->wiphy, "%s: EEPROM recovery - " fmt, \ + __func__, ##__VA_ARGS__) /* * Duration calculations @@ -103,6 +95,27 @@ #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) /* + * Determine the number of L2 padding bytes required between the header and + * the payload. + */ +#define L2PAD_SIZE(__hdrlen) (-(__hdrlen) & 3) + +/* + * Determine the alignment requirement, + * to make sure the 802.11 payload is padded to a 4-byte boundrary + * we must determine the address of the payload and calculate the + * amount of bytes needed to move the data. + */ +#define ALIGN_SIZE(__skb, __header) \ + ( ((unsigned long)((__skb)->data + (__header))) & 3 ) + +/* + * Constants for extra TX headroom for alignment purposes. + */ +#define RT2X00_ALIGN_SIZE 4 /* Only whole frame needs alignment */ +#define RT2X00_L2PAD_SIZE 8 /* Both header & payload need alignment */ + +/* * Standard timing and size defines. * These values should follow the ieee80211 specifications. */ @@ -124,6 +137,13 @@ #define SHORT_EIFS ( SIFS + SHORT_DIFS + \ GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) +enum rt2x00_chip_intf { + RT2X00_CHIP_INTF_PCI, + RT2X00_CHIP_INTF_PCIE, + RT2X00_CHIP_INTF_USB, + RT2X00_CHIP_INTF_SOC, +}; + /* * Chipset identification * The chipset on the device is composed of a RT and RF chip. @@ -131,16 +151,31 @@ */ struct rt2x00_chip { u16 rt; -#define RT2460 0x0101 -#define RT2560 0x0201 -#define RT2570 0x1201 -#define RT2561s 0x0301 /* Turbo */ -#define RT2561 0x0302 -#define RT2661 0x0401 -#define RT2571 0x1300 +#define RT2460 0x2460 +#define RT2560 0x2560 +#define RT2570 0x2570 +#define RT2661 0x2661 +#define RT2573 0x2573 +#define RT2860 0x2860 /* 2.4GHz */ +#define RT2872 0x2872 /* WSOC */ +#define RT2883 0x2883 /* WSOC */ +#define RT3070 0x3070 +#define RT3071 0x3071 +#define RT3090 0x3090 /* 2.4GHz PCIe */ +#define RT3290 0x3290 +#define RT3352 0x3352 /* WSOC */ +#define RT3390 0x3390 +#define RT3572 0x3572 +#define RT3593 0x3593 +#define RT3883 0x3883 /* WSOC */ +#define RT5390 0x5390 /* 2.4GHz */ +#define RT5392 0x5392 /* 2.4GHz */ +#define RT5592 0x5592 u16 rf; - u32 rev; + u16 rev; + + enum rt2x00_chip_intf intf; }; /* @@ -161,8 +196,10 @@ struct channel_info { unsigned int flags; #define GEOGRAPHY_ALLOWED 0x00000001 - short tx_power1; - short tx_power2; + short max_power; + short default_power1; + short default_power2; + short default_power3; }; /* @@ -171,6 +208,8 @@ struct channel_info { struct antenna_setup { enum antenna rx; enum antenna tx; + u8 rx_chain_num; + u8 tx_chain_num; }; /* @@ -235,21 +274,18 @@ struct link_ant { struct antenna_setup active; /* - * RSSI information for the different antenna's. - * These statistics are used to determine when - * to switch antenna when using software diversity. - * - * rssi[0] -> Antenna A RSSI - * rssi[1] -> Antenna B RSSI + * RSSI history information for the antenna. + * Used to determine when to switch antenna + * when using software diversity. */ - int rssi_history[2]; + int rssi_history; /* * Current RSSI average of the currently active antenna. * Similar to the avg_rssi in the link_qual structure * this value is updated by using the walking average. */ - int rssi_ant; + struct ewma rssi_ant; }; /* @@ -278,19 +314,36 @@ struct link { /* * Currently active average RSSI value */ - int avg_rssi; + struct ewma avg_rssi; /* - * Currently precalculated percentages of successful - * TX and RX frames. + * Work structure for scheduling periodic link tuning. */ - int rx_percentage; - int tx_percentage; + struct delayed_work work; /* - * Work structure for scheduling periodic link tuning. + * Work structure for scheduling periodic watchdog monitoring. + * This work must be scheduled on the kernel workqueue, while + * all other work structures must be queued on the mac80211 + * workqueue. This guarantees that the watchdog can schedule + * other work structures and wait for their completion in order + * to bring the device/driver back into the desired state. */ - struct delayed_work work; + struct delayed_work watchdog_work; + + /* + * Work structure for scheduling periodic AGC adjustments. + */ + struct delayed_work agc_work; + + /* + * Work structure for scheduling periodic VCO calibration. + */ + struct delayed_work vco_work; +}; + +enum rt2x00_delayed_flags { + DELAYED_UPDATE_BEACON, }; /* @@ -300,20 +353,9 @@ struct link { */ struct rt2x00_intf { /* - * All fields within the rt2x00_intf structure - * must be protected with a spinlock. - */ - spinlock_t lock; - - /* - * MAC of the device. + * beacon->skb must be protected with the mutex. */ - u8 mac[ETH_ALEN]; - - /* - * BBSID of the AP to associate with. - */ - u8 bssid[ETH_ALEN]; + struct mutex beacon_skb_mutex; /* * Entry in the beacon queue which belongs to @@ -321,22 +363,19 @@ struct rt2x00_intf { * dedicated beacon entry. */ struct queue_entry *beacon; + bool enable_beacon; /* * Actions that needed rescheduling. */ - unsigned int delayed_flags; -#define DELAYED_UPDATE_BEACON 0x00000001 -#define DELAYED_CONFIG_ERP 0x00000002 -#define DELAYED_LED_ASSOC 0x00000004 + unsigned long delayed_flags; /* * Software sequence counter, this is only required * for hardware which doesn't support hardware * sequence counting. */ - spinlock_t seqlock; - u16 seqno; + atomic_t seqno; }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) @@ -357,6 +396,7 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) * for @tx_power_a, @tx_power_bg and @channels. * @channels: Device/chipset specific channel values (See &struct rf_channel). * @channels_info: Additional information for channels (See &struct channel_info). + * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap). */ struct hw_mode_spec { unsigned int supported_bands; @@ -370,6 +410,8 @@ struct hw_mode_spec { unsigned int num_channels; const struct rf_channel *channels; const struct channel_info *channels_info; + + struct ieee80211_sta_ht_cap ht; }; /* @@ -393,9 +435,6 @@ struct rt2x00lib_erp { int short_preamble; int cts_protection; - int ack_timeout; - int ack_consume_time; - u32 basic_rates; int slot_time; @@ -404,6 +443,9 @@ struct rt2x00lib_erp { short pifs; short difs; short eifs; + + u16 beacon_int; + u16 ht_opmode; }; /* @@ -416,11 +458,12 @@ struct rt2x00lib_crypto { const u8 *address; u32 bssidx; - u32 aid; u8 key[16]; u8 tx_mic[8]; u8 rx_mic[8]; + + int wcid; }; /* @@ -434,13 +477,13 @@ struct rt2x00intf_conf { enum nl80211_iftype type; /* - * TSF sync value, this is dependant on the operation type. + * TSF sync value, this is dependent on the operation type. */ enum tsf_sync sync; /* - * The MAC and BSSID addressess are simple array of bytes, - * these arrays are little endian, so when sending the addressess + * The MAC and BSSID addresses are simple array of bytes, + * these arrays are little endian, so when sending the addresses * to the drivers, copy the it into a endian-signed variable. * * Note that all devices (except rt2500usb) have 32 bits @@ -455,6 +498,19 @@ struct rt2x00intf_conf { }; /* + * Private structure for storing STA details + * wcid: Wireless Client ID + */ +struct rt2x00_sta { + int wcid; +}; + +static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta) +{ + return (struct rt2x00_sta *)sta->drv_priv; +} + +/* * rt2x00lib callback functions. */ struct rt2x00lib_ops { @@ -464,6 +520,15 @@ struct rt2x00lib_ops { irq_handler_t irq_handler; /* + * TX status tasklet handler. + */ + void (*txstatus_tasklet) (unsigned long data); + void (*pretbtt_tasklet) (unsigned long data); + void (*tbtt_tasklet) (unsigned long data); + void (*rxdone_tasklet) (unsigned long data); + void (*autowake_tasklet) (unsigned long data); + + /* * Device init handlers. */ int (*probe_hw) (struct rt2x00_dev *rt2x00dev); @@ -497,20 +562,30 @@ struct rt2x00lib_ops { struct link_qual *qual); void (*link_tuner) (struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count); + void (*gain_calibration) (struct rt2x00_dev *rt2x00dev); + void (*vco_calibration) (struct rt2x00_dev *rt2x00dev); + + /* + * Data queue handlers. + */ + void (*watchdog) (struct rt2x00_dev *rt2x00dev); + void (*start_queue) (struct data_queue *queue); + void (*kick_queue) (struct data_queue *queue); + void (*stop_queue) (struct data_queue *queue); + void (*flush_queue) (struct data_queue *queue, bool drop); + void (*tx_dma_done) (struct queue_entry *entry); /* * TX control handlers */ - void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, + void (*write_tx_desc) (struct queue_entry *entry, + struct txentry_desc *txdesc); + void (*write_tx_data) (struct queue_entry *entry, struct txentry_desc *txdesc); - int (*write_tx_data) (struct queue_entry *entry); - void (*write_beacon) (struct queue_entry *entry); + void (*write_beacon) (struct queue_entry *entry, + struct txentry_desc *txdesc); + void (*clear_beacon) (struct queue_entry *entry); int (*get_tx_data_len) (struct queue_entry *entry); - void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue); - void (*kill_tx_queue) (struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue); /* * RX control handlers @@ -538,12 +613,18 @@ struct rt2x00lib_ops { #define CONFIG_UPDATE_BSSID ( 1 << 3 ) void (*config_erp) (struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp); + struct rt2x00lib_erp *erp, + u32 changed); void (*config_ant) (struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant); void (*config) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int changed_flags); + int (*sta_add) (struct rt2x00_dev *rt2x00dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + int (*sta_remove) (struct rt2x00_dev *rt2x00dev, + int wcid); }; /* @@ -551,16 +632,14 @@ struct rt2x00lib_ops { */ struct rt2x00_ops { const char *name; - const unsigned int max_sta_intf; + const unsigned int drv_data_size; const unsigned int max_ap_intf; const unsigned int eeprom_size; const unsigned int rf_size; const unsigned int tx_queues; - const struct data_queue_desc *rx; - const struct data_queue_desc *tx; - const struct data_queue_desc *bcn; - const struct data_queue_desc *atim; + void (*queue_init)(struct data_queue *queue); const struct rt2x00lib_ops *lib; + const void *drv; const struct ieee80211_ops *hw; #ifdef CONFIG_RT2X00_LIB_DEBUGFS const struct rt2x00debug *debugfs; @@ -568,44 +647,79 @@ struct rt2x00_ops { }; /* - * rt2x00 device flags + * rt2x00 state flags */ -enum rt2x00_flags { +enum rt2x00_state_flags { /* - * Device state flags + * Device flags */ DEVICE_STATE_PRESENT, DEVICE_STATE_REGISTERED_HW, DEVICE_STATE_INITIALIZED, DEVICE_STATE_STARTED, DEVICE_STATE_ENABLED_RADIO, - DEVICE_STATE_DISABLED_RADIO_HW, + DEVICE_STATE_SCANNING, + + /* + * Driver configuration + */ + CONFIG_CHANNEL_HT40, + CONFIG_POWERSAVING, + CONFIG_HT_DISABLED, + CONFIG_QOS_DISABLED, /* - * Driver requirements + * Mark we currently are sequentially reading TX_STA_FIFO register + * FIXME: this is for only rt2800usb, should go to private data */ - DRIVER_REQUIRE_FIRMWARE, - DRIVER_REQUIRE_BEACON_GUARD, - DRIVER_REQUIRE_ATIM_QUEUE, - DRIVER_REQUIRE_SCHEDULED, - DRIVER_REQUIRE_DMA, - DRIVER_REQUIRE_COPY_IV, + TX_STATUS_READING, +}; +/* + * rt2x00 capability flags + */ +enum rt2x00_capability_flags { /* - * Driver features + * Requirements */ - CONFIG_SUPPORT_HW_BUTTON, - CONFIG_SUPPORT_HW_CRYPTO, + REQUIRE_FIRMWARE, + REQUIRE_BEACON_GUARD, + REQUIRE_ATIM_QUEUE, + REQUIRE_DMA, + REQUIRE_COPY_IV, + REQUIRE_L2PAD, + REQUIRE_TXSTATUS_FIFO, + REQUIRE_TASKLET_CONTEXT, + REQUIRE_SW_SEQNO, + REQUIRE_HT_TX_DESC, + REQUIRE_PS_AUTOWAKE, + REQUIRE_DELAYED_RFKILL, /* - * Driver configuration + * Capabilities */ - CONFIG_FRAME_TYPE, - CONFIG_RF_SEQUENCE, - CONFIG_EXTERNAL_LNA_A, - CONFIG_EXTERNAL_LNA_BG, - CONFIG_DOUBLE_ANTENNA, - CONFIG_DISABLE_LINK_TUNING, + CAPABILITY_HW_BUTTON, + CAPABILITY_HW_CRYPTO, + CAPABILITY_POWER_LIMIT, + CAPABILITY_CONTROL_FILTERS, + CAPABILITY_CONTROL_FILTER_PSPOLL, + CAPABILITY_PRE_TBTT_INTERRUPT, + CAPABILITY_LINK_TUNING, + CAPABILITY_FRAME_TYPE, + CAPABILITY_RF_SEQUENCE, + CAPABILITY_EXTERNAL_LNA_A, + CAPABILITY_EXTERNAL_LNA_BG, + CAPABILITY_DOUBLE_ANTENNA, + CAPABILITY_BT_COEXIST, + CAPABILITY_VCO_RECALIBRATION, +}; + +/* + * Interface combinations + */ +enum { + IF_COMB_AP = 0, + NUM_IF_COMB, }; /* @@ -617,7 +731,7 @@ struct rt2x00_dev { * The structure stored in here depends on the * system bus (PCI or USB). * When accessing this variable, the rt2x00dev_{pci,usb} - * macro's should be used for correct typecasting. + * macros should be used for correct typecasting. */ struct device *dev; @@ -627,23 +741,17 @@ struct rt2x00_dev { const struct rt2x00_ops *ops; /* + * Driver data. + */ + void *drv_data; + + /* * IEEE80211 control structure. */ struct ieee80211_hw *hw; struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; enum ieee80211_band curr_band; - - /* - * rfkill structure for RF state switching support. - * This will only be compiled in when required. - */ -#ifdef CONFIG_RT2X00_LIB_RFKILL - unsigned long rfkill_state; -#define RFKILL_STATE_ALLOCATED 1 -#define RFKILL_STATE_REGISTERED 2 -#define RFKILL_STATE_BLOCKED 3 - struct input_polled_dev *rfkill_poll_dev; -#endif /* CONFIG_RT2X00_LIB_RFKILL */ + int curr_freq; /* * If enabled, the debugfs interface structures @@ -665,13 +773,26 @@ struct rt2x00_dev { #endif /* CONFIG_RT2X00_LIB_LEDS */ /* - * Device flags. - * In these flags the current status and some - * of the device capabilities are stored. + * Device state flags. + * In these flags the current status is stored. + * Access to these flags should occur atomically. */ unsigned long flags; /* + * Device capabiltiy flags. + * In these flags the device/driver capabilities are stored. + * Access to these flags should occur non-atomically. + */ + unsigned long cap_flags; + + /* + * Device information, Bus IRQ and name (PCI, SoC) + */ + int irq; + const char *name; + + /* * Chipset identification. */ struct rt2x00_chip chip; @@ -720,10 +841,18 @@ struct rt2x00_dev { * - Open ap interface count. * - Open sta interface count. * - Association count. + * - Beaconing enabled count. */ unsigned int intf_ap_count; unsigned int intf_sta_count; unsigned int intf_associated; + unsigned int intf_beaconing; + + /* + * Interface combinations + */ + struct ieee80211_iface_limit if_limits_ap; + struct ieee80211_iface_combination if_combinations[NUM_IF_COMB]; /* * Link quality @@ -767,20 +896,37 @@ struct rt2x00_dev { u8 rssi_offset; /* - * Frequency offset (for rt61pci & rt73usb). + * Frequency offset. */ u8 freq_offset; /* + * Association id. + */ + u16 aid; + + /* + * Beacon interval. + */ + u16 beacon_int; + + /** + * Timestamp of last received beacon + */ + unsigned long last_beacon; + + /* * Low level statistics which will have * to be kept up to date while device is running. */ struct ieee80211_low_level_stats low_level_stats; - /* - * RX configuration information. + /** + * Work queue for all work which should not be placed + * on the mac80211 workqueue (because of dependencies + * between various work structures). */ - struct ieee80211_rx_status rx_status; + struct workqueue_struct *workqueue; /* * Scheduled work. @@ -789,24 +935,95 @@ struct rt2x00_dev { * due to RTNL locking requirements. */ struct work_struct intf_work; - struct work_struct filter_work; + + /** + * Scheduled work for TX/RX done handling (USB devices) + */ + struct work_struct rxdone_work; + struct work_struct txdone_work; + + /* + * Powersaving work + */ + struct delayed_work autowakeup_work; + struct work_struct sleep_work; /* - * Data queue arrays for RX, TX and Beacon. - * The Beacon array also contains the Atim queue - * if that is supported by the device. + * Data queue arrays for RX, TX, Beacon and ATIM. */ unsigned int data_queues; struct data_queue *rx; struct data_queue *tx; struct data_queue *bcn; + struct data_queue *atim; /* * Firmware image. */ const struct firmware *fw; + + /* + * FIFO for storing tx status reports between isr and tasklet. + */ + DECLARE_KFIFO_PTR(txstatus_fifo, u32); + + /* + * Timer to ensure tx status reports are read (rt2800usb). + */ + struct hrtimer txstatus_timer; + + /* + * Tasklet for processing tx status reports (rt2800pci). + */ + struct tasklet_struct txstatus_tasklet; + struct tasklet_struct pretbtt_tasklet; + struct tasklet_struct tbtt_tasklet; + struct tasklet_struct rxdone_tasklet; + struct tasklet_struct autowake_tasklet; + + /* + * Used for VCO periodic calibration. + */ + int rf_channel; + + /* + * Protect the interrupt mask register. + */ + spinlock_t irqmask_lock; + + /* + * List of BlockAckReq TX entries that need driver BlockAck processing. + */ + struct list_head bar_list; + spinlock_t bar_list_lock; + + /* Extra TX headroom required for alignment purposes. */ + unsigned int extra_tx_headroom; }; +struct rt2x00_bar_list_entry { + struct list_head list; + struct rcu_head head; + + struct queue_entry *entry; + int block_acked; + + /* Relevant parts of the IEEE80211 BAR header */ + __u8 ra[6]; + __u8 ta[6]; + __le16 control; + __le16 start_seq_num; +}; + +/* + * Register defines. + * Some registers require multiple attempts before success, + * in those cases REGISTER_BUSY_COUNT attempts should be + * taken with a REGISTER_BUSY_DELAY interval. + */ +#define REGISTER_BUSY_COUNT 100 +#define REGISTER_BUSY_DELAY 100 + /* * Generic RF access. * The RF is being accessed by word index. @@ -814,18 +1031,19 @@ struct rt2x00_dev { static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 *data) { - *data = rt2x00dev->rf[word]; + BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32)); + *data = rt2x00dev->rf[word - 1]; } static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 data) { - rt2x00dev->rf[word] = data; + BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32)); + rt2x00dev->rf[word - 1] = data; } /* - * Generic EEPROM access. - * The EEPROM is being accessed by word index. + * Generic EEPROM access. The EEPROM is being accessed by word or byte index. */ static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev, const unsigned int word) @@ -845,57 +1063,231 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev, rt2x00dev->eeprom[word] = cpu_to_le16(data); } +static inline u8 rt2x00_eeprom_byte(struct rt2x00_dev *rt2x00dev, + const unsigned int byte) +{ + return *(((u8 *)rt2x00dev->eeprom) + byte); +} + /* * Chipset handlers */ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, - const u16 rt, const u16 rf, const u32 rev) + const u16 rt, const u16 rf, const u16 rev) { - INFO(rt2x00dev, - "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n", - rt, rf, rev); - rt2x00dev->chip.rt = rt; rt2x00dev->chip.rf = rf; rt2x00dev->chip.rev = rev; + + rt2x00_info(rt2x00dev, "Chipset detected - rt: %04x, rf: %04x, rev: %04x\n", + rt2x00dev->chip.rt, rt2x00dev->chip.rf, + rt2x00dev->chip.rev); } -static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip) +static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev, + const u16 rt, const u16 rev) { - return (chipset->rt == chip); + rt2x00dev->chip.rt = rt; + rt2x00dev->chip.rev = rev; + + rt2x00_info(rt2x00dev, "RT chipset %04x, rev %04x detected\n", + rt2x00dev->chip.rt, rt2x00dev->chip.rev); } -static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) +static inline void rt2x00_set_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) { - return (chipset->rf == chip); + rt2x00dev->chip.rf = rf; + + rt2x00_info(rt2x00dev, "RF chipset %04x detected\n", + rt2x00dev->chip.rf); } -static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) +static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) { - return chipset->rev; + return (rt2x00dev->chip.rt == rt); } -static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset, - const u32 rev) +static inline bool rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) { - return (((chipset->rev & 0xffff0) == rev) && - !!(chipset->rev & 0x0000f)); + return (rt2x00dev->chip.rf == rf); +} + +static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00dev->chip.rev; +} + +static inline bool rt2x00_rt_rev(struct rt2x00_dev *rt2x00dev, + const u16 rt, const u16 rev) +{ + return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) == rev); +} + +static inline bool rt2x00_rt_rev_lt(struct rt2x00_dev *rt2x00dev, + const u16 rt, const u16 rev) +{ + return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) < rev); +} + +static inline bool rt2x00_rt_rev_gte(struct rt2x00_dev *rt2x00dev, + const u16 rt, const u16 rev) +{ + return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) >= rev); +} + +static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, + enum rt2x00_chip_intf intf) +{ + rt2x00dev->chip.intf = intf; +} + +static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev, + enum rt2x00_chip_intf intf) +{ + return (rt2x00dev->chip.intf == intf); +} + +static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI) || + rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); +} + +static inline bool rt2x00_is_pcie(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); +} + +static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); +} + +static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); +} + +/* Helpers for capability flags */ + +static inline bool +rt2x00_has_cap_flag(struct rt2x00_dev *rt2x00dev, + enum rt2x00_capability_flags cap_flag) +{ + return test_bit(cap_flag, &rt2x00dev->cap_flags); +} + +static inline bool +rt2x00_has_cap_hw_crypto(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_HW_CRYPTO); +} + +static inline bool +rt2x00_has_cap_power_limit(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_POWER_LIMIT); +} + +static inline bool +rt2x00_has_cap_control_filters(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTERS); +} + +static inline bool +rt2x00_has_cap_control_filter_pspoll(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTER_PSPOLL); +} + +static inline bool +rt2x00_has_cap_pre_tbtt_interrupt(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_PRE_TBTT_INTERRUPT); +} + +static inline bool +rt2x00_has_cap_link_tuning(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_LINK_TUNING); +} + +static inline bool +rt2x00_has_cap_frame_type(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_FRAME_TYPE); +} + +static inline bool +rt2x00_has_cap_rf_sequence(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RF_SEQUENCE); +} + +static inline bool +rt2x00_has_cap_external_lna_a(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_A); +} + +static inline bool +rt2x00_has_cap_external_lna_bg(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_BG); +} + +static inline bool +rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA); +} + +static inline bool +rt2x00_has_cap_bt_coexist(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_BT_COEXIST); +} + +static inline bool +rt2x00_has_cap_vco_recalibration(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION); } /** * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to map. + * @entry: Pointer to &struct queue_entry + * + * Returns -ENOMEM if mapping fail, 0 otherwise. */ -void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); +int rt2x00queue_map_txskb(struct queue_entry *entry); /** - * rt2x00queue_get_queue - Convert queue index to queue pointer + * rt2x00queue_unmap_skb - Unmap a skb from DMA. + * @entry: Pointer to &struct queue_entry + */ +void rt2x00queue_unmap_skb(struct queue_entry *entry); + +/** + * rt2x00queue_get_tx_queue - Convert tx queue index to queue pointer * @rt2x00dev: Pointer to &struct rt2x00_dev. * @queue: rt2x00 queue index (see &enum data_queue_qid). + * + * Returns NULL for non tx queues. */ -struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue); +static inline struct data_queue * +rt2x00queue_get_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid queue) +{ + if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx) + return &rt2x00dev->tx[queue]; + + if (queue == QID_ATIM) + return rt2x00dev->atim; + + return NULL; +} /** * rt2x00queue_get_entry - Get queue entry where the given index points to. @@ -905,33 +1297,135 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, enum queue_index index); +/** + * rt2x00queue_pause_queue - Pause a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will pause the data queue locally, preventing + * new frames to be added to the queue (while the hardware is + * still allowed to run). + */ +void rt2x00queue_pause_queue(struct data_queue *queue); + +/** + * rt2x00queue_unpause_queue - unpause a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will unpause the data queue locally, allowing + * new frames to be added to the queue again. + */ +void rt2x00queue_unpause_queue(struct data_queue *queue); + +/** + * rt2x00queue_start_queue - Start a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will start handling all pending frames in the queue. + */ +void rt2x00queue_start_queue(struct data_queue *queue); + +/** + * rt2x00queue_stop_queue - Halt a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will stop all pending frames in the queue. + */ +void rt2x00queue_stop_queue(struct data_queue *queue); + +/** + * rt2x00queue_flush_queue - Flush a data queue + * @queue: Pointer to &struct data_queue. + * @drop: True to drop all pending frames. + * + * This function will flush the queue. After this call + * the queue is guaranteed to be empty. + */ +void rt2x00queue_flush_queue(struct data_queue *queue, bool drop); + +/** + * rt2x00queue_start_queues - Start all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to start them + */ +void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00queue_stop_queues - Halt all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to stop + * any pending frames. + */ +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00queue_flush_queues - Flush all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @drop: True to drop all pending frames. + * + * This function will loop through all available queues to flush + * any pending frames. + */ +void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop); + +/* + * Debugfs handlers. + */ +/** + * rt2x00debug_dump_frame - Dump a frame to userspace through debugfs. + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @type: The type of frame that is being dumped. + * @skb: The skb containing the frame to be dumped. + */ +#ifdef CONFIG_RT2X00_LIB_DEBUGFS +void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, + enum rt2x00_dump_type type, struct sk_buff *skb); +#else +static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, + enum rt2x00_dump_type type, + struct sk_buff *skb) +{ +} +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ + +/* + * Utility functions. + */ +u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev, + struct ieee80211_vif *vif); + /* * Interrupt context handlers. */ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_dmastart(struct queue_entry *entry); +void rt2x00lib_dmadone(struct queue_entry *entry); void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc); -void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry); +void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); +void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp); /* * mac80211 handlers. */ -int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +void rt2x00mac_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb); int rt2x00mac_start(struct ieee80211_hw *hw); void rt2x00mac_stop(struct ieee80211_hw *hw); int rt2x00mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); void rt2x00mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); -int rt2x00mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); void rt2x00mac_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_addr_list *mc_list); + u64 multicast); +int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + bool set); #ifdef CONFIG_RT2X00_LIB_CRYPTO int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -939,16 +1433,29 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, #else #define rt2x00mac_set_key NULL #endif /* CONFIG_RT2X00_LIB_CRYPTO */ +int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw); +void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw); int rt2x00mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); -int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats); void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, +int rt2x00mac_conf_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params); +void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); +void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop); +int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); +int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); +void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, + u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); +bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw); /* * Driver allocation handlers. |
