cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

usb.c (9841B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
      4 */
      5
      6#include <linux/kernel.h>
      7#include <linux/module.h>
      8#include <linux/usb.h>
      9
     10#include "mt7601u.h"
     11#include "usb.h"
     12#include "trace.h"
     13
     14static const struct usb_device_id mt7601u_device_table[] = {
     15	{ USB_DEVICE(0x0b05, 0x17d3) },
     16	{ USB_DEVICE(0x0e8d, 0x760a) },
     17	{ USB_DEVICE(0x0e8d, 0x760b) },
     18	{ USB_DEVICE(0x13d3, 0x3431) },
     19	{ USB_DEVICE(0x13d3, 0x3434) },
     20	{ USB_DEVICE(0x148f, 0x7601) },
     21	{ USB_DEVICE(0x148f, 0x760a) },
     22	{ USB_DEVICE(0x148f, 0x760b) },
     23	{ USB_DEVICE(0x148f, 0x760c) },
     24	{ USB_DEVICE(0x148f, 0x760d) },
     25	{ USB_DEVICE(0x2001, 0x3d04) },
     26	{ USB_DEVICE(0x2717, 0x4106) },
     27	{ USB_DEVICE(0x2955, 0x0001) },
     28	{ USB_DEVICE(0x2955, 0x1001) },
     29	{ USB_DEVICE(0x2955, 0x1003) },
     30	{ USB_DEVICE(0x2a5f, 0x1000) },
     31	{ USB_DEVICE(0x7392, 0x7710) },
     32	{ 0, }
     33};
     34
     35bool mt7601u_usb_alloc_buf(struct mt7601u_dev *dev, size_t len,
     36			   struct mt7601u_dma_buf *buf)
     37{
     38	struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
     39
     40	buf->len = len;
     41	buf->urb = usb_alloc_urb(0, GFP_KERNEL);
     42	buf->buf = usb_alloc_coherent(usb_dev, buf->len, GFP_KERNEL, &buf->dma);
     43
     44	return !buf->urb || !buf->buf;
     45}
     46
     47void mt7601u_usb_free_buf(struct mt7601u_dev *dev, struct mt7601u_dma_buf *buf)
     48{
     49	struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
     50
     51	usb_free_coherent(usb_dev, buf->len, buf->buf, buf->dma);
     52	usb_free_urb(buf->urb);
     53}
     54
     55int mt7601u_usb_submit_buf(struct mt7601u_dev *dev, int dir, int ep_idx,
     56			   struct mt7601u_dma_buf *buf, gfp_t gfp,
     57			   usb_complete_t complete_fn, void *context)
     58{
     59	struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
     60	unsigned pipe;
     61	int ret;
     62
     63	if (dir == USB_DIR_IN)
     64		pipe = usb_rcvbulkpipe(usb_dev, dev->in_eps[ep_idx]);
     65	else
     66		pipe = usb_sndbulkpipe(usb_dev, dev->out_eps[ep_idx]);
     67
     68	usb_fill_bulk_urb(buf->urb, usb_dev, pipe, buf->buf, buf->len,
     69			  complete_fn, context);
     70	buf->urb->transfer_dma = buf->dma;
     71	buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
     72
     73	trace_mt_submit_urb(dev, buf->urb);
     74	ret = usb_submit_urb(buf->urb, gfp);
     75	if (ret)
     76		dev_err(dev->dev, "Error: submit URB dir:%d ep:%d failed:%d\n",
     77			dir, ep_idx, ret);
     78	return ret;
     79}
     80
     81void mt7601u_complete_urb(struct urb *urb)
     82{
     83	struct completion *cmpl = urb->context;
     84
     85	complete(cmpl);
     86}
     87
     88int mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
     89			   const u8 direction, const u16 val, const u16 offset,
     90			   void *buf, const size_t buflen)
     91{
     92	int i, ret;
     93	struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
     94	const u8 req_type = direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
     95	const unsigned int pipe = (direction == USB_DIR_IN) ?
     96		usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
     97
     98	for (i = 0; i < MT_VEND_REQ_MAX_RETRY; i++) {
     99		ret = usb_control_msg(usb_dev, pipe, req, req_type,
    100				      val, offset, buf, buflen,
    101				      MT_VEND_REQ_TOUT_MS);
    102		trace_mt_vend_req(dev, pipe, req, req_type, val, offset,
    103				  buf, buflen, ret);
    104
    105		if (ret == -ENODEV)
    106			set_bit(MT7601U_STATE_REMOVED, &dev->state);
    107		if (ret >= 0 || ret == -ENODEV)
    108			return ret;
    109
    110		msleep(5);
    111	}
    112
    113	dev_err(dev->dev, "Vendor request req:%02x off:%04x failed:%d\n",
    114		req, offset, ret);
    115
    116	return ret;
    117}
    118
    119void mt7601u_vendor_reset(struct mt7601u_dev *dev)
    120{
    121	mt7601u_vendor_request(dev, MT_VEND_DEV_MODE, USB_DIR_OUT,
    122			       MT_VEND_DEV_MODE_RESET, 0, NULL, 0);
    123}
    124
    125/* should be called with vendor_req_mutex held */
    126static u32 __mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
    127{
    128	int ret;
    129	u32 val = ~0;
    130
    131	WARN_ONCE(offset > USHRT_MAX, "read high off:%08x", offset);
    132
    133	ret = mt7601u_vendor_request(dev, MT_VEND_MULTI_READ, USB_DIR_IN,
    134				     0, offset, dev->vend_buf, MT_VEND_BUF);
    135	if (ret == MT_VEND_BUF)
    136		val = get_unaligned_le32(dev->vend_buf);
    137	else if (ret > 0)
    138		dev_err(dev->dev, "Error: wrong size read:%d off:%08x\n",
    139			ret, offset);
    140
    141	trace_reg_read(dev, offset, val);
    142	return val;
    143}
    144
    145u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
    146{
    147	u32 ret;
    148
    149	mutex_lock(&dev->vendor_req_mutex);
    150	ret = __mt7601u_rr(dev, offset);
    151	mutex_unlock(&dev->vendor_req_mutex);
    152
    153	return ret;
    154}
    155
    156/* should be called with vendor_req_mutex held */
    157static int __mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
    158				      const u16 offset, const u32 val)
    159{
    160	int ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
    161					 val & 0xffff, offset, NULL, 0);
    162	if (!ret)
    163		ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
    164					     val >> 16, offset + 2, NULL, 0);
    165	trace_reg_write(dev, offset, val);
    166	return ret;
    167}
    168
    169int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
    170			     const u16 offset, const u32 val)
    171{
    172	int ret;
    173
    174	mutex_lock(&dev->vendor_req_mutex);
    175	ret = __mt7601u_vendor_single_wr(dev, req, offset, val);
    176	mutex_unlock(&dev->vendor_req_mutex);
    177
    178	return ret;
    179}
    180
    181void mt7601u_wr(struct mt7601u_dev *dev, u32 offset, u32 val)
    182{
    183	WARN_ONCE(offset > USHRT_MAX, "write high off:%08x", offset);
    184
    185	mt7601u_vendor_single_wr(dev, MT_VEND_WRITE, offset, val);
    186}
    187
    188u32 mt7601u_rmw(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
    189{
    190	mutex_lock(&dev->vendor_req_mutex);
    191	val |= __mt7601u_rr(dev, offset) & ~mask;
    192	__mt7601u_vendor_single_wr(dev, MT_VEND_WRITE, offset, val);
    193	mutex_unlock(&dev->vendor_req_mutex);
    194
    195	return val;
    196}
    197
    198u32 mt7601u_rmc(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
    199{
    200	u32 reg;
    201
    202	mutex_lock(&dev->vendor_req_mutex);
    203	reg = __mt7601u_rr(dev, offset);
    204	val |= reg & ~mask;
    205	if (reg != val)
    206		__mt7601u_vendor_single_wr(dev, MT_VEND_WRITE,
    207					   offset, val);
    208	mutex_unlock(&dev->vendor_req_mutex);
    209
    210	return val;
    211}
    212
    213void mt7601u_wr_copy(struct mt7601u_dev *dev, u32 offset,
    214		     const void *data, int len)
    215{
    216	WARN_ONCE(offset & 3, "unaligned write copy off:%08x", offset);
    217	WARN_ONCE(len & 3, "short write copy off:%08x", offset);
    218
    219	mt7601u_burst_write_regs(dev, offset, data, len / 4);
    220}
    221
    222void mt7601u_addr_wr(struct mt7601u_dev *dev, const u32 offset, const u8 *addr)
    223{
    224	mt7601u_wr(dev, offset, get_unaligned_le32(addr));
    225	mt7601u_wr(dev, offset + 4, addr[4] | addr[5] << 8);
    226}
    227
    228static int mt7601u_assign_pipes(struct usb_interface *usb_intf,
    229				struct mt7601u_dev *dev)
    230{
    231	struct usb_endpoint_descriptor *ep_desc;
    232	struct usb_host_interface *intf_desc = usb_intf->cur_altsetting;
    233	unsigned i, ep_i = 0, ep_o = 0;
    234
    235	BUILD_BUG_ON(sizeof(dev->in_eps) < __MT_EP_IN_MAX);
    236	BUILD_BUG_ON(sizeof(dev->out_eps) < __MT_EP_OUT_MAX);
    237
    238	for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
    239		ep_desc = &intf_desc->endpoint[i].desc;
    240
    241		if (usb_endpoint_is_bulk_in(ep_desc) &&
    242		    ep_i++ < __MT_EP_IN_MAX) {
    243			dev->in_eps[ep_i - 1] = usb_endpoint_num(ep_desc);
    244			dev->in_max_packet = usb_endpoint_maxp(ep_desc);
    245			/* Note: this is ignored by usb sub-system but vendor
    246			 *	 code does it. We can drop this at some point.
    247			 */
    248			dev->in_eps[ep_i - 1] |= USB_DIR_IN;
    249		} else if (usb_endpoint_is_bulk_out(ep_desc) &&
    250			   ep_o++ < __MT_EP_OUT_MAX) {
    251			dev->out_eps[ep_o - 1] = usb_endpoint_num(ep_desc);
    252			dev->out_max_packet = usb_endpoint_maxp(ep_desc);
    253		}
    254	}
    255
    256	if (ep_i != __MT_EP_IN_MAX || ep_o != __MT_EP_OUT_MAX) {
    257		dev_err(dev->dev, "Error: wrong pipe number in:%d out:%d\n",
    258			ep_i, ep_o);
    259		return -EINVAL;
    260	}
    261
    262	return 0;
    263}
    264
    265static int mt7601u_probe(struct usb_interface *usb_intf,
    266			 const struct usb_device_id *id)
    267{
    268	struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
    269	struct mt7601u_dev *dev;
    270	u32 asic_rev, mac_rev;
    271	int ret;
    272
    273	dev = mt7601u_alloc_device(&usb_intf->dev);
    274	if (!dev)
    275		return -ENOMEM;
    276
    277	usb_dev = usb_get_dev(usb_dev);
    278	usb_reset_device(usb_dev);
    279
    280	usb_set_intfdata(usb_intf, dev);
    281
    282	dev->vend_buf = devm_kmalloc(dev->dev, MT_VEND_BUF, GFP_KERNEL);
    283	if (!dev->vend_buf) {
    284		ret = -ENOMEM;
    285		goto err;
    286	}
    287
    288	ret = mt7601u_assign_pipes(usb_intf, dev);
    289	if (ret)
    290		goto err;
    291	ret = mt7601u_wait_asic_ready(dev);
    292	if (ret)
    293		goto err;
    294
    295	asic_rev = mt7601u_rr(dev, MT_ASIC_VERSION);
    296	mac_rev = mt7601u_rr(dev, MT_MAC_CSR0);
    297	dev_info(dev->dev, "ASIC revision: %08x MAC revision: %08x\n",
    298		 asic_rev, mac_rev);
    299	if ((asic_rev >> 16) != 0x7601) {
    300		ret = -ENODEV;
    301		goto err;
    302	}
    303
    304	/* Note: vendor driver skips this check for MT7601U */
    305	if (!(mt7601u_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
    306		dev_warn(dev->dev, "Warning: eFUSE not present\n");
    307
    308	ret = mt7601u_init_hardware(dev);
    309	if (ret)
    310		goto err;
    311	ret = mt7601u_register_device(dev);
    312	if (ret)
    313		goto err_hw;
    314
    315	set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
    316
    317	return 0;
    318err_hw:
    319	mt7601u_cleanup(dev);
    320err:
    321	usb_set_intfdata(usb_intf, NULL);
    322	usb_put_dev(interface_to_usbdev(usb_intf));
    323
    324	destroy_workqueue(dev->stat_wq);
    325	ieee80211_free_hw(dev->hw);
    326	return ret;
    327}
    328
    329static void mt7601u_disconnect(struct usb_interface *usb_intf)
    330{
    331	struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
    332
    333	ieee80211_unregister_hw(dev->hw);
    334	mt7601u_cleanup(dev);
    335
    336	usb_set_intfdata(usb_intf, NULL);
    337	usb_put_dev(interface_to_usbdev(usb_intf));
    338
    339	destroy_workqueue(dev->stat_wq);
    340	ieee80211_free_hw(dev->hw);
    341}
    342
    343static int mt7601u_suspend(struct usb_interface *usb_intf, pm_message_t state)
    344{
    345	struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
    346
    347	mt7601u_cleanup(dev);
    348
    349	return 0;
    350}
    351
    352static int mt7601u_resume(struct usb_interface *usb_intf)
    353{
    354	struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
    355	int ret;
    356
    357	ret = mt7601u_init_hardware(dev);
    358	if (ret)
    359		return ret;
    360
    361	set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
    362
    363	return 0;
    364}
    365
    366MODULE_DEVICE_TABLE(usb, mt7601u_device_table);
    367MODULE_FIRMWARE(MT7601U_FIRMWARE);
    368MODULE_LICENSE("GPL");
    369
    370static struct usb_driver mt7601u_driver = {
    371	.name		= KBUILD_MODNAME,
    372	.id_table	= mt7601u_device_table,
    373	.probe		= mt7601u_probe,
    374	.disconnect	= mt7601u_disconnect,
    375	.suspend	= mt7601u_suspend,
    376	.resume		= mt7601u_resume,
    377	.reset_resume	= mt7601u_resume,
    378	.soft_unbind	= 1,
    379	.disable_hub_initiated_lpm = 1,
    380};
    381module_usb_driver(mt7601u_driver);