usb.c 9.2 KB
Newer Older
S
Stanislaw Gruszka 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>

#include "mt76x0.h"
19
#include "mcu.h"
S
Stanislaw Gruszka 已提交
20
#include "trace.h"
21
#include "../mt76x02_util.h"
22
#include "../mt76x02_usb.h"
S
Stanislaw Gruszka 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

static struct usb_device_id mt76x0_device_table[] = {
	{ USB_DEVICE(0x148F, 0x7610) },	/* MT7610U */
	{ USB_DEVICE(0x13B1, 0x003E) },	/* Linksys AE6000 */
	{ USB_DEVICE(0x0E8D, 0x7610) },	/* Sabrent NTWLAC */
	{ USB_DEVICE(0x7392, 0xa711) },	/* Edimax 7711mac */
	{ USB_DEVICE(0x7392, 0xb711) },	/* Edimax / Elecom  */
	{ USB_DEVICE(0x148f, 0x761a) },	/* TP-Link TL-WDN5200 */
	{ USB_DEVICE(0x148f, 0x760a) },	/* TP-Link unknown */
	{ USB_DEVICE(0x0b05, 0x17d1) },	/* Asus USB-AC51 */
	{ USB_DEVICE(0x0b05, 0x17db) },	/* Asus USB-AC50 */
	{ USB_DEVICE(0x0df6, 0x0075) },	/* Sitecom WLA-3100 */
	{ USB_DEVICE(0x2019, 0xab31) },	/* Planex GW-450D */
	{ USB_DEVICE(0x2001, 0x3d02) },	/* D-LINK DWA-171 rev B1 */
	{ USB_DEVICE(0x0586, 0x3425) },	/* Zyxel NWD6505 */
	{ USB_DEVICE(0x07b8, 0x7610) },	/* AboCom AU7212 */
	{ USB_DEVICE(0x04bb, 0x0951) },	/* I-O DATA WN-AC433UK */
	{ USB_DEVICE(0x057c, 0x8502) },	/* AVM FRITZ!WLAN USB Stick AC 430 */
	{ USB_DEVICE(0x293c, 0x5702) },	/* Comcast Xfinity KXW02AAA  */
	{ USB_DEVICE(0x20f4, 0x806b) },	/* TRENDnet TEW-806UBH  */
	{ USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */
	{ USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac  Stick */
45 46
	{ USB_DEVICE(0x2357, 0x0105),
	  .driver_info = 1,	     }, /* TP-LINK Archer T1U */
S
Stanislaw Gruszka 已提交
47 48 49 50 51
	{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7630, 0xff, 0x2, 0xff)}, /* MT7630U */
	{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7650, 0xff, 0x2, 0xff)}, /* MT7650U */
	{ 0, }
};

52
static void mt76x0_init_usb_dma(struct mt76x02_dev *dev)
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
{
	u32 val;

	val = mt76_rr(dev, MT_USB_DMA_CFG);

	val |= MT_USB_DMA_CFG_RX_BULK_EN |
	       MT_USB_DMA_CFG_TX_BULK_EN;

	/* disable AGGR_BULK_RX in order to receive one
	 * frame in each rx urb and avoid copies
	 */
	val &= ~MT_USB_DMA_CFG_RX_BULK_AGG_EN;
	mt76_wr(dev, MT_USB_DMA_CFG, val);

	val = mt76_rr(dev, MT_COM_REG0);
	if (val & 1)
		dev_dbg(dev->mt76.dev, "MCU not ready\n");

	val = mt76_rr(dev, MT_USB_DMA_CFG);

	val |= MT_USB_DMA_CFG_RX_DROP_OR_PAD;
	mt76_wr(dev, MT_USB_DMA_CFG, val);
	val &= ~MT_USB_DMA_CFG_RX_DROP_OR_PAD;
	mt76_wr(dev, MT_USB_DMA_CFG, val);
}

79
static void mt76x0u_cleanup(struct mt76x02_dev *dev)
80 81 82 83 84 85 86
{
	clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
	mt76x0_chip_onoff(dev, false, false);
	mt76u_queues_deinit(&dev->mt76);
	mt76u_mcu_deinit(&dev->mt76);
}

87
static void mt76x0u_mac_stop(struct mt76x02_dev *dev)
88 89 90 91 92 93
{
	clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
	cancel_delayed_work_sync(&dev->cal_work);
	cancel_delayed_work_sync(&dev->mac_work);
	mt76u_stop_stat_wk(&dev->mt76);

94 95 96
	if (test_bit(MT76_REMOVED, &dev->mt76.state))
		return;

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
	mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
		   MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
		   MT_BEACON_TIME_CFG_BEACON_TX);

	if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
		dev_warn(dev->mt76.dev, "TX DMA did not stop\n");

	mt76x0_mac_stop(dev);

	if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
		dev_warn(dev->mt76.dev, "RX DMA did not stop\n");
}

