brintos

brintos / linux-shallow public Read only

0
0
Text · 29.1 KiB · cae4766 Raw
1141 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 3/*4 * Linux device driver for USB based Prism545 *6 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>7 *8 * Based on the islsm (softmac prism54) driver, which is:9 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.10 */11 12#include <linux/usb.h>13#include <linux/pci.h>14#include <linux/slab.h>15#include <linux/firmware.h>16#include <linux/etherdevice.h>17#include <linux/delay.h>18#include <linux/crc32.h>19#include <linux/module.h>20#include <net/mac80211.h>21 22#include "p54.h"23#include "lmac.h"24#include "p54usb.h"25 26MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");27MODULE_DESCRIPTION("Prism54 USB wireless driver");28MODULE_LICENSE("GPL");29MODULE_ALIAS("prism54usb");30MODULE_FIRMWARE("isl3886usb");31MODULE_FIRMWARE("isl3887usb");32 33static struct usb_driver p54u_driver;34 35/*36 * Note:37 *38 * Always update our wiki's device list (located at:39 * http://wireless.wiki.kernel.org/en/users/Drivers/p54/devices ),40 * whenever you add a new device.41 */42 43static const struct usb_device_id p54u_table[] = {44	/* Version 1 devices (pci chip + net2280) */45	{USB_DEVICE(0x0411, 0x0050)},	/* Buffalo WLI2-USB2-G54 */46	{USB_DEVICE(0x045e, 0x00c2)},	/* Microsoft MN-710 */47	{USB_DEVICE(0x0506, 0x0a11)},	/* 3COM 3CRWE254G72 */48	{USB_DEVICE(0x0675, 0x0530)},	/* DrayTek Vigor 530 */49	{USB_DEVICE(0x06b9, 0x0120)},	/* Thomson SpeedTouch 120g */50	{USB_DEVICE(0x0707, 0xee06)},	/* SMC 2862W-G */51	{USB_DEVICE(0x07aa, 0x001c)},	/* Corega CG-WLUSB2GT */52	{USB_DEVICE(0x083a, 0x4501)},	/* Accton 802.11g WN4501 USB */53	{USB_DEVICE(0x083a, 0x4502)},	/* Siemens Gigaset USB Adapter */54	{USB_DEVICE(0x083a, 0x5501)},	/* Phillips CPWUA054 */55	{USB_DEVICE(0x0846, 0x4200)},	/* Netgear WG121 */56	{USB_DEVICE(0x0846, 0x4210)},	/* Netgear WG121 the second ? */57	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */58	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */59	{USB_DEVICE(0x0bf8, 0x1007)},	/* Fujitsu E-5400 USB */60	{USB_DEVICE(0x0cde, 0x0006)},	/* Medion 40900, Roper Europe */61	{USB_DEVICE(0x0db0, 0x6826)},	/* MSI UB54G (MS-6826) */62	{USB_DEVICE(0x107b, 0x55f2)},	/* Gateway WGU-210 (Gemtek) */63	{USB_DEVICE(0x124a, 0x4023)},	/* Shuttle PN15, Airvast WM168g, IOGear GWU513 */64	{USB_DEVICE(0x124a, 0x4026)},	/* AirVasT USB wireless device */65	{USB_DEVICE(0x1435, 0x0210)},	/* Inventel UR054G */66	{USB_DEVICE(0x15a9, 0x0002)},	/* Gemtek WUBI-100GW 802.11g */67	{USB_DEVICE(0x1630, 0x0005)},	/* 2Wire 802.11g USB (v1) / Z-Com */68	{USB_DEVICE(0x182d, 0x096b)},	/* Sitecom WL-107 */69	{USB_DEVICE(0x1915, 0x2234)},	/* Linksys WUSB54G OEM */70	{USB_DEVICE(0x1915, 0x2235)},	/* Linksys WUSB54G Portable OEM */71	{USB_DEVICE(0x2001, 0x3701)},	/* DLink DWL-G120 Spinnaker */72	{USB_DEVICE(0x2001, 0x3703)},	/* DLink DWL-G122 */73	{USB_DEVICE(0x2001, 0x3762)},	/* Conceptronic C54U */74	{USB_DEVICE(0x5041, 0x2234)},	/* Linksys WUSB54G */75	{USB_DEVICE(0x5041, 0x2235)},	/* Linksys WUSB54G Portable */76 77	/* Version 2 devices (3887) */78	{USB_DEVICE(0x0471, 0x1230)},   /* Philips CPWUA054/00 */79	{USB_DEVICE(0x050d, 0x7050)},	/* Belkin F5D7050 ver 1000 */80	{USB_DEVICE(0x0572, 0x2000)},	/* Cohiba Proto board */81	{USB_DEVICE(0x0572, 0x2002)},	/* Cohiba Proto board */82	{USB_DEVICE(0x06a9, 0x000e)},	/* Westell 802.11g USB (A90-211WG-01) */83	{USB_DEVICE(0x06b9, 0x0121)},	/* Thomson SpeedTouch 121g */84	{USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */85	{USB_DEVICE(0x07aa, 0x0020)},	/* Corega WLUSB2GTST USB */86	{USB_DEVICE(0x0803, 0x4310)},	/* Zoom 4410a */87	{USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */88	{USB_DEVICE(0x083a, 0x4531)},	/* T-Com Sinus 154 data II */89	{USB_DEVICE(0x083a, 0xc501)},	/* Zoom Wireless-G 4410 */90	{USB_DEVICE(0x083a, 0xf503)},	/* Accton FD7050E ver 1010ec  */91	{USB_DEVICE(0x0846, 0x4240)},	/* Netgear WG111 (v2) */92	{USB_DEVICE(0x0915, 0x2000)},	/* Cohiba Proto board */93	{USB_DEVICE(0x0915, 0x2002)},	/* Cohiba Proto board */94	{USB_DEVICE(0x0baf, 0x0118)},   /* U.S. Robotics U5 802.11g Adapter*/95	{USB_DEVICE(0x0bf8, 0x1009)},   /* FUJITSU E-5400 USB D1700*/96	/* {USB_DEVICE(0x0cde, 0x0006)}, * Medion MD40900 already listed above,97					 * just noting it here for clarity */98	{USB_DEVICE(0x0cde, 0x0008)},	/* Sagem XG703A */99	{USB_DEVICE(0x0cde, 0x0015)},	/* Zcomax XG-705A */100	{USB_DEVICE(0x0d8e, 0x3762)},	/* DLink DWL-G120 Cohiba */101	{USB_DEVICE(0x124a, 0x4025)},	/* IOGear GWU513 (GW3887IK chip) */102	{USB_DEVICE(0x1260, 0xee22)},	/* SMC 2862W-G version 2 */103	{USB_DEVICE(0x13b1, 0x000a)},	/* Linksys WUSB54G ver 2 */104	{USB_DEVICE(0x13B1, 0x000C)},	/* Linksys WUSB54AG */105	{USB_DEVICE(0x1413, 0x5400)},   /* Telsey 802.11g USB2.0 Adapter */106	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */107	/* {USB_DEVICE(0x15a9, 0x0002)}, * Also SparkLAN WL-682 with 3887 */108	{USB_DEVICE(0x1668, 0x1050)},	/* Actiontec 802UIG-1 */109	{USB_DEVICE(0x1740, 0x1000)},	/* Senao NUB-350 */110	{USB_DEVICE(0x2001, 0x3704)},	/* DLink DWL-G122 rev A2 */111	{USB_DEVICE(0x2001, 0x3705)},	/* D-Link DWL-G120 rev C1 */112	{USB_DEVICE(0x413c, 0x5513)},	/* Dell WLA3310 USB Wireless Adapter */113	{USB_DEVICE(0x413c, 0x8102)},	/* Spinnaker DUT */114	{USB_DEVICE(0x413c, 0x8104)},	/* Cohiba Proto board */115	{}116};117 118MODULE_DEVICE_TABLE(usb, p54u_table);119 120static const struct {121	u32 intf;122	enum p54u_hw_type type;123	const char *fw;124	char hw[20];125} p54u_fwlist[__NUM_P54U_HWTYPES] = {126	{127		.type = P54U_NET2280,128		.intf = FW_LM86,129		.fw = "isl3886usb",130		.hw = "ISL3886 + net2280",131	},132	{133		.type = P54U_3887,134		.intf = FW_LM87,135		.fw = "isl3887usb",136		.hw = "ISL3887",137	},138};139 140static void p54u_rx_cb(struct urb *urb)141{142	struct sk_buff *skb = (struct sk_buff *) urb->context;143	struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;144	struct ieee80211_hw *dev = info->dev;145	struct p54u_priv *priv = dev->priv;146 147	skb_unlink(skb, &priv->rx_queue);148 149	if (unlikely(urb->status)) {150		dev_kfree_skb_irq(skb);151		return;152	}153 154	skb_put(skb, urb->actual_length);155 156	if (priv->hw_type == P54U_NET2280)157		skb_pull(skb, priv->common.tx_hdr_len);158	if (priv->common.fw_interface == FW_LM87) {159		skb_pull(skb, 4);160		skb_put(skb, 4);161	}162 163	if (p54_rx(dev, skb)) {164		skb = dev_alloc_skb(priv->common.rx_mtu + 32);165		if (unlikely(!skb)) {166			/* TODO check rx queue length and refill *somewhere* */167			return;168		}169 170		info = (struct p54u_rx_info *) skb->cb;171		info->urb = urb;172		info->dev = dev;173		urb->transfer_buffer = skb_tail_pointer(skb);174		urb->context = skb;175	} else {176		if (priv->hw_type == P54U_NET2280)177			skb_push(skb, priv->common.tx_hdr_len);178		if (priv->common.fw_interface == FW_LM87) {179			skb_push(skb, 4);180			skb_put(skb, 4);181		}182		skb_reset_tail_pointer(skb);183		skb_trim(skb, 0);184		urb->transfer_buffer = skb_tail_pointer(skb);185	}186	skb_queue_tail(&priv->rx_queue, skb);187	usb_anchor_urb(urb, &priv->submitted);188	if (usb_submit_urb(urb, GFP_ATOMIC)) {189		skb_unlink(skb, &priv->rx_queue);190		usb_unanchor_urb(urb);191		dev_kfree_skb_irq(skb);192	}193}194 195static void p54u_tx_cb(struct urb *urb)196{197	struct sk_buff *skb = urb->context;198	struct ieee80211_hw *dev =199		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));200 201	p54_free_skb(dev, skb);202}203 204static void p54u_tx_dummy_cb(struct urb *urb) { }205 206static void p54u_free_urbs(struct ieee80211_hw *dev)207{208	struct p54u_priv *priv = dev->priv;209	usb_kill_anchored_urbs(&priv->submitted);210}211 212static void p54u_stop(struct ieee80211_hw *dev)213{214	/*215	 * TODO: figure out how to reliably stop the 3887 and net2280 so216	 * the hardware is still usable next time we want to start it.217	 * until then, we just stop listening to the hardware..218	 */219	p54u_free_urbs(dev);220}221 222static int p54u_init_urbs(struct ieee80211_hw *dev)223{224	struct p54u_priv *priv = dev->priv;225	struct urb *entry = NULL;226	struct sk_buff *skb;227	struct p54u_rx_info *info;228	int ret = 0;229 230	while (skb_queue_len(&priv->rx_queue) < 32) {231		skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);232		if (!skb) {233			ret = -ENOMEM;234			goto err;235		}236		entry = usb_alloc_urb(0, GFP_KERNEL);237		if (!entry) {238			ret = -ENOMEM;239			goto err;240		}241 242		usb_fill_bulk_urb(entry, priv->udev,243				  usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),244				  skb_tail_pointer(skb),245				  priv->common.rx_mtu + 32, p54u_rx_cb, skb);246		info = (struct p54u_rx_info *) skb->cb;247		info->urb = entry;248		info->dev = dev;249		skb_queue_tail(&priv->rx_queue, skb);250 251		usb_anchor_urb(entry, &priv->submitted);252		ret = usb_submit_urb(entry, GFP_KERNEL);253		if (ret) {254			skb_unlink(skb, &priv->rx_queue);255			usb_unanchor_urb(entry);256			goto err;257		}258		usb_free_urb(entry);259		entry = NULL;260	}261 262	return 0;263 264 err:265	usb_free_urb(entry);266	kfree_skb(skb);267	p54u_free_urbs(dev);268	return ret;269}270 271static int p54u_open(struct ieee80211_hw *dev)272{273	/*274	 * TODO: Because we don't know how to reliably stop the 3887 and275	 * the isl3886+net2280, other than brutally cut off all276	 * communications. We have to reinitialize the urbs on every start.277	 */278	return p54u_init_urbs(dev);279}280 281static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)282{283	u32 chk = 0;284 285	length >>= 2;286	while (length--) {287		chk ^= le32_to_cpu(*data++);288		chk = (chk >> 5) ^ (chk << 3);289	}290 291	return cpu_to_le32(chk);292}293 294static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)295{296	struct p54u_priv *priv = dev->priv;297	struct urb *data_urb;298	struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);299 300	data_urb = usb_alloc_urb(0, GFP_ATOMIC);301	if (!data_urb) {302		p54_free_skb(dev, skb);303		return;304	}305 306	hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);307	hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;308 309	usb_fill_bulk_urb(data_urb, priv->udev,310			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),311			  hdr, skb->len + sizeof(*hdr),  FREE_AFTER_TX(skb) ?312			  p54u_tx_cb : p54u_tx_dummy_cb, skb);313	data_urb->transfer_flags |= URB_ZERO_PACKET;314 315	usb_anchor_urb(data_urb, &priv->submitted);316	if (usb_submit_urb(data_urb, GFP_ATOMIC)) {317		usb_unanchor_urb(data_urb);318		p54_free_skb(dev, skb);319	}320	usb_free_urb(data_urb);321}322 323static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)324{325	struct p54u_priv *priv = dev->priv;326	struct urb *int_urb = NULL, *data_urb = NULL;327	struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);328	struct net2280_reg_write *reg = NULL;329	int err = -ENOMEM;330 331	reg = kmalloc(sizeof(*reg), GFP_ATOMIC);332	if (!reg)333		goto out;334 335	int_urb = usb_alloc_urb(0, GFP_ATOMIC);336	if (!int_urb)337		goto out;338 339	data_urb = usb_alloc_urb(0, GFP_ATOMIC);340	if (!data_urb)341		goto out;342 343	reg->port = cpu_to_le16(NET2280_DEV_U32);344	reg->addr = cpu_to_le32(P54U_DEV_BASE);345	reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);346 347	memset(hdr, 0, sizeof(*hdr));348	hdr->len = cpu_to_le16(skb->len);349	hdr->device_addr = ((struct p54_hdr *) skb->data)->req_id;350 351	usb_fill_bulk_urb(int_urb, priv->udev,352		usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),353		p54u_tx_dummy_cb, dev);354 355	/*356	 * URB_FREE_BUFFER triggers a code path in the USB subsystem that will357	 * free what is inside the transfer_buffer after the last reference to358	 * the int_urb is dropped.359	 */360	int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET;361	reg = NULL;362 363	usb_fill_bulk_urb(data_urb, priv->udev,364			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),365			  hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?366			  p54u_tx_cb : p54u_tx_dummy_cb, skb);367	data_urb->transfer_flags |= URB_ZERO_PACKET;368 369	usb_anchor_urb(int_urb, &priv->submitted);370	err = usb_submit_urb(int_urb, GFP_ATOMIC);371	if (err) {372		usb_unanchor_urb(int_urb);373		goto out;374	}375 376	usb_anchor_urb(data_urb, &priv->submitted);377	err = usb_submit_urb(data_urb, GFP_ATOMIC);378	if (err) {379		usb_unanchor_urb(data_urb);380		goto out;381	}382out:383	usb_free_urb(int_urb);384	usb_free_urb(data_urb);385 386	if (err) {387		kfree(reg);388		p54_free_skb(dev, skb);389	}390}391 392static int p54u_write(struct p54u_priv *priv,393		      struct net2280_reg_write *buf,394		      enum net2280_op_type type,395		      __le32 addr, __le32 val)396{397	unsigned int ep;398	int alen;399 400	if (type & 0x0800)401		ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);402	else403		ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);404 405	buf->port = cpu_to_le16(type);406	buf->addr = addr;407	buf->val = val;408 409	return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);410}411 412static int p54u_read(struct p54u_priv *priv, void *buf,413		     enum net2280_op_type type,414		     __le32 addr, __le32 *val)415{416	struct net2280_reg_read *read = buf;417	__le32 *reg = buf;418	unsigned int ep;419	int alen, err;420 421	if (type & 0x0800)422		ep = P54U_PIPE_DEV;423	else424		ep = P54U_PIPE_BRG;425 426	read->port = cpu_to_le16(type);427	read->addr = addr;428 429	err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),430			   read, sizeof(*read), &alen, 1000);431	if (err)432		return err;433 434	err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),435			   reg, sizeof(*reg), &alen, 1000);436	if (err)437		return err;438 439	*val = *reg;440	return 0;441}442 443static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,444			 void *data, size_t len)445{446	int alen;447	return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),448			    data, len, &alen, 2000);449}450 451static int p54u_device_reset(struct ieee80211_hw *dev)452{453	struct p54u_priv *priv = dev->priv;454	int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING);455 456	if (lock) {457		ret = usb_lock_device_for_reset(priv->udev, priv->intf);458		if (ret < 0) {459			dev_err(&priv->udev->dev, "(p54usb) unable to lock "460				"device for reset (%d)!\n", ret);461			return ret;462		}463	}464 465	ret = usb_reset_device(priv->udev);466	if (lock)467		usb_unlock_device(priv->udev);468 469	if (ret)470		dev_err(&priv->udev->dev, "(p54usb) unable to reset "471			"device (%d)!\n", ret);472 473	return ret;474}475 476static const char p54u_romboot_3887[] = "~~~~";477static int p54u_firmware_reset_3887(struct ieee80211_hw *dev)478{479	struct p54u_priv *priv = dev->priv;480	u8 *buf;481	int ret;482 483	buf = kmemdup(p54u_romboot_3887, 4, GFP_KERNEL);484	if (!buf)485		return -ENOMEM;486	ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,487			    buf, 4);488	kfree(buf);489	if (ret)490		dev_err(&priv->udev->dev, "(p54usb) unable to jump to "491			"boot ROM (%d)!\n", ret);492 493	return ret;494}495 496static const char p54u_firmware_upload_3887[] = "<\r";497static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)498{499	struct p54u_priv *priv = dev->priv;500	int err, alen;501	u8 carry = 0;502	u8 *buf, *tmp;503	const u8 *data;504	unsigned int left, remains, block_size;505	struct x2_header *hdr;506	unsigned long timeout;507 508	err = p54u_firmware_reset_3887(dev);509	if (err)510		return err;511 512	tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);513	if (!buf)514		return -ENOMEM;515 516	left = block_size = min_t(size_t, P54U_FW_BLOCK, priv->fw->size);517	strcpy(buf, p54u_firmware_upload_3887);518	left -= strlen(p54u_firmware_upload_3887);519	tmp += strlen(p54u_firmware_upload_3887);520 521	data = priv->fw->data;522	remains = priv->fw->size;523 524	hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));525	memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);526	hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);527	hdr->fw_length = cpu_to_le32(priv->fw->size);528	hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,529					 sizeof(u32)*2));530	left -= sizeof(*hdr);531	tmp += sizeof(*hdr);532 533	while (remains) {534		while (left--) {535			if (carry) {536				*tmp++ = carry;537				carry = 0;538				remains--;539				continue;540			}541			switch (*data) {542			case '~':543				*tmp++ = '}';544				carry = '^';545				break;546			case '}':547				*tmp++ = '}';548				carry = ']';549				break;550			default:551				*tmp++ = *data;552				remains--;553				break;554			}555			data++;556		}557 558		err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);559		if (err) {560			dev_err(&priv->udev->dev, "(p54usb) firmware "561						  "upload failed!\n");562			goto err_upload_failed;563		}564 565		tmp = buf;566		left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);567	}568 569	*((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, priv->fw->data,570						 priv->fw->size));571	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));572	if (err) {573		dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");574		goto err_upload_failed;575	}576	timeout = jiffies + msecs_to_jiffies(1000);577	while (!(err = usb_bulk_msg(priv->udev,578		usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {579		if (alen > 2 && !memcmp(buf, "OK", 2))580			break;581 582		if (alen > 5 && !memcmp(buf, "ERROR", 5)) {583			err = -EINVAL;584			break;585		}586 587		if (time_after(jiffies, timeout)) {588			dev_err(&priv->udev->dev, "(p54usb) firmware boot "589						  "timed out!\n");590			err = -ETIMEDOUT;591			break;592		}593	}594	if (err) {595		dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");596		goto err_upload_failed;597	}598 599	buf[0] = 'g';600	buf[1] = '\r';601	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);602	if (err) {603		dev_err(&priv->udev->dev, "(p54usb) firmware boot failed!\n");604		goto err_upload_failed;605	}606 607	timeout = jiffies + msecs_to_jiffies(1000);608	while (!(err = usb_bulk_msg(priv->udev,609		usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {610		if (alen > 0 && buf[0] == 'g')611			break;612 613		if (time_after(jiffies, timeout)) {614			err = -ETIMEDOUT;615			break;616		}617	}618	if (err)619		goto err_upload_failed;620 621err_upload_failed:622	kfree(buf);623	return err;624}625 626static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)627{628	struct p54u_priv *priv = dev->priv;629	const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;630	int err, alen;631	void *buf;632	__le32 reg;633	unsigned int remains, offset;634	const u8 *data;635 636	buf = kmalloc(512, GFP_KERNEL);637	if (!buf)638		return -ENOMEM;639 640#define P54U_WRITE(type, addr, data) \641	do {\642		err = p54u_write(priv, buf, type,\643				 cpu_to_le32((u32)(unsigned long)addr), data);\644		if (err) \645			goto fail;\646	} while (0)647 648#define P54U_READ(type, addr) \649	do {\650		err = p54u_read(priv, buf, type,\651				cpu_to_le32((u32)(unsigned long)addr), &reg);\652		if (err)\653			goto fail;\654	} while (0)655 656	/* power down net2280 bridge */657	P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);658	reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);659	reg &= cpu_to_le32(~P54U_BRG_POWER_UP);660	P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);661 662	mdelay(100);663 664	/* power up bridge */665	reg |= cpu_to_le32(P54U_BRG_POWER_UP);666	reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);667	P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);668 669	mdelay(100);670 671	P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,672		   cpu_to_le32(NET2280_CLK_30Mhz |673			       NET2280_PCI_ENABLE |674			       NET2280_PCI_SOFT_RESET));675 676	mdelay(20);677 678	P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,679		   cpu_to_le32(PCI_COMMAND_MEMORY |680			       PCI_COMMAND_MASTER));681 682	P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,683		   cpu_to_le32(NET2280_BASE));684 685	P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);686	reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);687	P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);688 689	// TODO: we really need this?690	P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);691 692	P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,693		   cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));694	P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,695		   cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));696 697	P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,698		   cpu_to_le32(NET2280_BASE2));699 700	/* finally done setting up the bridge */701 702	P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,703		   cpu_to_le32(PCI_COMMAND_MEMORY |704			       PCI_COMMAND_MASTER));705 706	P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);707	P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,708		   cpu_to_le32(P54U_DEV_BASE));709 710	P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);711	P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,712		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));713 714	/* do romboot */715	P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);716 717	P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);718	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);719	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);720	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);721	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);722 723	mdelay(20);724 725	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);726	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);727 728	mdelay(20);729 730	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);731	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);732 733	mdelay(100);734 735	P54U_READ(NET2280_DEV_U32, &devreg->int_ident);736	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);737 738	/* finally, we can upload firmware now! */739	remains = priv->fw->size;740	data = priv->fw->data;741	offset = ISL38XX_DEV_FIRMWARE_ADDR;742 743	while (remains) {744		unsigned int block_len = min(remains, (unsigned int)512);745		memcpy(buf, data, block_len);746 747		err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);748		if (err) {749			dev_err(&priv->udev->dev, "(p54usb) firmware block "750						  "upload failed\n");751			goto fail;752		}753 754		P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,755			   cpu_to_le32(0xc0000f00));756 757		P54U_WRITE(NET2280_DEV_U32,758			   0x0020 | (unsigned long)&devreg->direct_mem_win, 0);759		P54U_WRITE(NET2280_DEV_U32,760			   0x0020 | (unsigned long)&devreg->direct_mem_win,761			   cpu_to_le32(1));762 763		P54U_WRITE(NET2280_DEV_U32,764			   0x0024 | (unsigned long)&devreg->direct_mem_win,765			   cpu_to_le32(block_len));766		P54U_WRITE(NET2280_DEV_U32,767			   0x0028 | (unsigned long)&devreg->direct_mem_win,768			   cpu_to_le32(offset));769 770		P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,771			   cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));772		P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,773			   cpu_to_le32(block_len >> 2));774		P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,775			   cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));776 777		mdelay(10);778 779		P54U_READ(NET2280_DEV_U32,780			  0x002C | (unsigned long)&devreg->direct_mem_win);781		if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||782		    !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {783			dev_err(&priv->udev->dev, "(p54usb) firmware DMA "784						  "transfer failed\n");785			goto fail;786		}787 788		P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,789			   cpu_to_le32(NET2280_FIFO_FLUSH));790 791		remains -= block_len;792		data += block_len;793		offset += block_len;794	}795 796	/* do ramboot */797	P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);798	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);799	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);800	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);801	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);802 803	mdelay(20);804 805	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);806	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);807 808	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);809	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);810 811	mdelay(100);812 813	P54U_READ(NET2280_DEV_U32, &devreg->int_ident);814	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);815 816	/* start up the firmware */817	P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,818		   cpu_to_le32(ISL38XX_INT_IDENT_INIT));819 820	P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,821		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));822 823	P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,824		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |825			       NET2280_USB_INTERRUPT_ENABLE));826 827	P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,828		   cpu_to_le32(ISL38XX_DEV_INT_RESET));829 830	err = usb_interrupt_msg(priv->udev,831				usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),832				buf, sizeof(__le32), &alen, 1000);833	if (err || alen != sizeof(__le32))834		goto fail;835 836	P54U_READ(NET2280_DEV_U32, &devreg->int_ident);837	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);838 839	if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))840		err = -EINVAL;841 842	P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);843	P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,844		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));845 846#undef P54U_WRITE847#undef P54U_READ848 849fail:850	kfree(buf);851	return err;852}853 854static int p54_find_type(struct p54u_priv *priv)855{856	int i;857 858	for (i = 0; i < __NUM_P54U_HWTYPES; i++)859		if (p54u_fwlist[i].type == priv->hw_type)860			break;861	if (i == __NUM_P54U_HWTYPES)862		return -EOPNOTSUPP;863 864	return i;865}866 867static int p54u_start_ops(struct p54u_priv *priv)868{869	struct ieee80211_hw *dev = priv->common.hw;870	int ret;871 872	ret = p54_parse_firmware(dev, priv->fw);873	if (ret)874		goto err_out;875 876	ret = p54_find_type(priv);877	if (ret < 0)878		goto err_out;879 880	if (priv->common.fw_interface != p54u_fwlist[ret].intf) {881		dev_err(&priv->udev->dev, "wrong firmware, please get "882			"a firmware for \"%s\" and try again.\n",883			p54u_fwlist[ret].hw);884		ret = -ENODEV;885		goto err_out;886	}887 888	ret = priv->upload_fw(dev);889	if (ret)890		goto err_out;891 892	ret = p54u_open(dev);893	if (ret)894		goto err_out;895 896	ret = p54_read_eeprom(dev);897	if (ret)898		goto err_stop;899 900	p54u_stop(dev);901 902	ret = p54_register_common(dev, &priv->udev->dev);903	if (ret)904		goto err_stop;905 906	return 0;907 908err_stop:909	p54u_stop(dev);910 911err_out:912	/*913	 * p54u_disconnect will do the rest of the914	 * cleanup915	 */916	return ret;917}918 919static void p54u_load_firmware_cb(const struct firmware *firmware,920				  void *context)921{922	struct p54u_priv *priv = context;923	struct usb_device *udev = priv->udev;924	struct usb_interface *intf = priv->intf;925	int err;926 927	if (firmware) {928		priv->fw = firmware;929		err = p54u_start_ops(priv);930	} else {931		err = -ENOENT;932		dev_err(&udev->dev, "Firmware not found.\n");933	}934 935	complete(&priv->fw_wait_load);936	/*937	 * At this point p54u_disconnect may have already freed938	 * the "priv" context. Do not use it anymore!939	 */940	priv = NULL;941 942	if (err) {943		dev_err(&intf->dev, "failed to initialize device (%d)\n", err);944 945		usb_lock_device(udev);946		usb_driver_release_interface(&p54u_driver, intf);947		usb_unlock_device(udev);948	}949 950	usb_put_intf(intf);951}952 953static int p54u_load_firmware(struct ieee80211_hw *dev,954			      struct usb_interface *intf)955{956	struct usb_device *udev = interface_to_usbdev(intf);957	struct p54u_priv *priv = dev->priv;958	struct device *device = &udev->dev;959	int err, i;960 961	BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES);962 963	init_completion(&priv->fw_wait_load);964	i = p54_find_type(priv);965	if (i < 0)966		return i;967 968	dev_info(&priv->udev->dev, "Loading firmware file %s\n",969	       p54u_fwlist[i].fw);970 971	usb_get_intf(intf);972	err = request_firmware_nowait(THIS_MODULE, 1, p54u_fwlist[i].fw,973				      device, GFP_KERNEL, priv,974				      p54u_load_firmware_cb);975	if (err) {976		dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "977					  "(%d)!\n", p54u_fwlist[i].fw, err);978		usb_put_intf(intf);979	}980 981	return err;982}983 984static int p54u_probe(struct usb_interface *intf,985				const struct usb_device_id *id)986{987	struct usb_device *udev = interface_to_usbdev(intf);988	struct ieee80211_hw *dev;989	struct p54u_priv *priv;990	int err;991	unsigned int i, recognized_pipes;992 993	dev = p54_init_common(sizeof(*priv));994 995	if (!dev) {996		dev_err(&udev->dev, "(p54usb) ieee80211 alloc failed\n");997		return -ENOMEM;998	}999 1000	priv = dev->priv;1001	priv->hw_type = P54U_INVALID_HW;1002 1003	SET_IEEE80211_DEV(dev, &intf->dev);1004	usb_set_intfdata(intf, dev);1005	priv->udev = udev;1006	priv->intf = intf;1007	skb_queue_head_init(&priv->rx_queue);1008	init_usb_anchor(&priv->submitted);1009 1010	/* really lazy and simple way of figuring out if we're a 3887 */1011	/* TODO: should just stick the identification in the device table */1012	i = intf->altsetting->desc.bNumEndpoints;1013	recognized_pipes = 0;1014	while (i--) {1015		switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {1016		case P54U_PIPE_DATA:1017		case P54U_PIPE_MGMT:1018		case P54U_PIPE_BRG:1019		case P54U_PIPE_DEV:1020		case P54U_PIPE_DATA | USB_DIR_IN:1021		case P54U_PIPE_MGMT | USB_DIR_IN:1022		case P54U_PIPE_BRG | USB_DIR_IN:1023		case P54U_PIPE_DEV | USB_DIR_IN:1024		case P54U_PIPE_INT | USB_DIR_IN:1025			recognized_pipes++;1026		}1027	}1028	priv->common.open = p54u_open;1029	priv->common.stop = p54u_stop;1030	if (recognized_pipes < P54U_PIPE_NUMBER) {1031#ifdef CONFIG_PM1032		/* ISL3887 needs a full reset on resume */1033		udev->reset_resume = 1;1034#endif /* CONFIG_PM */1035		err = p54u_device_reset(dev);1036 1037		priv->hw_type = P54U_3887;1038		dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);1039		priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);1040		priv->common.tx = p54u_tx_lm87;1041		priv->upload_fw = p54u_upload_firmware_3887;1042	} else {1043		priv->hw_type = P54U_NET2280;1044		dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);1045		priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);1046		priv->common.tx = p54u_tx_net2280;1047		priv->upload_fw = p54u_upload_firmware_net2280;1048	}1049	err = p54u_load_firmware(dev, intf);1050	if (err)1051		p54_free_common(dev);1052	return err;1053}1054 1055static void p54u_disconnect(struct usb_interface *intf)1056{1057	struct ieee80211_hw *dev = usb_get_intfdata(intf);1058	struct p54u_priv *priv;1059 1060	if (!dev)1061		return;1062 1063	priv = dev->priv;1064	wait_for_completion(&priv->fw_wait_load);1065	p54_unregister_common(dev);1066 1067	release_firmware(priv->fw);1068	p54_free_common(dev);1069}1070 1071static int p54u_pre_reset(struct usb_interface *intf)1072{1073	struct ieee80211_hw *dev = usb_get_intfdata(intf);1074 1075	if (!dev)1076		return -ENODEV;1077 1078	p54u_stop(dev);1079	return 0;1080}1081 1082static int p54u_resume(struct usb_interface *intf)1083{1084	struct ieee80211_hw *dev = usb_get_intfdata(intf);1085	struct p54u_priv *priv;1086 1087	if (!dev)1088		return -ENODEV;1089 1090	priv = dev->priv;1091	if (unlikely(!(priv->upload_fw && priv->fw)))1092		return 0;1093 1094	return priv->upload_fw(dev);1095}1096 1097static int p54u_post_reset(struct usb_interface *intf)1098{1099	struct ieee80211_hw *dev = usb_get_intfdata(intf);1100	struct p54u_priv *priv;1101	int err;1102 1103	err = p54u_resume(intf);1104	if (err)1105		return err;1106 1107	/* reinitialize old device state */1108	priv = dev->priv;1109	if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED)1110		ieee80211_restart_hw(dev);1111 1112	return 0;1113}1114 1115#ifdef CONFIG_PM1116 1117static int p54u_suspend(struct usb_interface *intf, pm_message_t message)1118{1119	return p54u_pre_reset(intf);1120}1121 1122#endif /* CONFIG_PM */1123 1124static struct usb_driver p54u_driver = {1125	.name	= "p54usb",1126	.id_table = p54u_table,1127	.probe = p54u_probe,1128	.disconnect = p54u_disconnect,1129	.pre_reset = p54u_pre_reset,1130	.post_reset = p54u_post_reset,1131#ifdef CONFIG_PM1132	.suspend = p54u_suspend,1133	.resume = p54u_resume,1134	.reset_resume = p54u_resume,1135#endif /* CONFIG_PM */1136	.soft_unbind = 1,1137	.disable_hub_initiated_lpm = 1,1138};1139 1140module_usb_driver(p54u_driver);1141