162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
462306a36Sopenharmony_ci	Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
562306a36Sopenharmony_ci	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
662306a36Sopenharmony_ci	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
762306a36Sopenharmony_ci	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
862306a36Sopenharmony_ci	Copyright (C) 2009 Axel Kollhofer <rain_maker@root-forum.org>
962306a36Sopenharmony_ci	<http://rt2x00.serialmonkey.com>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/*
1462306a36Sopenharmony_ci	Module: rt2800usb
1562306a36Sopenharmony_ci	Abstract: rt2800usb device specific routines.
1662306a36Sopenharmony_ci	Supported chipsets: RT2800U.
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <linux/delay.h>
2062306a36Sopenharmony_ci#include <linux/etherdevice.h>
2162306a36Sopenharmony_ci#include <linux/kernel.h>
2262306a36Sopenharmony_ci#include <linux/module.h>
2362306a36Sopenharmony_ci#include <linux/usb.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include "rt2x00.h"
2662306a36Sopenharmony_ci#include "rt2x00usb.h"
2762306a36Sopenharmony_ci#include "rt2800lib.h"
2862306a36Sopenharmony_ci#include "rt2800.h"
2962306a36Sopenharmony_ci#include "rt2800usb.h"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci/*
3262306a36Sopenharmony_ci * Allow hardware encryption to be disabled.
3362306a36Sopenharmony_ci */
3462306a36Sopenharmony_cistatic bool modparam_nohwcrypt;
3562306a36Sopenharmony_cimodule_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444);
3662306a36Sopenharmony_ciMODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic bool rt2800usb_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	return modparam_nohwcrypt;
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/*
4462306a36Sopenharmony_ci * Queue handlers.
4562306a36Sopenharmony_ci */
4662306a36Sopenharmony_cistatic void rt2800usb_start_queue(struct data_queue *queue)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
4962306a36Sopenharmony_ci	u32 reg;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	switch (queue->qid) {
5262306a36Sopenharmony_ci	case QID_RX:
5362306a36Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL);
5462306a36Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
5562306a36Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
5662306a36Sopenharmony_ci		break;
5762306a36Sopenharmony_ci	case QID_BEACON:
5862306a36Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG);
5962306a36Sopenharmony_ci		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
6062306a36Sopenharmony_ci		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
6162306a36Sopenharmony_ci		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
6262306a36Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
6362306a36Sopenharmony_ci		break;
6462306a36Sopenharmony_ci	default:
6562306a36Sopenharmony_ci		break;
6662306a36Sopenharmony_ci	}
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic void rt2800usb_stop_queue(struct data_queue *queue)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
7262306a36Sopenharmony_ci	u32 reg;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	switch (queue->qid) {
7562306a36Sopenharmony_ci	case QID_RX:
7662306a36Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL);
7762306a36Sopenharmony_ci		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
7862306a36Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
7962306a36Sopenharmony_ci		break;
8062306a36Sopenharmony_ci	case QID_BEACON:
8162306a36Sopenharmony_ci		reg = rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG);
8262306a36Sopenharmony_ci		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
8362306a36Sopenharmony_ci		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
8462306a36Sopenharmony_ci		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
8562306a36Sopenharmony_ci		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
8662306a36Sopenharmony_ci		break;
8762306a36Sopenharmony_ci	default:
8862306a36Sopenharmony_ci		break;
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#define TXSTATUS_READ_INTERVAL 1000000
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
9562306a36Sopenharmony_ci						 int urb_status, u32 tx_status)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	bool valid;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	if (urb_status) {
10062306a36Sopenharmony_ci		rt2x00_warn(rt2x00dev, "TX status read failed %d\n",
10162306a36Sopenharmony_ci			    urb_status);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci		goto stop_reading;
10462306a36Sopenharmony_ci	}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID);
10762306a36Sopenharmony_ci	if (valid) {
10862306a36Sopenharmony_ci		if (!kfifo_put(&rt2x00dev->txstatus_fifo, tx_status))
10962306a36Sopenharmony_ci			rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n");
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci		/* Reschedule urb to read TX status again instantly */
11462306a36Sopenharmony_ci		return true;
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	/* Check if there is any entry that timedout waiting on TX status */
11862306a36Sopenharmony_ci	if (rt2800_txstatus_timeout(rt2x00dev))
11962306a36Sopenharmony_ci		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	if (rt2800_txstatus_pending(rt2x00dev)) {
12262306a36Sopenharmony_ci		/* Read register after 1 ms */
12362306a36Sopenharmony_ci		hrtimer_start(&rt2x00dev->txstatus_timer,
12462306a36Sopenharmony_ci			      TXSTATUS_READ_INTERVAL,
12562306a36Sopenharmony_ci			      HRTIMER_MODE_REL);
12662306a36Sopenharmony_ci		return false;
12762306a36Sopenharmony_ci	}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistop_reading:
13062306a36Sopenharmony_ci	clear_bit(TX_STATUS_READING, &rt2x00dev->flags);
13162306a36Sopenharmony_ci	/*
13262306a36Sopenharmony_ci	 * There is small race window above, between txstatus pending check and
13362306a36Sopenharmony_ci	 * clear_bit someone could do rt2x00usb_interrupt_txdone, so recheck
13462306a36Sopenharmony_ci	 * here again if status reading is needed.
13562306a36Sopenharmony_ci	 */
13662306a36Sopenharmony_ci	if (rt2800_txstatus_pending(rt2x00dev) &&
13762306a36Sopenharmony_ci	    !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
13862306a36Sopenharmony_ci		return true;
13962306a36Sopenharmony_ci	else
14062306a36Sopenharmony_ci		return false;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
14762306a36Sopenharmony_ci		return;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	/* Read TX_STA_FIFO register after 2 ms */
15062306a36Sopenharmony_ci	hrtimer_start(&rt2x00dev->txstatus_timer,
15162306a36Sopenharmony_ci		      2 * TXSTATUS_READ_INTERVAL,
15262306a36Sopenharmony_ci		      HRTIMER_MODE_REL);
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic void rt2800usb_tx_dma_done(struct queue_entry *entry)
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	rt2800usb_async_read_tx_status(rt2x00dev);
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev =
16562306a36Sopenharmony_ci	    container_of(timer, struct rt2x00_dev, txstatus_timer);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
16862306a36Sopenharmony_ci				      rt2800usb_tx_sta_fifo_read_completed);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	return HRTIMER_NORESTART;
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci/*
17462306a36Sopenharmony_ci * Firmware functions
17562306a36Sopenharmony_ci */
17662306a36Sopenharmony_cistatic int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	__le32 *reg;
17962306a36Sopenharmony_ci	u32 fw_mode;
18062306a36Sopenharmony_ci	int ret;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	reg = kmalloc(sizeof(*reg), GFP_KERNEL);
18362306a36Sopenharmony_ci	if (reg == NULL)
18462306a36Sopenharmony_ci		return -ENOMEM;
18562306a36Sopenharmony_ci	/* cannot use rt2x00usb_register_read here as it uses different
18662306a36Sopenharmony_ci	 * mode (MULTI_READ vs. DEVICE_MODE) and does not pass the
18762306a36Sopenharmony_ci	 * magic value USB_MODE_AUTORUN (0x11) to the device, thus the
18862306a36Sopenharmony_ci	 * returned value would be invalid.
18962306a36Sopenharmony_ci	 */
19062306a36Sopenharmony_ci	ret = rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE,
19162306a36Sopenharmony_ci				       USB_VENDOR_REQUEST_IN, 0,
19262306a36Sopenharmony_ci				       USB_MODE_AUTORUN, reg, sizeof(*reg),
19362306a36Sopenharmony_ci				       REGISTER_TIMEOUT_FIRMWARE);
19462306a36Sopenharmony_ci	fw_mode = le32_to_cpu(*reg);
19562306a36Sopenharmony_ci	kfree(reg);
19662306a36Sopenharmony_ci	if (ret < 0)
19762306a36Sopenharmony_ci		return ret;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	if ((fw_mode & 0x00000003) == 2)
20062306a36Sopenharmony_ci		return 1;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	return 0;
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistatic char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	return FIRMWARE_RT2870;
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistatic int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
21162306a36Sopenharmony_ci				    const u8 *data, const size_t len)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	int status;
21462306a36Sopenharmony_ci	u32 offset;
21562306a36Sopenharmony_ci	u32 length;
21662306a36Sopenharmony_ci	int retval;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	/*
21962306a36Sopenharmony_ci	 * Check which section of the firmware we need.
22062306a36Sopenharmony_ci	 */
22162306a36Sopenharmony_ci	if (rt2x00_rt(rt2x00dev, RT2860) ||
22262306a36Sopenharmony_ci	    rt2x00_rt(rt2x00dev, RT2872) ||
22362306a36Sopenharmony_ci	    rt2x00_rt(rt2x00dev, RT3070)) {
22462306a36Sopenharmony_ci		offset = 0;
22562306a36Sopenharmony_ci		length = 4096;
22662306a36Sopenharmony_ci	} else {
22762306a36Sopenharmony_ci		offset = 4096;
22862306a36Sopenharmony_ci		length = 4096;
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	/*
23262306a36Sopenharmony_ci	 * Write firmware to device.
23362306a36Sopenharmony_ci	 */
23462306a36Sopenharmony_ci	retval = rt2800usb_autorun_detect(rt2x00dev);
23562306a36Sopenharmony_ci	if (retval < 0)
23662306a36Sopenharmony_ci		return retval;
23762306a36Sopenharmony_ci	if (retval) {
23862306a36Sopenharmony_ci		rt2x00_info(rt2x00dev,
23962306a36Sopenharmony_ci			    "Firmware loading not required - NIC in AutoRun mode\n");
24062306a36Sopenharmony_ci		__clear_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
24162306a36Sopenharmony_ci	} else {
24262306a36Sopenharmony_ci		rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
24362306a36Sopenharmony_ci					      data + offset, length);
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
24762306a36Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	/*
25062306a36Sopenharmony_ci	 * Send firmware request to device to load firmware,
25162306a36Sopenharmony_ci	 * we need to specify a long timeout time.
25262306a36Sopenharmony_ci	 */
25362306a36Sopenharmony_ci	status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
25462306a36Sopenharmony_ci					     0, USB_MODE_FIRMWARE,
25562306a36Sopenharmony_ci					     REGISTER_TIMEOUT_FIRMWARE);
25662306a36Sopenharmony_ci	if (status < 0) {
25762306a36Sopenharmony_ci		rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
25862306a36Sopenharmony_ci		return status;
25962306a36Sopenharmony_ci	}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	msleep(10);
26262306a36Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	return 0;
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci/*
26862306a36Sopenharmony_ci * Device state switch handlers.
26962306a36Sopenharmony_ci */
27062306a36Sopenharmony_cistatic int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	u32 reg;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	/*
27562306a36Sopenharmony_ci	 * Wait until BBP and RF are ready.
27662306a36Sopenharmony_ci	 */
27762306a36Sopenharmony_ci	if (rt2800_wait_csr_ready(rt2x00dev))
27862306a36Sopenharmony_ci		return -EBUSY;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	reg = rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL);
28162306a36Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	reg = 0;
28462306a36Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
28562306a36Sopenharmony_ci	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
28662306a36Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
28962306a36Sopenharmony_ci				    USB_MODE_RESET, REGISTER_TIMEOUT);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	return 0;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	u32 reg = 0;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
30162306a36Sopenharmony_ci		return -EIO;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
30462306a36Sopenharmony_ci	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
30562306a36Sopenharmony_ci	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
30662306a36Sopenharmony_ci	/*
30762306a36Sopenharmony_ci	 * Total room for RX frames in kilobytes, PBF might still exceed
30862306a36Sopenharmony_ci	 * this limit so reduce the number to prevent errors.
30962306a36Sopenharmony_ci	 */
31062306a36Sopenharmony_ci	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
31162306a36Sopenharmony_ci			   ((rt2x00dev->rx->limit * DATA_FRAME_SIZE)
31262306a36Sopenharmony_ci			    / 1024) - 3);
31362306a36Sopenharmony_ci	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
31462306a36Sopenharmony_ci	rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
31562306a36Sopenharmony_ci	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	return rt2800_enable_radio(rt2x00dev);
31862306a36Sopenharmony_ci}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	rt2800_disable_radio(rt2x00dev);
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistatic int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev,
32662306a36Sopenharmony_ci			       enum dev_state state)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	if (state == STATE_AWAKE)
32962306a36Sopenharmony_ci		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 2);
33062306a36Sopenharmony_ci	else
33162306a36Sopenharmony_ci		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	return 0;
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
33762306a36Sopenharmony_ci				      enum dev_state state)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	int retval = 0;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	switch (state) {
34262306a36Sopenharmony_ci	case STATE_RADIO_ON:
34362306a36Sopenharmony_ci		/*
34462306a36Sopenharmony_ci		 * Before the radio can be enabled, the device first has
34562306a36Sopenharmony_ci		 * to be woken up. After that it needs a bit of time
34662306a36Sopenharmony_ci		 * to be fully awake and then the radio can be enabled.
34762306a36Sopenharmony_ci		 */
34862306a36Sopenharmony_ci		rt2800usb_set_state(rt2x00dev, STATE_AWAKE);
34962306a36Sopenharmony_ci		msleep(1);
35062306a36Sopenharmony_ci		retval = rt2800usb_enable_radio(rt2x00dev);
35162306a36Sopenharmony_ci		break;
35262306a36Sopenharmony_ci	case STATE_RADIO_OFF:
35362306a36Sopenharmony_ci		/*
35462306a36Sopenharmony_ci		 * After the radio has been disabled, the device should
35562306a36Sopenharmony_ci		 * be put to sleep for powersaving.
35662306a36Sopenharmony_ci		 */
35762306a36Sopenharmony_ci		rt2800usb_disable_radio(rt2x00dev);
35862306a36Sopenharmony_ci		rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
35962306a36Sopenharmony_ci		break;
36062306a36Sopenharmony_ci	case STATE_RADIO_IRQ_ON:
36162306a36Sopenharmony_ci	case STATE_RADIO_IRQ_OFF:
36262306a36Sopenharmony_ci		/* No support, but no error either */
36362306a36Sopenharmony_ci		break;
36462306a36Sopenharmony_ci	case STATE_DEEP_SLEEP:
36562306a36Sopenharmony_ci	case STATE_SLEEP:
36662306a36Sopenharmony_ci	case STATE_STANDBY:
36762306a36Sopenharmony_ci	case STATE_AWAKE:
36862306a36Sopenharmony_ci		retval = rt2800usb_set_state(rt2x00dev, state);
36962306a36Sopenharmony_ci		break;
37062306a36Sopenharmony_ci	default:
37162306a36Sopenharmony_ci		retval = -ENOTSUPP;
37262306a36Sopenharmony_ci		break;
37362306a36Sopenharmony_ci	}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	if (unlikely(retval))
37662306a36Sopenharmony_ci		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
37762306a36Sopenharmony_ci			   state, retval);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	return retval;
38062306a36Sopenharmony_ci}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_cistatic unsigned int rt2800usb_get_dma_done(struct data_queue *queue)
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	struct queue_entry *entry;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
38762306a36Sopenharmony_ci	return entry->entry_idx;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci/*
39162306a36Sopenharmony_ci * TX descriptor initialization
39262306a36Sopenharmony_ci */
39362306a36Sopenharmony_cistatic __le32 *rt2800usb_get_txwi(struct queue_entry *entry)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	if (entry->queue->qid == QID_BEACON)
39662306a36Sopenharmony_ci		return (__le32 *) (entry->skb->data);
39762306a36Sopenharmony_ci	else
39862306a36Sopenharmony_ci		return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
39962306a36Sopenharmony_ci}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic void rt2800usb_write_tx_desc(struct queue_entry *entry,
40262306a36Sopenharmony_ci				    struct txentry_desc *txdesc)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
40562306a36Sopenharmony_ci	__le32 *txi = (__le32 *) entry->skb->data;
40662306a36Sopenharmony_ci	u32 word;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	/*
40962306a36Sopenharmony_ci	 * Initialize TXINFO descriptor
41062306a36Sopenharmony_ci	 */
41162306a36Sopenharmony_ci	word = rt2x00_desc_read(txi, 0);
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	/*
41462306a36Sopenharmony_ci	 * The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is
41562306a36Sopenharmony_ci	 * TXWI + 802.11 header + L2 pad + payload + pad,
41662306a36Sopenharmony_ci	 * so need to decrease size of TXINFO.
41762306a36Sopenharmony_ci	 */
41862306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
41962306a36Sopenharmony_ci			   roundup(entry->skb->len, 4) - TXINFO_DESC_SIZE);
42062306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXINFO_W0_WIV,
42162306a36Sopenharmony_ci			   !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
42262306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
42362306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXINFO_W0_SW_USE_LAST_ROUND, 0);
42462306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_NEXT_VALID, 0);
42562306a36Sopenharmony_ci	rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST,
42662306a36Sopenharmony_ci			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));
42762306a36Sopenharmony_ci	rt2x00_desc_write(txi, 0, word);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	/*
43062306a36Sopenharmony_ci	 * Register descriptor details in skb frame descriptor.
43162306a36Sopenharmony_ci	 */
43262306a36Sopenharmony_ci	skbdesc->flags |= SKBDESC_DESC_IN_SKB;
43362306a36Sopenharmony_ci	skbdesc->desc = txi;
43462306a36Sopenharmony_ci	skbdesc->desc_len = TXINFO_DESC_SIZE + entry->queue->winfo_size;
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci/*
43862306a36Sopenharmony_ci * TX data initialization
43962306a36Sopenharmony_ci */
44062306a36Sopenharmony_cistatic int rt2800usb_get_tx_data_len(struct queue_entry *entry)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	/*
44362306a36Sopenharmony_ci	 * pad(1~3 bytes) is needed after each 802.11 payload.
44462306a36Sopenharmony_ci	 * USB end pad(4 bytes) is needed at each USB bulk out packet end.
44562306a36Sopenharmony_ci	 * TX frame format is :
44662306a36Sopenharmony_ci	 * | TXINFO | TXWI | 802.11 header | L2 pad | payload | pad | USB end pad |
44762306a36Sopenharmony_ci	 *                 |<------------- tx_pkt_len ------------->|
44862306a36Sopenharmony_ci	 */
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	return roundup(entry->skb->len, 4) + 4;
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci/*
45462306a36Sopenharmony_ci * TX control handlers
45562306a36Sopenharmony_ci */
45662306a36Sopenharmony_cistatic void rt2800usb_work_txdone(struct work_struct *work)
45762306a36Sopenharmony_ci{
45862306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev =
45962306a36Sopenharmony_ci	    container_of(work, struct rt2x00_dev, txdone_work);
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
46262306a36Sopenharmony_ci	       rt2800_txstatus_timeout(rt2x00dev)) {
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci		rt2800_txdone(rt2x00dev, UINT_MAX);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci		rt2800_txdone_nostatus(rt2x00dev);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci		/*
46962306a36Sopenharmony_ci		 * The hw may delay sending the packet after DMA complete
47062306a36Sopenharmony_ci		 * if the medium is busy, thus the TX_STA_FIFO entry is
47162306a36Sopenharmony_ci		 * also delayed -> use a timer to retrieve it.
47262306a36Sopenharmony_ci		 */
47362306a36Sopenharmony_ci		if (rt2800_txstatus_pending(rt2x00dev))
47462306a36Sopenharmony_ci			rt2800usb_async_read_tx_status(rt2x00dev);
47562306a36Sopenharmony_ci	}
47662306a36Sopenharmony_ci}
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci/*
47962306a36Sopenharmony_ci * RX control handlers
48062306a36Sopenharmony_ci */
48162306a36Sopenharmony_cistatic void rt2800usb_fill_rxdone(struct queue_entry *entry,
48262306a36Sopenharmony_ci				  struct rxdone_entry_desc *rxdesc)
48362306a36Sopenharmony_ci{
48462306a36Sopenharmony_ci	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
48562306a36Sopenharmony_ci	__le32 *rxi = (__le32 *)entry->skb->data;
48662306a36Sopenharmony_ci	__le32 *rxd;
48762306a36Sopenharmony_ci	u32 word;
48862306a36Sopenharmony_ci	int rx_pkt_len;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	/*
49162306a36Sopenharmony_ci	 * Copy descriptor to the skbdesc->desc buffer, making it safe from
49262306a36Sopenharmony_ci	 * moving of frame data in rt2x00usb.
49362306a36Sopenharmony_ci	 */
49462306a36Sopenharmony_ci	memcpy(skbdesc->desc, rxi, skbdesc->desc_len);
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	/*
49762306a36Sopenharmony_ci	 * RX frame format is :
49862306a36Sopenharmony_ci	 * | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad |
49962306a36Sopenharmony_ci	 *          |<------------ rx_pkt_len -------------->|
50062306a36Sopenharmony_ci	 */
50162306a36Sopenharmony_ci	word = rt2x00_desc_read(rxi, 0);
50262306a36Sopenharmony_ci	rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	/*
50562306a36Sopenharmony_ci	 * Remove the RXINFO structure from the sbk.
50662306a36Sopenharmony_ci	 */
50762306a36Sopenharmony_ci	skb_pull(entry->skb, RXINFO_DESC_SIZE);
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	/*
51062306a36Sopenharmony_ci	 * Check for rx_pkt_len validity. Return if invalid, leaving
51162306a36Sopenharmony_ci	 * rxdesc->size zeroed out by the upper level.
51262306a36Sopenharmony_ci	 */
51362306a36Sopenharmony_ci	if (unlikely(rx_pkt_len == 0 ||
51462306a36Sopenharmony_ci			rx_pkt_len > entry->queue->data_size)) {
51562306a36Sopenharmony_ci		rt2x00_err(entry->queue->rt2x00dev,
51662306a36Sopenharmony_ci			   "Bad frame size %d, forcing to 0\n", rx_pkt_len);
51762306a36Sopenharmony_ci		return;
51862306a36Sopenharmony_ci	}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	rxd = (__le32 *)(entry->skb->data + rx_pkt_len);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	/*
52362306a36Sopenharmony_ci	 * It is now safe to read the descriptor on all architectures.
52462306a36Sopenharmony_ci	 */
52562306a36Sopenharmony_ci	word = rt2x00_desc_read(rxd, 0);
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	if (rt2x00_get_field32(word, RXD_W0_CRC_ERROR))
52862306a36Sopenharmony_ci		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W0_CIPHER_ERROR);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	if (rt2x00_get_field32(word, RXD_W0_DECRYPTED)) {
53362306a36Sopenharmony_ci		/*
53462306a36Sopenharmony_ci		 * Hardware has stripped IV/EIV data from 802.11 frame during
53562306a36Sopenharmony_ci		 * decryption. Unfortunately the descriptor doesn't contain
53662306a36Sopenharmony_ci		 * any fields with the EIV/IV data either, so they can't
53762306a36Sopenharmony_ci		 * be restored by rt2x00lib.
53862306a36Sopenharmony_ci		 */
53962306a36Sopenharmony_ci		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci		/*
54262306a36Sopenharmony_ci		 * The hardware has already checked the Michael Mic and has
54362306a36Sopenharmony_ci		 * stripped it from the frame. Signal this to mac80211.
54462306a36Sopenharmony_ci		 */
54562306a36Sopenharmony_ci		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci		if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) {
54862306a36Sopenharmony_ci			rxdesc->flags |= RX_FLAG_DECRYPTED;
54962306a36Sopenharmony_ci		} else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) {
55062306a36Sopenharmony_ci			/*
55162306a36Sopenharmony_ci			 * In order to check the Michael Mic, the packet must have
55262306a36Sopenharmony_ci			 * been decrypted.  Mac80211 doesnt check the MMIC failure
55362306a36Sopenharmony_ci			 * flag to initiate MMIC countermeasures if the decoded flag
55462306a36Sopenharmony_ci			 * has not been set.
55562306a36Sopenharmony_ci			 */
55662306a36Sopenharmony_ci			rxdesc->flags |= RX_FLAG_DECRYPTED;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci			rxdesc->flags |= RX_FLAG_MMIC_ERROR;
55962306a36Sopenharmony_ci		}
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	if (rt2x00_get_field32(word, RXD_W0_MY_BSS))
56362306a36Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_MY_BSS;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	if (rt2x00_get_field32(word, RXD_W0_L2PAD))
56662306a36Sopenharmony_ci		rxdesc->dev_flags |= RXDONE_L2PAD;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	/*
56962306a36Sopenharmony_ci	 * Remove RXD descriptor from end of buffer.
57062306a36Sopenharmony_ci	 */
57162306a36Sopenharmony_ci	skb_trim(entry->skb, rx_pkt_len);
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	/*
57462306a36Sopenharmony_ci	 * Process the RXWI structure.
57562306a36Sopenharmony_ci	 */
57662306a36Sopenharmony_ci	rt2800_process_rxwi(entry, rxdesc);
57762306a36Sopenharmony_ci}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci/*
58062306a36Sopenharmony_ci * Device probe functions.
58162306a36Sopenharmony_ci */
58262306a36Sopenharmony_cistatic int rt2800usb_efuse_detect(struct rt2x00_dev *rt2x00dev)
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	int retval;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	retval = rt2800usb_autorun_detect(rt2x00dev);
58762306a36Sopenharmony_ci	if (retval < 0)
58862306a36Sopenharmony_ci		return retval;
58962306a36Sopenharmony_ci	if (retval)
59062306a36Sopenharmony_ci		return 1;
59162306a36Sopenharmony_ci	return rt2800_efuse_detect(rt2x00dev);
59262306a36Sopenharmony_ci}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_cistatic int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	int retval;
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	retval = rt2800usb_efuse_detect(rt2x00dev);
59962306a36Sopenharmony_ci	if (retval < 0)
60062306a36Sopenharmony_ci		return retval;
60162306a36Sopenharmony_ci	if (retval)
60262306a36Sopenharmony_ci		retval = rt2800_read_eeprom_efuse(rt2x00dev);
60362306a36Sopenharmony_ci	else
60462306a36Sopenharmony_ci		retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
60562306a36Sopenharmony_ci					       EEPROM_SIZE);
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	return retval;
60862306a36Sopenharmony_ci}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_cistatic int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci	int retval;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	retval = rt2800_probe_hw(rt2x00dev);
61562306a36Sopenharmony_ci	if (retval)
61662306a36Sopenharmony_ci		return retval;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	/*
61962306a36Sopenharmony_ci	 * Set txstatus timer function.
62062306a36Sopenharmony_ci	 */
62162306a36Sopenharmony_ci	rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	/*
62462306a36Sopenharmony_ci	 * Overwrite TX done handler
62562306a36Sopenharmony_ci	 */
62662306a36Sopenharmony_ci	INIT_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	return 0;
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_cistatic const struct ieee80211_ops rt2800usb_mac80211_ops = {
63262306a36Sopenharmony_ci	.tx			= rt2x00mac_tx,
63362306a36Sopenharmony_ci	.wake_tx_queue		= ieee80211_handle_wake_tx_queue,
63462306a36Sopenharmony_ci	.start			= rt2x00mac_start,
63562306a36Sopenharmony_ci	.stop			= rt2x00mac_stop,
63662306a36Sopenharmony_ci	.add_interface		= rt2x00mac_add_interface,
63762306a36Sopenharmony_ci	.remove_interface	= rt2x00mac_remove_interface,
63862306a36Sopenharmony_ci	.config			= rt2x00mac_config,
63962306a36Sopenharmony_ci	.configure_filter	= rt2x00mac_configure_filter,
64062306a36Sopenharmony_ci	.set_tim		= rt2x00mac_set_tim,
64162306a36Sopenharmony_ci	.set_key		= rt2x00mac_set_key,
64262306a36Sopenharmony_ci	.sw_scan_start		= rt2x00mac_sw_scan_start,
64362306a36Sopenharmony_ci	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
64462306a36Sopenharmony_ci	.get_stats		= rt2x00mac_get_stats,
64562306a36Sopenharmony_ci	.get_key_seq		= rt2800_get_key_seq,
64662306a36Sopenharmony_ci	.set_rts_threshold	= rt2800_set_rts_threshold,
64762306a36Sopenharmony_ci	.sta_add		= rt2800_sta_add,
64862306a36Sopenharmony_ci	.sta_remove		= rt2800_sta_remove,
64962306a36Sopenharmony_ci	.bss_info_changed	= rt2x00mac_bss_info_changed,
65062306a36Sopenharmony_ci	.conf_tx		= rt2800_conf_tx,
65162306a36Sopenharmony_ci	.get_tsf		= rt2800_get_tsf,
65262306a36Sopenharmony_ci	.rfkill_poll		= rt2x00mac_rfkill_poll,
65362306a36Sopenharmony_ci	.ampdu_action		= rt2800_ampdu_action,
65462306a36Sopenharmony_ci	.flush			= rt2x00mac_flush,
65562306a36Sopenharmony_ci	.get_survey		= rt2800_get_survey,
65662306a36Sopenharmony_ci	.get_ringparam		= rt2x00mac_get_ringparam,
65762306a36Sopenharmony_ci	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
65862306a36Sopenharmony_ci	.reconfig_complete	= rt2x00mac_reconfig_complete,
65962306a36Sopenharmony_ci};
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_cistatic const struct rt2800_ops rt2800usb_rt2800_ops = {
66262306a36Sopenharmony_ci	.register_read		= rt2x00usb_register_read,
66362306a36Sopenharmony_ci	.register_read_lock	= rt2x00usb_register_read_lock,
66462306a36Sopenharmony_ci	.register_write		= rt2x00usb_register_write,
66562306a36Sopenharmony_ci	.register_write_lock	= rt2x00usb_register_write_lock,
66662306a36Sopenharmony_ci	.register_multiread	= rt2x00usb_register_multiread,
66762306a36Sopenharmony_ci	.register_multiwrite	= rt2x00usb_register_multiwrite,
66862306a36Sopenharmony_ci	.regbusy_read		= rt2x00usb_regbusy_read,
66962306a36Sopenharmony_ci	.read_eeprom		= rt2800usb_read_eeprom,
67062306a36Sopenharmony_ci	.hwcrypt_disabled	= rt2800usb_hwcrypt_disabled,
67162306a36Sopenharmony_ci	.drv_write_firmware	= rt2800usb_write_firmware,
67262306a36Sopenharmony_ci	.drv_init_registers	= rt2800usb_init_registers,
67362306a36Sopenharmony_ci	.drv_get_txwi		= rt2800usb_get_txwi,
67462306a36Sopenharmony_ci	.drv_get_dma_done	= rt2800usb_get_dma_done,
67562306a36Sopenharmony_ci};
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_cistatic const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
67862306a36Sopenharmony_ci	.probe_hw		= rt2800usb_probe_hw,
67962306a36Sopenharmony_ci	.get_firmware_name	= rt2800usb_get_firmware_name,
68062306a36Sopenharmony_ci	.check_firmware		= rt2800_check_firmware,
68162306a36Sopenharmony_ci	.load_firmware		= rt2800_load_firmware,
68262306a36Sopenharmony_ci	.initialize		= rt2x00usb_initialize,
68362306a36Sopenharmony_ci	.uninitialize		= rt2x00usb_uninitialize,
68462306a36Sopenharmony_ci	.clear_entry		= rt2x00usb_clear_entry,
68562306a36Sopenharmony_ci	.set_device_state	= rt2800usb_set_device_state,
68662306a36Sopenharmony_ci	.rfkill_poll		= rt2800_rfkill_poll,
68762306a36Sopenharmony_ci	.link_stats		= rt2800_link_stats,
68862306a36Sopenharmony_ci	.reset_tuner		= rt2800_reset_tuner,
68962306a36Sopenharmony_ci	.link_tuner		= rt2800_link_tuner,
69062306a36Sopenharmony_ci	.gain_calibration	= rt2800_gain_calibration,
69162306a36Sopenharmony_ci	.vco_calibration	= rt2800_vco_calibration,
69262306a36Sopenharmony_ci	.watchdog		= rt2800_watchdog,
69362306a36Sopenharmony_ci	.start_queue		= rt2800usb_start_queue,
69462306a36Sopenharmony_ci	.kick_queue		= rt2x00usb_kick_queue,
69562306a36Sopenharmony_ci	.stop_queue		= rt2800usb_stop_queue,
69662306a36Sopenharmony_ci	.flush_queue		= rt2x00usb_flush_queue,
69762306a36Sopenharmony_ci	.tx_dma_done		= rt2800usb_tx_dma_done,
69862306a36Sopenharmony_ci	.write_tx_desc		= rt2800usb_write_tx_desc,
69962306a36Sopenharmony_ci	.write_tx_data		= rt2800_write_tx_data,
70062306a36Sopenharmony_ci	.write_beacon		= rt2800_write_beacon,
70162306a36Sopenharmony_ci	.clear_beacon		= rt2800_clear_beacon,
70262306a36Sopenharmony_ci	.get_tx_data_len	= rt2800usb_get_tx_data_len,
70362306a36Sopenharmony_ci	.fill_rxdone		= rt2800usb_fill_rxdone,
70462306a36Sopenharmony_ci	.config_shared_key	= rt2800_config_shared_key,
70562306a36Sopenharmony_ci	.config_pairwise_key	= rt2800_config_pairwise_key,
70662306a36Sopenharmony_ci	.config_filter		= rt2800_config_filter,
70762306a36Sopenharmony_ci	.config_intf		= rt2800_config_intf,
70862306a36Sopenharmony_ci	.config_erp		= rt2800_config_erp,
70962306a36Sopenharmony_ci	.config_ant		= rt2800_config_ant,
71062306a36Sopenharmony_ci	.config			= rt2800_config,
71162306a36Sopenharmony_ci	.pre_reset_hw		= rt2800_pre_reset_hw,
71262306a36Sopenharmony_ci};
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cistatic void rt2800usb_queue_init(struct data_queue *queue)
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
71762306a36Sopenharmony_ci	unsigned short txwi_size, rxwi_size;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size);
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	switch (queue->qid) {
72262306a36Sopenharmony_ci	case QID_RX:
72362306a36Sopenharmony_ci		queue->limit = 128;
72462306a36Sopenharmony_ci		queue->data_size = AGGREGATION_SIZE;
72562306a36Sopenharmony_ci		queue->desc_size = RXINFO_DESC_SIZE;
72662306a36Sopenharmony_ci		queue->winfo_size = rxwi_size;
72762306a36Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb);
72862306a36Sopenharmony_ci		break;
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	case QID_AC_VO:
73162306a36Sopenharmony_ci	case QID_AC_VI:
73262306a36Sopenharmony_ci	case QID_AC_BE:
73362306a36Sopenharmony_ci	case QID_AC_BK:
73462306a36Sopenharmony_ci		queue->limit = 16;
73562306a36Sopenharmony_ci		queue->data_size = AGGREGATION_SIZE;
73662306a36Sopenharmony_ci		queue->desc_size = TXINFO_DESC_SIZE;
73762306a36Sopenharmony_ci		queue->winfo_size = txwi_size;
73862306a36Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb);
73962306a36Sopenharmony_ci		break;
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	case QID_BEACON:
74262306a36Sopenharmony_ci		queue->limit = 8;
74362306a36Sopenharmony_ci		queue->data_size = MGMT_FRAME_SIZE;
74462306a36Sopenharmony_ci		queue->desc_size = TXINFO_DESC_SIZE;
74562306a36Sopenharmony_ci		queue->winfo_size = txwi_size;
74662306a36Sopenharmony_ci		queue->priv_size = sizeof(struct queue_entry_priv_usb);
74762306a36Sopenharmony_ci		break;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	case QID_ATIM:
75062306a36Sopenharmony_ci	default:
75162306a36Sopenharmony_ci		BUG();
75262306a36Sopenharmony_ci		break;
75362306a36Sopenharmony_ci	}
75462306a36Sopenharmony_ci}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_cistatic const struct rt2x00_ops rt2800usb_ops = {
75762306a36Sopenharmony_ci	.name			= KBUILD_MODNAME,
75862306a36Sopenharmony_ci	.drv_data_size		= sizeof(struct rt2800_drv_data),
75962306a36Sopenharmony_ci	.max_ap_intf		= 8,
76062306a36Sopenharmony_ci	.eeprom_size		= EEPROM_SIZE,
76162306a36Sopenharmony_ci	.rf_size		= RF_SIZE,
76262306a36Sopenharmony_ci	.tx_queues		= NUM_TX_QUEUES,
76362306a36Sopenharmony_ci	.queue_init		= rt2800usb_queue_init,
76462306a36Sopenharmony_ci	.lib			= &rt2800usb_rt2x00_ops,
76562306a36Sopenharmony_ci	.drv			= &rt2800usb_rt2800_ops,
76662306a36Sopenharmony_ci	.hw			= &rt2800usb_mac80211_ops,
76762306a36Sopenharmony_ci#ifdef CONFIG_RT2X00_LIB_DEBUGFS
76862306a36Sopenharmony_ci	.debugfs		= &rt2800_rt2x00debug,
76962306a36Sopenharmony_ci#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
77062306a36Sopenharmony_ci};
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci/*
77362306a36Sopenharmony_ci * rt2800usb module information.
77462306a36Sopenharmony_ci */
77562306a36Sopenharmony_cistatic const struct usb_device_id rt2800usb_device_table[] = {
77662306a36Sopenharmony_ci	/* Abocom */
77762306a36Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0x2870) },
77862306a36Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0x2770) },
77962306a36Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0x3070) },
78062306a36Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0x3071) },
78162306a36Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0x3072) },
78262306a36Sopenharmony_ci	{ USB_DEVICE(0x1482, 0x3c09) },
78362306a36Sopenharmony_ci	/* AirTies */
78462306a36Sopenharmony_ci	{ USB_DEVICE(0x1eda, 0x2012) },
78562306a36Sopenharmony_ci	{ USB_DEVICE(0x1eda, 0x2210) },
78662306a36Sopenharmony_ci	{ USB_DEVICE(0x1eda, 0x2310) },
78762306a36Sopenharmony_ci	/* Allwin */
78862306a36Sopenharmony_ci	{ USB_DEVICE(0x8516, 0x2070) },
78962306a36Sopenharmony_ci	{ USB_DEVICE(0x8516, 0x2770) },
79062306a36Sopenharmony_ci	{ USB_DEVICE(0x8516, 0x2870) },
79162306a36Sopenharmony_ci	{ USB_DEVICE(0x8516, 0x3070) },
79262306a36Sopenharmony_ci	{ USB_DEVICE(0x8516, 0x3071) },
79362306a36Sopenharmony_ci	{ USB_DEVICE(0x8516, 0x3072) },
79462306a36Sopenharmony_ci	/* Alpha Networks */
79562306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c06) },
79662306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c07) },
79762306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c09) },
79862306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c12) },
79962306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c23) },
80062306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c25) },
80162306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c27) },
80262306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c28) },
80362306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c2c) },
80462306a36Sopenharmony_ci	/* Amit */
80562306a36Sopenharmony_ci	{ USB_DEVICE(0x15c5, 0x0008) },
80662306a36Sopenharmony_ci	/* Askey */
80762306a36Sopenharmony_ci	{ USB_DEVICE(0x1690, 0x0740) },
80862306a36Sopenharmony_ci	/* ASUS */
80962306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1731) },
81062306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1732) },
81162306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1742) },
81262306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1784) },
81362306a36Sopenharmony_ci	{ USB_DEVICE(0x1761, 0x0b05) },
81462306a36Sopenharmony_ci	/* AzureWave */
81562306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3247) },
81662306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3273) },
81762306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3305) },
81862306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3307) },
81962306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3321) },
82062306a36Sopenharmony_ci	/* Belkin */
82162306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x8053) },
82262306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x805c) },
82362306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x815c) },
82462306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x825a) },
82562306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x825b) },
82662306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x935a) },
82762306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x935b) },
82862306a36Sopenharmony_ci	/* Buffalo */
82962306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x00e8) },
83062306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0158) },
83162306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x015d) },
83262306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x016f) },
83362306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x01a2) },
83462306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x01ee) },
83562306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x01a8) },
83662306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x01fd) },
83762306a36Sopenharmony_ci	/* Corega */
83862306a36Sopenharmony_ci	{ USB_DEVICE(0x07aa, 0x002f) },
83962306a36Sopenharmony_ci	{ USB_DEVICE(0x07aa, 0x003c) },
84062306a36Sopenharmony_ci	{ USB_DEVICE(0x07aa, 0x003f) },
84162306a36Sopenharmony_ci	{ USB_DEVICE(0x18c5, 0x0012) },
84262306a36Sopenharmony_ci	/* D-Link */
84362306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c09) },
84462306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c0a) },
84562306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c0d) },
84662306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c0e) },
84762306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c0f) },
84862306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c11) },
84962306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c13) },
85062306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c15) },
85162306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c16) },
85262306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c17) },
85362306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3317) },
85462306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c1b) },
85562306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c25) },
85662306a36Sopenharmony_ci	/* Draytek */
85762306a36Sopenharmony_ci	{ USB_DEVICE(0x07fa, 0x7712) },
85862306a36Sopenharmony_ci	/* DVICO */
85962306a36Sopenharmony_ci	{ USB_DEVICE(0x0fe9, 0xb307) },
86062306a36Sopenharmony_ci	/* Edimax */
86162306a36Sopenharmony_ci	{ USB_DEVICE(0x7392, 0x4085) },
86262306a36Sopenharmony_ci	{ USB_DEVICE(0x7392, 0x7711) },
86362306a36Sopenharmony_ci	{ USB_DEVICE(0x7392, 0x7717) },
86462306a36Sopenharmony_ci	{ USB_DEVICE(0x7392, 0x7718) },
86562306a36Sopenharmony_ci	{ USB_DEVICE(0x7392, 0x7722) },
86662306a36Sopenharmony_ci	/* Encore */
86762306a36Sopenharmony_ci	{ USB_DEVICE(0x203d, 0x1480) },
86862306a36Sopenharmony_ci	{ USB_DEVICE(0x203d, 0x14a9) },
86962306a36Sopenharmony_ci	/* EnGenius */
87062306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x9701) },
87162306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x9702) },
87262306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x9703) },
87362306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x9705) },
87462306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x9706) },
87562306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x9707) },
87662306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x9708) },
87762306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x9709) },
87862306a36Sopenharmony_ci	/* Gemtek */
87962306a36Sopenharmony_ci	{ USB_DEVICE(0x15a9, 0x0012) },
88062306a36Sopenharmony_ci	/* Gigabyte */
88162306a36Sopenharmony_ci	{ USB_DEVICE(0x1044, 0x800b) },
88262306a36Sopenharmony_ci	{ USB_DEVICE(0x1044, 0x800d) },
88362306a36Sopenharmony_ci	/* Hawking */
88462306a36Sopenharmony_ci	{ USB_DEVICE(0x0e66, 0x0001) },
88562306a36Sopenharmony_ci	{ USB_DEVICE(0x0e66, 0x0003) },
88662306a36Sopenharmony_ci	{ USB_DEVICE(0x0e66, 0x0009) },
88762306a36Sopenharmony_ci	{ USB_DEVICE(0x0e66, 0x000b) },
88862306a36Sopenharmony_ci	{ USB_DEVICE(0x0e66, 0x0013) },
88962306a36Sopenharmony_ci	{ USB_DEVICE(0x0e66, 0x0017) },
89062306a36Sopenharmony_ci	{ USB_DEVICE(0x0e66, 0x0018) },
89162306a36Sopenharmony_ci	/* I-O DATA */
89262306a36Sopenharmony_ci	{ USB_DEVICE(0x04bb, 0x0945) },
89362306a36Sopenharmony_ci	{ USB_DEVICE(0x04bb, 0x0947) },
89462306a36Sopenharmony_ci	{ USB_DEVICE(0x04bb, 0x0948) },
89562306a36Sopenharmony_ci	/* Linksys */
89662306a36Sopenharmony_ci	{ USB_DEVICE(0x13b1, 0x0031) },
89762306a36Sopenharmony_ci	{ USB_DEVICE(0x1737, 0x0070) },
89862306a36Sopenharmony_ci	{ USB_DEVICE(0x1737, 0x0071) },
89962306a36Sopenharmony_ci	{ USB_DEVICE(0x1737, 0x0077) },
90062306a36Sopenharmony_ci	{ USB_DEVICE(0x1737, 0x0078) },
90162306a36Sopenharmony_ci	/* Logitec */
90262306a36Sopenharmony_ci	{ USB_DEVICE(0x0789, 0x0162) },
90362306a36Sopenharmony_ci	{ USB_DEVICE(0x0789, 0x0163) },
90462306a36Sopenharmony_ci	{ USB_DEVICE(0x0789, 0x0164) },
90562306a36Sopenharmony_ci	{ USB_DEVICE(0x0789, 0x0166) },
90662306a36Sopenharmony_ci	/* Motorola */
90762306a36Sopenharmony_ci	{ USB_DEVICE(0x100d, 0x9031) },
90862306a36Sopenharmony_ci	/* MSI */
90962306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x3820) },
91062306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x3821) },
91162306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x3822) },
91262306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x3870) },
91362306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x3871) },
91462306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x6899) },
91562306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x821a) },
91662306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x822a) },
91762306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x822b) },
91862306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x822c) },
91962306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x870a) },
92062306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x871a) },
92162306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x871b) },
92262306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x871c) },
92362306a36Sopenharmony_ci	{ USB_DEVICE(0x0db0, 0x899a) },
92462306a36Sopenharmony_ci	/* Ovislink */
92562306a36Sopenharmony_ci	{ USB_DEVICE(0x1b75, 0x3070) },
92662306a36Sopenharmony_ci	{ USB_DEVICE(0x1b75, 0x3071) },
92762306a36Sopenharmony_ci	{ USB_DEVICE(0x1b75, 0x3072) },
92862306a36Sopenharmony_ci	{ USB_DEVICE(0x1b75, 0xa200) },
92962306a36Sopenharmony_ci	/* Para */
93062306a36Sopenharmony_ci	{ USB_DEVICE(0x20b8, 0x8888) },
93162306a36Sopenharmony_ci	/* Pegatron */
93262306a36Sopenharmony_ci	{ USB_DEVICE(0x1d4d, 0x0002) },
93362306a36Sopenharmony_ci	{ USB_DEVICE(0x1d4d, 0x000c) },
93462306a36Sopenharmony_ci	{ USB_DEVICE(0x1d4d, 0x000e) },
93562306a36Sopenharmony_ci	{ USB_DEVICE(0x1d4d, 0x0011) },
93662306a36Sopenharmony_ci	/* Philips */
93762306a36Sopenharmony_ci	{ USB_DEVICE(0x0471, 0x200f) },
93862306a36Sopenharmony_ci	/* Planex */
93962306a36Sopenharmony_ci	{ USB_DEVICE(0x2019, 0x5201) },
94062306a36Sopenharmony_ci	{ USB_DEVICE(0x2019, 0xab25) },
94162306a36Sopenharmony_ci	{ USB_DEVICE(0x2019, 0xed06) },
94262306a36Sopenharmony_ci	/* Quanta */
94362306a36Sopenharmony_ci	{ USB_DEVICE(0x1a32, 0x0304) },
94462306a36Sopenharmony_ci	/* Ralink */
94562306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x2070) },
94662306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x2770) },
94762306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x2870) },
94862306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x3070) },
94962306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x3071) },
95062306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x3072) },
95162306a36Sopenharmony_ci	/* Samsung */
95262306a36Sopenharmony_ci	{ USB_DEVICE(0x04e8, 0x2018) },
95362306a36Sopenharmony_ci	/* Siemens */
95462306a36Sopenharmony_ci	{ USB_DEVICE(0x129b, 0x1828) },
95562306a36Sopenharmony_ci	/* Sitecom */
95662306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0017) },
95762306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x002b) },
95862306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x002c) },
95962306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x002d) },
96062306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0039) },
96162306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x003b) },
96262306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x003d) },
96362306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x003e) },
96462306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x003f) },
96562306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0040) },
96662306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0042) },
96762306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0047) },
96862306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0048) },
96962306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0051) },
97062306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x005f) },
97162306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0060) },
97262306a36Sopenharmony_ci	/* SMC */
97362306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0x6618) },
97462306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0x7511) },
97562306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0x7512) },
97662306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0x7522) },
97762306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0x8522) },
97862306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xa618) },
97962306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xa701) },
98062306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xa702) },
98162306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xa703) },
98262306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xb522) },
98362306a36Sopenharmony_ci	/* Sparklan */
98462306a36Sopenharmony_ci	{ USB_DEVICE(0x15a9, 0x0006) },
98562306a36Sopenharmony_ci	/* Sweex */
98662306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x0153) },
98762306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x0164) },
98862306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x0302) },
98962306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x0313) },
99062306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x0323) },
99162306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x0324) },
99262306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x1163) },
99362306a36Sopenharmony_ci	/* U-Media */
99462306a36Sopenharmony_ci	{ USB_DEVICE(0x157e, 0x300e) },
99562306a36Sopenharmony_ci	{ USB_DEVICE(0x157e, 0x3013) },
99662306a36Sopenharmony_ci	/* ZCOM */
99762306a36Sopenharmony_ci	{ USB_DEVICE(0x0cde, 0x0022) },
99862306a36Sopenharmony_ci	{ USB_DEVICE(0x0cde, 0x0025) },
99962306a36Sopenharmony_ci	/* Zinwell */
100062306a36Sopenharmony_ci	{ USB_DEVICE(0x5a57, 0x0280) },
100162306a36Sopenharmony_ci	{ USB_DEVICE(0x5a57, 0x0282) },
100262306a36Sopenharmony_ci	{ USB_DEVICE(0x5a57, 0x0283) },
100362306a36Sopenharmony_ci	{ USB_DEVICE(0x5a57, 0x5257) },
100462306a36Sopenharmony_ci	/* Zyxel */
100562306a36Sopenharmony_ci	{ USB_DEVICE(0x0586, 0x3416) },
100662306a36Sopenharmony_ci	{ USB_DEVICE(0x0586, 0x3418) },
100762306a36Sopenharmony_ci	{ USB_DEVICE(0x0586, 0x341a) },
100862306a36Sopenharmony_ci	{ USB_DEVICE(0x0586, 0x341e) },
100962306a36Sopenharmony_ci	{ USB_DEVICE(0x0586, 0x343e) },
101062306a36Sopenharmony_ci#ifdef CONFIG_RT2800USB_RT33XX
101162306a36Sopenharmony_ci	/* Belkin */
101262306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x945b) },
101362306a36Sopenharmony_ci	/* D-Link */
101462306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c17) },
101562306a36Sopenharmony_ci	/* Panasonic */
101662306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xb511) },
101762306a36Sopenharmony_ci	/* Accton/Arcadyan/Epson */
101862306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xb512) },
101962306a36Sopenharmony_ci	/* Philips */
102062306a36Sopenharmony_ci	{ USB_DEVICE(0x0471, 0x20dd) },
102162306a36Sopenharmony_ci	/* Ralink */
102262306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x3370) },
102362306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x8070) },
102462306a36Sopenharmony_ci	/* Sitecom */
102562306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0050) },
102662306a36Sopenharmony_ci	/* Sweex */
102762306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x0163) },
102862306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x0165) },
102962306a36Sopenharmony_ci#endif
103062306a36Sopenharmony_ci#ifdef CONFIG_RT2800USB_RT35XX
103162306a36Sopenharmony_ci	/* Allwin */
103262306a36Sopenharmony_ci	{ USB_DEVICE(0x8516, 0x3572) },
103362306a36Sopenharmony_ci	/* Askey */
103462306a36Sopenharmony_ci	{ USB_DEVICE(0x1690, 0x0744) },
103562306a36Sopenharmony_ci	{ USB_DEVICE(0x1690, 0x0761) },
103662306a36Sopenharmony_ci	{ USB_DEVICE(0x1690, 0x0764) },
103762306a36Sopenharmony_ci	/* ASUS */
103862306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x179d) },
103962306a36Sopenharmony_ci	/* Cisco */
104062306a36Sopenharmony_ci	{ USB_DEVICE(0x167b, 0x4001) },
104162306a36Sopenharmony_ci	/* EnGenius */
104262306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x9801) },
104362306a36Sopenharmony_ci	/* I-O DATA */
104462306a36Sopenharmony_ci	{ USB_DEVICE(0x04bb, 0x0944) },
104562306a36Sopenharmony_ci	/* Linksys */
104662306a36Sopenharmony_ci	{ USB_DEVICE(0x13b1, 0x002f) },
104762306a36Sopenharmony_ci	{ USB_DEVICE(0x1737, 0x0079) },
104862306a36Sopenharmony_ci	/* Logitec */
104962306a36Sopenharmony_ci	{ USB_DEVICE(0x0789, 0x0170) },
105062306a36Sopenharmony_ci	/* Ralink */
105162306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x3572) },
105262306a36Sopenharmony_ci	/* Sitecom */
105362306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0041) },
105462306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0062) },
105562306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0065) },
105662306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0066) },
105762306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0068) },
105862306a36Sopenharmony_ci	/* Toshiba */
105962306a36Sopenharmony_ci	{ USB_DEVICE(0x0930, 0x0a07) },
106062306a36Sopenharmony_ci	/* Zinwell */
106162306a36Sopenharmony_ci	{ USB_DEVICE(0x5a57, 0x0284) },
106262306a36Sopenharmony_ci#endif
106362306a36Sopenharmony_ci#ifdef CONFIG_RT2800USB_RT3573
106462306a36Sopenharmony_ci	/* AirLive */
106562306a36Sopenharmony_ci	{ USB_DEVICE(0x1b75, 0x7733) },
106662306a36Sopenharmony_ci	/* ASUS */
106762306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x17bc) },
106862306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x17ad) },
106962306a36Sopenharmony_ci	/* Belkin */
107062306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x1103) },
107162306a36Sopenharmony_ci	/* Cameo */
107262306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0xf301) },
107362306a36Sopenharmony_ci	/* D-Link */
107462306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c1f) },
107562306a36Sopenharmony_ci	/* Edimax */
107662306a36Sopenharmony_ci	{ USB_DEVICE(0x7392, 0x7733) },
107762306a36Sopenharmony_ci	/* Hawking */
107862306a36Sopenharmony_ci	{ USB_DEVICE(0x0e66, 0x0020) },
107962306a36Sopenharmony_ci	{ USB_DEVICE(0x0e66, 0x0021) },
108062306a36Sopenharmony_ci	/* I-O DATA */
108162306a36Sopenharmony_ci	{ USB_DEVICE(0x04bb, 0x094e) },
108262306a36Sopenharmony_ci	/* Linksys */
108362306a36Sopenharmony_ci	{ USB_DEVICE(0x13b1, 0x003b) },
108462306a36Sopenharmony_ci	/* Logitec */
108562306a36Sopenharmony_ci	{ USB_DEVICE(0x0789, 0x016b) },
108662306a36Sopenharmony_ci	/* NETGEAR */
108762306a36Sopenharmony_ci	{ USB_DEVICE(0x0846, 0x9012) },
108862306a36Sopenharmony_ci	{ USB_DEVICE(0x0846, 0x9013) },
108962306a36Sopenharmony_ci	{ USB_DEVICE(0x0846, 0x9019) },
109062306a36Sopenharmony_ci	/* Planex */
109162306a36Sopenharmony_ci	{ USB_DEVICE(0x2019, 0xed14) },
109262306a36Sopenharmony_ci	{ USB_DEVICE(0x2019, 0xed19) },
109362306a36Sopenharmony_ci	/* Ralink */
109462306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x3573) },
109562306a36Sopenharmony_ci	/* Sitecom */
109662306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0067) },
109762306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x006a) },
109862306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x006e) },
109962306a36Sopenharmony_ci	/* ZyXEL */
110062306a36Sopenharmony_ci	{ USB_DEVICE(0x0586, 0x3421) },
110162306a36Sopenharmony_ci#endif
110262306a36Sopenharmony_ci#ifdef CONFIG_RT2800USB_RT53XX
110362306a36Sopenharmony_ci	/* Arcadyan */
110462306a36Sopenharmony_ci	{ USB_DEVICE(0x043e, 0x7a12) },
110562306a36Sopenharmony_ci	/* ASUS */
110662306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x17e8) },
110762306a36Sopenharmony_ci	/* Azurewave */
110862306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3329) },
110962306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3365) },
111062306a36Sopenharmony_ci	/* D-Link */
111162306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c15) },
111262306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c19) },
111362306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c1c) },
111462306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c1d) },
111562306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c1e) },
111662306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c20) },
111762306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c22) },
111862306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c23) },
111962306a36Sopenharmony_ci	/* LG innotek */
112062306a36Sopenharmony_ci	{ USB_DEVICE(0x043e, 0x7a22) },
112162306a36Sopenharmony_ci	{ USB_DEVICE(0x043e, 0x7a42) },
112262306a36Sopenharmony_ci	/* Panasonic */
112362306a36Sopenharmony_ci	{ USB_DEVICE(0x04da, 0x1801) },
112462306a36Sopenharmony_ci	{ USB_DEVICE(0x04da, 0x1800) },
112562306a36Sopenharmony_ci	{ USB_DEVICE(0x04da, 0x23f6) },
112662306a36Sopenharmony_ci	/* Philips */
112762306a36Sopenharmony_ci	{ USB_DEVICE(0x0471, 0x2104) },
112862306a36Sopenharmony_ci	{ USB_DEVICE(0x0471, 0x2126) },
112962306a36Sopenharmony_ci	{ USB_DEVICE(0x0471, 0x2180) },
113062306a36Sopenharmony_ci	{ USB_DEVICE(0x0471, 0x2181) },
113162306a36Sopenharmony_ci	{ USB_DEVICE(0x0471, 0x2182) },
113262306a36Sopenharmony_ci	/* Ralink */
113362306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x5370) },
113462306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x5372) },
113562306a36Sopenharmony_ci#endif
113662306a36Sopenharmony_ci#ifdef CONFIG_RT2800USB_RT55XX
113762306a36Sopenharmony_ci	/* Arcadyan */
113862306a36Sopenharmony_ci	{ USB_DEVICE(0x043e, 0x7a32) },
113962306a36Sopenharmony_ci	/* AVM GmbH */
114062306a36Sopenharmony_ci	{ USB_DEVICE(0x057c, 0x8501) },
114162306a36Sopenharmony_ci	/* Buffalo */
114262306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0241) },
114362306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0253) },
114462306a36Sopenharmony_ci	/* D-Link */
114562306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c1a) },
114662306a36Sopenharmony_ci	{ USB_DEVICE(0x2001, 0x3c21) },
114762306a36Sopenharmony_ci	/* Proware */
114862306a36Sopenharmony_ci	{ USB_DEVICE(0x043e, 0x7a13) },
114962306a36Sopenharmony_ci	/* Ralink */
115062306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0x5572) },
115162306a36Sopenharmony_ci	/* TRENDnet */
115262306a36Sopenharmony_ci	{ USB_DEVICE(0x20f4, 0x724a) },
115362306a36Sopenharmony_ci#endif
115462306a36Sopenharmony_ci#ifdef CONFIG_RT2800USB_UNKNOWN
115562306a36Sopenharmony_ci	/*
115662306a36Sopenharmony_ci	 * Unclear what kind of devices these are (they aren't supported by the
115762306a36Sopenharmony_ci	 * vendor linux driver).
115862306a36Sopenharmony_ci	 */
115962306a36Sopenharmony_ci	/* Abocom */
116062306a36Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0x3073) },
116162306a36Sopenharmony_ci	{ USB_DEVICE(0x07b8, 0x3074) },
116262306a36Sopenharmony_ci	/* Alpha Networks */
116362306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c08) },
116462306a36Sopenharmony_ci	{ USB_DEVICE(0x14b2, 0x3c11) },
116562306a36Sopenharmony_ci	/* Amigo */
116662306a36Sopenharmony_ci	{ USB_DEVICE(0x0e0b, 0x9031) },
116762306a36Sopenharmony_ci	{ USB_DEVICE(0x0e0b, 0x9041) },
116862306a36Sopenharmony_ci	/* ASUS */
116962306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x166a) },
117062306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1760) },
117162306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1761) },
117262306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x1790) },
117362306a36Sopenharmony_ci	{ USB_DEVICE(0x0b05, 0x17a7) },
117462306a36Sopenharmony_ci	/* AzureWave */
117562306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3262) },
117662306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3284) },
117762306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3322) },
117862306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3340) },
117962306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3399) },
118062306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3400) },
118162306a36Sopenharmony_ci	{ USB_DEVICE(0x13d3, 0x3401) },
118262306a36Sopenharmony_ci	/* Belkin */
118362306a36Sopenharmony_ci	{ USB_DEVICE(0x050d, 0x1003) },
118462306a36Sopenharmony_ci	/* Buffalo */
118562306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x012e) },
118662306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0148) },
118762306a36Sopenharmony_ci	{ USB_DEVICE(0x0411, 0x0150) },
118862306a36Sopenharmony_ci	/* Corega */
118962306a36Sopenharmony_ci	{ USB_DEVICE(0x07aa, 0x0041) },
119062306a36Sopenharmony_ci	{ USB_DEVICE(0x07aa, 0x0042) },
119162306a36Sopenharmony_ci	{ USB_DEVICE(0x18c5, 0x0008) },
119262306a36Sopenharmony_ci	/* D-Link */
119362306a36Sopenharmony_ci	{ USB_DEVICE(0x07d1, 0x3c0b) },
119462306a36Sopenharmony_ci	/* Encore */
119562306a36Sopenharmony_ci	{ USB_DEVICE(0x203d, 0x14a1) },
119662306a36Sopenharmony_ci	/* EnGenius */
119762306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x0600) },
119862306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x0602) },
119962306a36Sopenharmony_ci	/* Gemtek */
120062306a36Sopenharmony_ci	{ USB_DEVICE(0x15a9, 0x0010) },
120162306a36Sopenharmony_ci	/* Gigabyte */
120262306a36Sopenharmony_ci	{ USB_DEVICE(0x1044, 0x800c) },
120362306a36Sopenharmony_ci	/* Hercules */
120462306a36Sopenharmony_ci	{ USB_DEVICE(0x06f8, 0xe036) },
120562306a36Sopenharmony_ci	/* Huawei */
120662306a36Sopenharmony_ci	{ USB_DEVICE(0x148f, 0xf101) },
120762306a36Sopenharmony_ci	/* I-O DATA */
120862306a36Sopenharmony_ci	{ USB_DEVICE(0x04bb, 0x094b) },
120962306a36Sopenharmony_ci	/* LevelOne */
121062306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x0605) },
121162306a36Sopenharmony_ci	{ USB_DEVICE(0x1740, 0x0615) },
121262306a36Sopenharmony_ci	/* Logitec */
121362306a36Sopenharmony_ci	{ USB_DEVICE(0x0789, 0x0168) },
121462306a36Sopenharmony_ci	{ USB_DEVICE(0x0789, 0x0169) },
121562306a36Sopenharmony_ci	/* Motorola */
121662306a36Sopenharmony_ci	{ USB_DEVICE(0x100d, 0x9032) },
121762306a36Sopenharmony_ci	/* Pegatron */
121862306a36Sopenharmony_ci	{ USB_DEVICE(0x05a6, 0x0101) },
121962306a36Sopenharmony_ci	{ USB_DEVICE(0x1d4d, 0x0010) },
122062306a36Sopenharmony_ci	/* Planex */
122162306a36Sopenharmony_ci	{ USB_DEVICE(0x2019, 0xab24) },
122262306a36Sopenharmony_ci	{ USB_DEVICE(0x2019, 0xab29) },
122362306a36Sopenharmony_ci	/* Qcom */
122462306a36Sopenharmony_ci	{ USB_DEVICE(0x18e8, 0x6259) },
122562306a36Sopenharmony_ci	/* RadioShack */
122662306a36Sopenharmony_ci	{ USB_DEVICE(0x08b9, 0x1197) },
122762306a36Sopenharmony_ci	/* Sitecom */
122862306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x003c) },
122962306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x004a) },
123062306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x004d) },
123162306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0053) },
123262306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0069) },
123362306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x006f) },
123462306a36Sopenharmony_ci	{ USB_DEVICE(0x0df6, 0x0078) },
123562306a36Sopenharmony_ci	/* SMC */
123662306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xa512) },
123762306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xc522) },
123862306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xd522) },
123962306a36Sopenharmony_ci	{ USB_DEVICE(0x083a, 0xf511) },
124062306a36Sopenharmony_ci	/* Sweex */
124162306a36Sopenharmony_ci	{ USB_DEVICE(0x177f, 0x0254) },
124262306a36Sopenharmony_ci	/* TP-LINK */
124362306a36Sopenharmony_ci	{ USB_DEVICE(0xf201, 0x5370) },
124462306a36Sopenharmony_ci#endif
124562306a36Sopenharmony_ci	{ 0, }
124662306a36Sopenharmony_ci};
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ciMODULE_AUTHOR(DRV_PROJECT);
124962306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION);
125062306a36Sopenharmony_ciMODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver.");
125162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
125262306a36Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_RT2870);
125362306a36Sopenharmony_ciMODULE_LICENSE("GPL");
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_cistatic int rt2800usb_probe(struct usb_interface *usb_intf,
125662306a36Sopenharmony_ci			   const struct usb_device_id *id)
125762306a36Sopenharmony_ci{
125862306a36Sopenharmony_ci	return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
125962306a36Sopenharmony_ci}
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_cistatic struct usb_driver rt2800usb_driver = {
126262306a36Sopenharmony_ci	.name		= KBUILD_MODNAME,
126362306a36Sopenharmony_ci	.id_table	= rt2800usb_device_table,
126462306a36Sopenharmony_ci	.probe		= rt2800usb_probe,
126562306a36Sopenharmony_ci	.disconnect	= rt2x00usb_disconnect,
126662306a36Sopenharmony_ci	.suspend	= rt2x00usb_suspend,
126762306a36Sopenharmony_ci	.resume		= rt2x00usb_resume,
126862306a36Sopenharmony_ci	.reset_resume	= rt2x00usb_resume,
126962306a36Sopenharmony_ci	.disable_hub_initiated_lpm = 1,
127062306a36Sopenharmony_ci};
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_cimodule_usb_driver(rt2800usb_driver);
1273