static int mt76x0u_start(struct ieee80211_hw *hw)
{
112
	struct mt76x02_dev *dev = hw->priv;
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
	int ret;

	mutex_lock(&dev->mt76.mutex);

	ret = mt76x0_mac_start(dev);
	if (ret)
		goto out;

	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
				     MT_CALIBRATE_INTERVAL);
	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
				     MT_CALIBRATE_INTERVAL);
	set_bit(MT76_STATE_RUNNING, &dev->mt76.state);

out:
	mutex_unlock(&dev->mt76.mutex);
	return ret;
}

static void mt76x0u_stop(struct ieee80211_hw *hw)
{
134
	struct mt76x02_dev *dev = hw->priv;
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

	mutex_lock(&dev->mt76.mutex);
	mt76x0u_mac_stop(dev);
	mutex_unlock(&dev->mt76.mutex);
}

static const struct ieee80211_ops mt76x0u_ops = {
	.tx = mt76x0_tx,
	.start = mt76x0u_start,
	.stop = mt76x0u_stop,
	.add_interface = mt76x02_add_interface,
	.remove_interface = mt76x02_remove_interface,
	.config = mt76x0_config,
	.configure_filter = mt76x02_configure_filter,
	.bss_info_changed = mt76x0_bss_info_changed,
	.sta_add = mt76x02_sta_add,
	.sta_remove = mt76x02_sta_remove,
	.set_key = mt76x02_set_key,
	.conf_tx = mt76x02_conf_tx,
	.sw_scan_start = mt76x0_sw_scan,
	.sw_scan_complete = mt76x0_sw_scan_complete,
	.ampdu_action = mt76x02_ampdu_action,
	.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
	.set_rts_threshold = mt76x0_set_rts_threshold,
	.wake_tx_queue = mt76_wake_tx_queue,
};

162
static int mt76x0u_register_device(struct mt76x02_dev *dev)
163 164 165 166
{
	struct ieee80211_hw *hw = dev->mt76.hw;
	int err;

167
	err = mt76u_alloc_queues(&dev->mt76);
168
	if (err < 0)
169
		goto out_err;
170

171
	err = mt76u_mcu_init_rx(&dev->mt76);
172
	if (err < 0)
173
		goto out_err;
174 175 176 177

	mt76x0_chip_onoff(dev, true, true);
	if (!mt76x02_wait_for_mac(&dev->mt76)) {
		err = -ETIMEDOUT;
178
		goto out_err;
179 180 181 182
	}

	err = mt76x0u_mcu_init(dev);
	if (err < 0)
183
		goto out_err;
184 185 186 187

	mt76x0_init_usb_dma(dev);
	err = mt76x0_init_hardware(dev);
	if (err < 0)
188
		goto out_err;
189 190 191 192 193 194 195 196

	mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
	mt76_wr(dev, MT_TXOP_CTRL_CFG,
		FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
		FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));

	err = mt76x0_register_device(dev);
	if (err < 0)
197
		goto out_err;
198 199 200 201 202 203 204 205 206 207 208

	/* check hw sg support in order to enable AMSDU */
	if (mt76u_check_sg(&dev->mt76))
		hw->max_tx_fragments = MT_SG_MAX_SIZE;
	else
		hw->max_tx_fragments = 1;

	set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);

	return 0;

209
out_err:
210 211 212 213
	mt76x0u_cleanup(dev);
	return err;
}

214
static int mt76x0u_probe(struct usb_interface *usb_intf,
S
Stanislaw Gruszka 已提交
215 216
			 const struct usb_device_id *id)
{
217
	static const struct mt76_driver_ops drv_ops = {
218
		.tx_prepare_skb = mt76x02u_tx_prepare_skb,
219 220 221 222
		.tx_complete_skb = mt76x02_tx_complete_skb,
		.tx_status_data = mt76x02_tx_status_data,
		.rx_skb = mt76x0_queue_rx_skb,
	};
S
Stanislaw Gruszka 已提交
223
	struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
224
	struct mt76x02_dev *dev;
S
Stanislaw Gruszka 已提交
225 226 227
	u32 asic_rev, mac_rev;
	int ret;

228 229
	dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops,
				  &mt76x0u_ops);
S
Stanislaw Gruszka 已提交
230 231 232
	if (!dev)
		return -ENOMEM;

233 234 235 236
	/* Quirk for Archer T1U */
	if (id->driver_info)
		dev->no_2ghz = true;

S
Stanislaw Gruszka 已提交
237 238 239 240 241
	usb_dev = usb_get_dev(usb_dev);
	usb_reset_device(usb_dev);

	usb_set_intfdata(usb_intf, dev);

242
	mt76x02u_init_mcu(&dev->mt76);
243
	ret = mt76u_init(&dev->mt76, usb_intf);
S
Stanislaw Gruszka 已提交
244 245
	if (ret)
		goto err;
246 247 248 249

	/* Disable the HW, otherwise MCU fail to initalize on hot reboot */
	mt76x0_chip_onoff(dev, false, false);

S
Stanislaw Gruszka 已提交
250 251
	if (!mt76x02_wait_for_mac(&dev->mt76)) {
		ret = -ETIMEDOUT;
S
Stanislaw Gruszka 已提交
252
		goto err;
S
Stanislaw Gruszka 已提交
253
	}
S
Stanislaw Gruszka 已提交
254 255 256 257 258 259 260 261 262 263

	asic_rev = mt76_rr(dev, MT_ASIC_VERSION);
	mac_rev = mt76_rr(dev, MT_MAC_CSR0);
	dev_info(dev->mt76.dev, "ASIC revision: %08x MAC revision: %08x\n",
		 asic_rev, mac_rev);

	/* Note: vendor driver skips this check for MT76X0U */
	if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
		dev_warn(dev->mt76.dev, "Warning: eFUSE not present\n");

264
	ret = mt76x0u_register_device(dev);
265 266 267
	if (ret < 0)
		goto err;

S
Stanislaw Gruszka 已提交
268
	return 0;
269

S
Stanislaw Gruszka 已提交
270 271 272 273 274 275 276 277 278 279
err:
	usb_set_intfdata(usb_intf, NULL);
	usb_put_dev(interface_to_usbdev(usb_intf));

	ieee80211_free_hw(dev->mt76.hw);
	return ret;
}

static void mt76x0_disconnect(struct usb_interface *usb_intf)
{
280
	struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
S
Stanislaw Gruszka 已提交
281 282 283 284 285 286
	bool initalized = test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);

	if (!initalized)
		return;

	ieee80211_unregister_hw(dev->mt76.hw);
287
	mt76x0u_cleanup(dev);
S
Stanislaw Gruszka 已提交
288 289 290 291 292 293 294

	usb_set_intfdata(usb_intf, NULL);
	usb_put_dev(interface_to_usbdev(usb_intf));

	ieee80211_free_hw(dev->mt76.hw);
}

295 296
static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
					 pm_message_t state)
S
Stanislaw Gruszka 已提交
297
{
298
	struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
299
	struct mt76_usb *usb = &dev->mt76.usb;
S
Stanislaw Gruszka 已提交
300

301
	mt76u_stop_queues(&dev->mt76);
302
	mt76x0u_mac_stop(dev);
303
	usb_kill_urb(usb->mcu.res.urb);
S
Stanislaw Gruszka 已提交
304 305 306 307

	return 0;
}

308
static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
S
Stanislaw Gruszka 已提交
309
{
310
	struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
311
	struct mt76_usb *usb = &dev->mt76.usb;
S
Stanislaw Gruszka 已提交
312 313
	int ret;

314 315 316 317 318 319 320 321
	reinit_completion(&usb->mcu.cmpl);
	ret = mt76u_submit_buf(&dev->mt76, USB_DIR_IN,
			       MT_EP_IN_CMD_RESP,
			       &usb->mcu.res, GFP_KERNEL,
			       mt76u_mcu_complete_urb,
			       &usb->mcu.cmpl);
	if (ret < 0)
		goto err;
S
Stanislaw Gruszka 已提交
322

323 324 325 326 327 328 329 330 331 332
	ret = mt76u_submit_rx_buffers(&dev->mt76);
	if (ret < 0)
		goto err;

	tasklet_enable(&usb->rx_tasklet);
	tasklet_enable(&usb->tx_tasklet);

	ret = mt76x0_init_hardware(dev);
	if (ret)
		goto err;
S
Stanislaw Gruszka 已提交
333 334

	return 0;
335
err:
336
	mt76x0u_cleanup(dev);
337
	return ret;
S
Stanislaw Gruszka 已提交
338 339 340 341 342 343 344 345
}

MODULE_DEVICE_TABLE(usb, mt76x0_device_table);
MODULE_LICENSE("GPL");

static struct usb_driver mt76x0_driver = {
	.name		= KBUILD_MODNAME,
	.id_table	= mt76x0_device_table,
346
	.probe		= mt76x0u_probe,
S
Stanislaw Gruszka 已提交
347 348 349 350 351 352 353 354
	.disconnect	= mt76x0_disconnect,
	.suspend	= mt76x0_suspend,
	.resume		= mt76x0_resume,
	.reset_resume	= mt76x0_resume,
	.soft_unbind	= 1,
	.disable_hub_initiated_lpm = 1,
};
module_usb_driver(mt76x0_driver);