xref: /openbmc/linux/drivers/net/wireless/marvell/libertas/if_usb.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2f988d640SKalle Valo /*
3f988d640SKalle Valo  * This file contains functions used in USB interface module.
4f988d640SKalle Valo  */
5f988d640SKalle Valo 
6f988d640SKalle Valo #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7f988d640SKalle Valo 
8f988d640SKalle Valo #include <linux/delay.h>
9f988d640SKalle Valo #include <linux/module.h>
10f988d640SKalle Valo #include <linux/firmware.h>
11f988d640SKalle Valo #include <linux/netdevice.h>
12f988d640SKalle Valo #include <linux/slab.h>
13f988d640SKalle Valo #include <linux/usb.h>
14f988d640SKalle Valo #include <linux/olpc-ec.h>
15f988d640SKalle Valo 
16f988d640SKalle Valo #ifdef CONFIG_OLPC
17f988d640SKalle Valo #include <asm/olpc.h>
18f988d640SKalle Valo #endif
19f988d640SKalle Valo 
20f988d640SKalle Valo #define DRV_NAME "usb8xxx"
21f988d640SKalle Valo 
22f988d640SKalle Valo #include "host.h"
23f988d640SKalle Valo #include "decl.h"
24f988d640SKalle Valo #include "defs.h"
25f988d640SKalle Valo #include "dev.h"
26f988d640SKalle Valo #include "cmd.h"
27f988d640SKalle Valo #include "if_usb.h"
28f988d640SKalle Valo 
29f988d640SKalle Valo #define INSANEDEBUG	0
30f988d640SKalle Valo #define lbs_deb_usb2(...) do { if (INSANEDEBUG) lbs_deb_usbd(__VA_ARGS__); } while (0)
31f988d640SKalle Valo 
32f988d640SKalle Valo #define MESSAGE_HEADER_LEN	4
33f988d640SKalle Valo 
34f988d640SKalle Valo MODULE_FIRMWARE("libertas/usb8388_v9.bin");
35f988d640SKalle Valo MODULE_FIRMWARE("libertas/usb8388_v5.bin");
36f988d640SKalle Valo MODULE_FIRMWARE("libertas/usb8388.bin");
37f988d640SKalle Valo MODULE_FIRMWARE("libertas/usb8682.bin");
38f988d640SKalle Valo MODULE_FIRMWARE("usb8388.bin");
39f988d640SKalle Valo 
40f988d640SKalle Valo enum {
41f988d640SKalle Valo 	MODEL_UNKNOWN = 0x0,
42f988d640SKalle Valo 	MODEL_8388 = 0x1,
43f988d640SKalle Valo 	MODEL_8682 = 0x2
44f988d640SKalle Valo };
45f988d640SKalle Valo 
46f988d640SKalle Valo /* table of firmware file names */
47f988d640SKalle Valo static const struct lbs_fw_table fw_table[] = {
48f988d640SKalle Valo 	{ MODEL_8388, "libertas/usb8388_olpc.bin", NULL },
49f988d640SKalle Valo 	{ MODEL_8388, "libertas/usb8388_v9.bin", NULL },
50f988d640SKalle Valo 	{ MODEL_8388, "libertas/usb8388_v5.bin", NULL },
51f988d640SKalle Valo 	{ MODEL_8388, "libertas/usb8388.bin", NULL },
52f988d640SKalle Valo 	{ MODEL_8388, "usb8388.bin", NULL },
53764f3f1eSKevin Easton 	{ MODEL_8682, "libertas/usb8682.bin", NULL },
54764f3f1eSKevin Easton 	{ 0, NULL, NULL }
55f988d640SKalle Valo };
56f988d640SKalle Valo 
573673c417SArvind Yadav static const struct usb_device_id if_usb_table[] = {
58f988d640SKalle Valo 	/* Enter the device signature inside */
59f988d640SKalle Valo 	{ USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 },
60f988d640SKalle Valo 	{ USB_DEVICE(0x05a3, 0x8388), .driver_info = MODEL_8388 },
61f988d640SKalle Valo 	{}	/* Terminating entry */
62f988d640SKalle Valo };
63f988d640SKalle Valo 
64f988d640SKalle Valo MODULE_DEVICE_TABLE(usb, if_usb_table);
65f988d640SKalle Valo 
66f988d640SKalle Valo static void if_usb_receive(struct urb *urb);
67f988d640SKalle Valo static void if_usb_receive_fwload(struct urb *urb);
68f988d640SKalle Valo static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
69f988d640SKalle Valo 				 const struct firmware *fw,
70f988d640SKalle Valo 				 const struct firmware *unused);
71f988d640SKalle Valo static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
72f988d640SKalle Valo 			       uint8_t *payload, uint16_t nb);
73f988d640SKalle Valo static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
74f988d640SKalle Valo 			uint16_t nb);
75f988d640SKalle Valo static void if_usb_free(struct if_usb_card *cardp);
76f988d640SKalle Valo static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
77f988d640SKalle Valo static int if_usb_reset_device(struct if_usb_card *cardp);
78f988d640SKalle Valo 
79f988d640SKalle Valo /**
80f988d640SKalle Valo  * if_usb_write_bulk_callback - callback function to handle the status
81f988d640SKalle Valo  * of the URB
82f988d640SKalle Valo  * @urb:	pointer to &urb structure
83f988d640SKalle Valo  * returns:	N/A
84f988d640SKalle Valo  */
if_usb_write_bulk_callback(struct urb * urb)85f988d640SKalle Valo static void if_usb_write_bulk_callback(struct urb *urb)
86f988d640SKalle Valo {
87f988d640SKalle Valo 	struct if_usb_card *cardp = (struct if_usb_card *) urb->context;
88f988d640SKalle Valo 
89f988d640SKalle Valo 	/* handle the transmission complete validations */
90f988d640SKalle Valo 
91f988d640SKalle Valo 	if (urb->status == 0) {
92f988d640SKalle Valo 		struct lbs_private *priv = cardp->priv;
93f988d640SKalle Valo 
94f988d640SKalle Valo 		lbs_deb_usb2(&urb->dev->dev, "URB status is successful\n");
95f988d640SKalle Valo 		lbs_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
96f988d640SKalle Valo 			     urb->actual_length);
97f988d640SKalle Valo 
98f988d640SKalle Valo 		/* Boot commands such as UPDATE_FW and UPDATE_BOOT2 are not
99f988d640SKalle Valo 		 * passed up to the lbs level.
100f988d640SKalle Valo 		 */
101f988d640SKalle Valo 		if (priv && priv->dnld_sent != DNLD_BOOTCMD_SENT)
102f988d640SKalle Valo 			lbs_host_to_card_done(priv);
103f988d640SKalle Valo 	} else {
104f988d640SKalle Valo 		/* print the failure status number for debug */
105f988d640SKalle Valo 		pr_info("URB in failure status: %d\n", urb->status);
106f988d640SKalle Valo 	}
107f988d640SKalle Valo }
108f988d640SKalle Valo 
109f988d640SKalle Valo /**
110f988d640SKalle Valo  * if_usb_free - free tx/rx urb, skb and rx buffer
111f988d640SKalle Valo  * @cardp:	pointer to &if_usb_card
112f988d640SKalle Valo  * returns:	N/A
113f988d640SKalle Valo  */
if_usb_free(struct if_usb_card * cardp)114f988d640SKalle Valo static void if_usb_free(struct if_usb_card *cardp)
115f988d640SKalle Valo {
116f988d640SKalle Valo 	/* Unlink tx & rx urb */
117f988d640SKalle Valo 	usb_kill_urb(cardp->tx_urb);
118f988d640SKalle Valo 	usb_kill_urb(cardp->rx_urb);
119f988d640SKalle Valo 
120f988d640SKalle Valo 	usb_free_urb(cardp->tx_urb);
121f988d640SKalle Valo 	cardp->tx_urb = NULL;
122f988d640SKalle Valo 
123f988d640SKalle Valo 	usb_free_urb(cardp->rx_urb);
124f988d640SKalle Valo 	cardp->rx_urb = NULL;
125f988d640SKalle Valo 
126f988d640SKalle Valo 	kfree(cardp->ep_out_buf);
127f988d640SKalle Valo 	cardp->ep_out_buf = NULL;
128f988d640SKalle Valo }
129f988d640SKalle Valo 
if_usb_setup_firmware(struct lbs_private * priv)130f988d640SKalle Valo static void if_usb_setup_firmware(struct lbs_private *priv)
131f988d640SKalle Valo {
132f988d640SKalle Valo 	struct if_usb_card *cardp = priv->card;
133f988d640SKalle Valo 	struct cmd_ds_set_boot2_ver b2_cmd;
134f988d640SKalle Valo 	struct cmd_ds_802_11_fw_wake_method wake_method;
135f988d640SKalle Valo 
136f988d640SKalle Valo 	b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
137f988d640SKalle Valo 	b2_cmd.action = 0;
138f988d640SKalle Valo 	b2_cmd.version = cardp->boot2_version;
139f988d640SKalle Valo 
140f988d640SKalle Valo 	if (lbs_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
141f988d640SKalle Valo 		lbs_deb_usb("Setting boot2 version failed\n");
142f988d640SKalle Valo 
143f988d640SKalle Valo 	priv->wol_gpio = 2; /* Wake via GPIO2... */
144f988d640SKalle Valo 	priv->wol_gap = 20; /* ... after 20ms    */
145f988d640SKalle Valo 	lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA,
146f988d640SKalle Valo 			(struct wol_config *) NULL);
147f988d640SKalle Valo 
148f988d640SKalle Valo 	wake_method.hdr.size = cpu_to_le16(sizeof(wake_method));
149f988d640SKalle Valo 	wake_method.action = cpu_to_le16(CMD_ACT_GET);
150f988d640SKalle Valo 	if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) {
151f988d640SKalle Valo 		netdev_info(priv->dev, "Firmware does not seem to support PS mode\n");
152f988d640SKalle Valo 		priv->fwcapinfo &= ~FW_CAPINFO_PS;
153f988d640SKalle Valo 	} else {
154f988d640SKalle Valo 		if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) {
155f988d640SKalle Valo 			lbs_deb_usb("Firmware seems to support PS with wake-via-command\n");
156f988d640SKalle Valo 		} else {
157f988d640SKalle Valo 			/* The versions which boot up this way don't seem to
158f988d640SKalle Valo 			   work even if we set it to the command interrupt */
159f988d640SKalle Valo 			priv->fwcapinfo &= ~FW_CAPINFO_PS;
160f988d640SKalle Valo 			netdev_info(priv->dev,
161f988d640SKalle Valo 				    "Firmware doesn't wake via command interrupt; disabling PS mode\n");
162f988d640SKalle Valo 		}
163f988d640SKalle Valo 	}
164f988d640SKalle Valo }
165f988d640SKalle Valo 
if_usb_fw_timeo(struct timer_list * t)16678ce6a90SKees Cook static void if_usb_fw_timeo(struct timer_list *t)
167f988d640SKalle Valo {
16878ce6a90SKees Cook 	struct if_usb_card *cardp = from_timer(cardp, t, fw_timeout);
169f988d640SKalle Valo 
170f988d640SKalle Valo 	if (cardp->fwdnldover) {
171f988d640SKalle Valo 		lbs_deb_usb("Download complete, no event. Assuming success\n");
172f988d640SKalle Valo 	} else {
173f988d640SKalle Valo 		pr_err("Download timed out\n");
174f988d640SKalle Valo 		cardp->surprise_removed = 1;
175f988d640SKalle Valo 	}
176f988d640SKalle Valo 	wake_up(&cardp->fw_wq);
177f988d640SKalle Valo }
178f988d640SKalle Valo 
179f988d640SKalle Valo #ifdef CONFIG_OLPC
if_usb_reset_olpc_card(struct lbs_private * priv)180f988d640SKalle Valo static void if_usb_reset_olpc_card(struct lbs_private *priv)
181f988d640SKalle Valo {
182f988d640SKalle Valo 	printk(KERN_CRIT "Resetting OLPC wireless via EC...\n");
183f988d640SKalle Valo 	olpc_ec_cmd(0x25, NULL, 0, NULL, 0);
184f988d640SKalle Valo }
185f988d640SKalle Valo #endif
186f988d640SKalle Valo 
187f988d640SKalle Valo /**
188f988d640SKalle Valo  * if_usb_probe - sets the configuration values
189f988d640SKalle Valo  * @intf:	&usb_interface pointer
190f988d640SKalle Valo  * @id:	pointer to usb_device_id
191f988d640SKalle Valo  * returns:	0 on success, error code on failure
192f988d640SKalle Valo  */
if_usb_probe(struct usb_interface * intf,const struct usb_device_id * id)193f988d640SKalle Valo static int if_usb_probe(struct usb_interface *intf,
194f988d640SKalle Valo 			const struct usb_device_id *id)
195f988d640SKalle Valo {
196f988d640SKalle Valo 	struct usb_device *udev;
197f988d640SKalle Valo 	struct usb_host_interface *iface_desc;
198f988d640SKalle Valo 	struct usb_endpoint_descriptor *endpoint;
199f988d640SKalle Valo 	struct lbs_private *priv;
200f988d640SKalle Valo 	struct if_usb_card *cardp;
201f988d640SKalle Valo 	int r = -ENOMEM;
202f988d640SKalle Valo 	int i;
203f988d640SKalle Valo 
204f988d640SKalle Valo 	udev = interface_to_usbdev(intf);
205f988d640SKalle Valo 
206f988d640SKalle Valo 	cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
207f988d640SKalle Valo 	if (!cardp)
208f988d640SKalle Valo 		goto error;
209f988d640SKalle Valo 
21078ce6a90SKees Cook 	timer_setup(&cardp->fw_timeout, if_usb_fw_timeo, 0);
211f988d640SKalle Valo 	init_waitqueue_head(&cardp->fw_wq);
212f988d640SKalle Valo 
213f988d640SKalle Valo 	cardp->udev = udev;
214f988d640SKalle Valo 	cardp->model = (uint32_t) id->driver_info;
215f988d640SKalle Valo 	iface_desc = intf->cur_altsetting;
216f988d640SKalle Valo 
217f988d640SKalle Valo 	lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
218f988d640SKalle Valo 		     " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
219f988d640SKalle Valo 		     le16_to_cpu(udev->descriptor.bcdUSB),
220f988d640SKalle Valo 		     udev->descriptor.bDeviceClass,
221f988d640SKalle Valo 		     udev->descriptor.bDeviceSubClass,
222f988d640SKalle Valo 		     udev->descriptor.bDeviceProtocol);
223f988d640SKalle Valo 
224f988d640SKalle Valo 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
225f988d640SKalle Valo 		endpoint = &iface_desc->endpoint[i].desc;
226f988d640SKalle Valo 		if (usb_endpoint_is_bulk_in(endpoint)) {
227f988d640SKalle Valo 			cardp->ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize);
228f988d640SKalle Valo 			cardp->ep_in = usb_endpoint_num(endpoint);
229f988d640SKalle Valo 
230f988d640SKalle Valo 			lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in);
231f988d640SKalle Valo 			lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size);
232f988d640SKalle Valo 
233f988d640SKalle Valo 		} else if (usb_endpoint_is_bulk_out(endpoint)) {
234f988d640SKalle Valo 			cardp->ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize);
235f988d640SKalle Valo 			cardp->ep_out = usb_endpoint_num(endpoint);
236f988d640SKalle Valo 
237f988d640SKalle Valo 			lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out);
238f988d640SKalle Valo 			lbs_deb_usbd(&udev->dev, "Bulk out size is %d\n", cardp->ep_out_size);
239f988d640SKalle Valo 		}
240f988d640SKalle Valo 	}
241f988d640SKalle Valo 	if (!cardp->ep_out_size || !cardp->ep_in_size) {
242f988d640SKalle Valo 		lbs_deb_usbd(&udev->dev, "Endpoints not found\n");
243f988d640SKalle Valo 		goto dealloc;
244f988d640SKalle Valo 	}
245f988d640SKalle Valo 	if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
246f988d640SKalle Valo 		lbs_deb_usbd(&udev->dev, "Rx URB allocation failed\n");
247f988d640SKalle Valo 		goto dealloc;
248f988d640SKalle Valo 	}
249f988d640SKalle Valo 	if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
250f988d640SKalle Valo 		lbs_deb_usbd(&udev->dev, "Tx URB allocation failed\n");
251f988d640SKalle Valo 		goto dealloc;
252f988d640SKalle Valo 	}
253f988d640SKalle Valo 	cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL);
254f988d640SKalle Valo 	if (!cardp->ep_out_buf) {
255f988d640SKalle Valo 		lbs_deb_usbd(&udev->dev, "Could not allocate buffer\n");
256f988d640SKalle Valo 		goto dealloc;
257f988d640SKalle Valo 	}
258f988d640SKalle Valo 
259bbc2a101SLubomir Rintel 	priv = lbs_add_card(cardp, &intf->dev);
260bbc2a101SLubomir Rintel 	if (IS_ERR(priv)) {
261bbc2a101SLubomir Rintel 		r = PTR_ERR(priv);
262f988d640SKalle Valo 		goto err_add_card;
263bbc2a101SLubomir Rintel 	}
264f988d640SKalle Valo 
265f988d640SKalle Valo 	cardp->priv = priv;
266f988d640SKalle Valo 
267f988d640SKalle Valo 	priv->hw_host_to_card = if_usb_host_to_card;
268f988d640SKalle Valo 	priv->enter_deep_sleep = NULL;
269f988d640SKalle Valo 	priv->exit_deep_sleep = NULL;
270f988d640SKalle Valo 	priv->reset_deep_sleep_wakeup = NULL;
271fae4f9f7SAndreas Kemnade 	priv->is_polling = false;
272f988d640SKalle Valo #ifdef CONFIG_OLPC
273f988d640SKalle Valo 	if (machine_is_olpc())
274f988d640SKalle Valo 		priv->reset_card = if_usb_reset_olpc_card;
275f988d640SKalle Valo #endif
276f988d640SKalle Valo 
277f988d640SKalle Valo 	cardp->boot2_version = udev->descriptor.bcdDevice;
278f988d640SKalle Valo 
279f988d640SKalle Valo 	usb_get_dev(udev);
280f988d640SKalle Valo 	usb_set_intfdata(intf, cardp);
281f988d640SKalle Valo 
282f988d640SKalle Valo 	r = lbs_get_firmware_async(priv, &udev->dev, cardp->model,
283f988d640SKalle Valo 				   fw_table, if_usb_prog_firmware);
284f988d640SKalle Valo 	if (r)
285f988d640SKalle Valo 		goto err_get_fw;
286f988d640SKalle Valo 
287f988d640SKalle Valo 	return 0;
288f988d640SKalle Valo 
289f988d640SKalle Valo err_get_fw:
2906fd57e1dSHangyu Hua 	usb_put_dev(udev);
291f988d640SKalle Valo 	lbs_remove_card(priv);
292f988d640SKalle Valo err_add_card:
293f988d640SKalle Valo 	if_usb_reset_device(cardp);
294f988d640SKalle Valo dealloc:
295f988d640SKalle Valo 	if_usb_free(cardp);
2969692151eSWang Hai 	kfree(cardp);
297f988d640SKalle Valo 
298f988d640SKalle Valo error:
299f988d640SKalle Valo 	return r;
300f988d640SKalle Valo }
301f988d640SKalle Valo 
302f988d640SKalle Valo /**
303f988d640SKalle Valo  * if_usb_disconnect - free resource and cleanup
304f988d640SKalle Valo  * @intf:	USB interface structure
305f988d640SKalle Valo  * returns:	N/A
306f988d640SKalle Valo  */
if_usb_disconnect(struct usb_interface * intf)307f988d640SKalle Valo static void if_usb_disconnect(struct usb_interface *intf)
308f988d640SKalle Valo {
309f988d640SKalle Valo 	struct if_usb_card *cardp = usb_get_intfdata(intf);
310f988d640SKalle Valo 	struct lbs_private *priv = cardp->priv;
311f988d640SKalle Valo 
312f988d640SKalle Valo 	cardp->surprise_removed = 1;
313f988d640SKalle Valo 
314f988d640SKalle Valo 	if (priv) {
315f988d640SKalle Valo 		lbs_stop_card(priv);
316f988d640SKalle Valo 		lbs_remove_card(priv);
317f988d640SKalle Valo 	}
318f988d640SKalle Valo 
319f988d640SKalle Valo 	/* Unlink and free urb */
320f988d640SKalle Valo 	if_usb_free(cardp);
3219692151eSWang Hai 	kfree(cardp);
322f988d640SKalle Valo 
323f988d640SKalle Valo 	usb_set_intfdata(intf, NULL);
324f988d640SKalle Valo 	usb_put_dev(interface_to_usbdev(intf));
325f988d640SKalle Valo }
326f988d640SKalle Valo 
327f988d640SKalle Valo /**
328f988d640SKalle Valo  * if_usb_send_fw_pkt - download FW
329f988d640SKalle Valo  * @cardp:	pointer to &struct if_usb_card
330f988d640SKalle Valo  * returns:	0
331f988d640SKalle Valo  */
if_usb_send_fw_pkt(struct if_usb_card * cardp)332f988d640SKalle Valo static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
333f988d640SKalle Valo {
334f988d640SKalle Valo 	struct fwdata *fwdata = cardp->ep_out_buf;
335f988d640SKalle Valo 	const uint8_t *firmware = cardp->fw->data;
336f988d640SKalle Valo 
337f988d640SKalle Valo 	/* If we got a CRC failure on the last block, back
338f988d640SKalle Valo 	   up and retry it */
339f988d640SKalle Valo 	if (!cardp->CRC_OK) {
340f988d640SKalle Valo 		cardp->totalbytes = cardp->fwlastblksent;
341f988d640SKalle Valo 		cardp->fwseqnum--;
342f988d640SKalle Valo 	}
343f988d640SKalle Valo 
344f988d640SKalle Valo 	lbs_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n",
345f988d640SKalle Valo 		     cardp->totalbytes);
346f988d640SKalle Valo 
347f988d640SKalle Valo 	/* struct fwdata (which we sent to the card) has an
348f988d640SKalle Valo 	   extra __le32 field in between the header and the data,
349f988d640SKalle Valo 	   which is not in the struct fwheader in the actual
350f988d640SKalle Valo 	   firmware binary. Insert the seqnum in the middle... */
351f988d640SKalle Valo 	memcpy(&fwdata->hdr, &firmware[cardp->totalbytes],
352f988d640SKalle Valo 	       sizeof(struct fwheader));
353f988d640SKalle Valo 
354f988d640SKalle Valo 	cardp->fwlastblksent = cardp->totalbytes;
355f988d640SKalle Valo 	cardp->totalbytes += sizeof(struct fwheader);
356f988d640SKalle Valo 
357f988d640SKalle Valo 	memcpy(fwdata->data, &firmware[cardp->totalbytes],
358f988d640SKalle Valo 	       le32_to_cpu(fwdata->hdr.datalength));
359f988d640SKalle Valo 
360f988d640SKalle Valo 	lbs_deb_usb2(&cardp->udev->dev, "Data length = %d\n",
361f988d640SKalle Valo 		     le32_to_cpu(fwdata->hdr.datalength));
362f988d640SKalle Valo 
363f988d640SKalle Valo 	fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
364f988d640SKalle Valo 	cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
365f988d640SKalle Valo 
366f988d640SKalle Valo 	usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
367f988d640SKalle Valo 		     le32_to_cpu(fwdata->hdr.datalength));
368f988d640SKalle Valo 
369f988d640SKalle Valo 	if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
370f988d640SKalle Valo 		lbs_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
371f988d640SKalle Valo 		lbs_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n",
372f988d640SKalle Valo 			     cardp->fwseqnum, cardp->totalbytes);
373f988d640SKalle Valo 	} else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
374f988d640SKalle Valo 		lbs_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n");
375aeffda6bSColin Ian King 		lbs_deb_usb2(&cardp->udev->dev, "Downloading FW JUMP BLOCK\n");
376f988d640SKalle Valo 
377f988d640SKalle Valo 		cardp->fwfinalblk = 1;
378f988d640SKalle Valo 	}
379f988d640SKalle Valo 
380f988d640SKalle Valo 	lbs_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n",
381f988d640SKalle Valo 		     cardp->totalbytes);
382f988d640SKalle Valo 
383f988d640SKalle Valo 	return 0;
384f988d640SKalle Valo }
385f988d640SKalle Valo 
if_usb_reset_device(struct if_usb_card * cardp)386f988d640SKalle Valo static int if_usb_reset_device(struct if_usb_card *cardp)
387f988d640SKalle Valo {
388f988d640SKalle Valo 	struct cmd_header *cmd = cardp->ep_out_buf + 4;
389f988d640SKalle Valo 	int ret;
390f988d640SKalle Valo 
391f988d640SKalle Valo 	*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
392f988d640SKalle Valo 
393f988d640SKalle Valo 	cmd->command = cpu_to_le16(CMD_802_11_RESET);
394f988d640SKalle Valo 	cmd->size = cpu_to_le16(sizeof(cmd));
395f988d640SKalle Valo 	cmd->result = cpu_to_le16(0);
396f988d640SKalle Valo 	cmd->seqnum = cpu_to_le16(0x5a5a);
397f988d640SKalle Valo 	usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header));
398f988d640SKalle Valo 
399f988d640SKalle Valo 	msleep(100);
400f988d640SKalle Valo 	ret = usb_reset_device(cardp->udev);
401f988d640SKalle Valo 	msleep(100);
402f988d640SKalle Valo 
403f988d640SKalle Valo #ifdef CONFIG_OLPC
404f988d640SKalle Valo 	if (ret && machine_is_olpc())
405f988d640SKalle Valo 		if_usb_reset_olpc_card(NULL);
406f988d640SKalle Valo #endif
407f988d640SKalle Valo 
408f988d640SKalle Valo 	return ret;
409f988d640SKalle Valo }
410f988d640SKalle Valo 
411f988d640SKalle Valo /**
412f988d640SKalle Valo  *  usb_tx_block - transfer the data to the device
413f988d640SKalle Valo  *  @cardp: 	pointer to &struct if_usb_card
414f988d640SKalle Valo  *  @payload:	pointer to payload data
415f988d640SKalle Valo  *  @nb:	data length
416f988d640SKalle Valo  *  returns:	0 for success or negative error code
417f988d640SKalle Valo  */
usb_tx_block(struct if_usb_card * cardp,uint8_t * payload,uint16_t nb)418f988d640SKalle Valo static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb)
419f988d640SKalle Valo {
420f988d640SKalle Valo 	int ret;
421f988d640SKalle Valo 
422f988d640SKalle Valo 	/* check if device is removed */
423f988d640SKalle Valo 	if (cardp->surprise_removed) {
424f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
425f988d640SKalle Valo 		ret = -ENODEV;
426f988d640SKalle Valo 		goto tx_ret;
427f988d640SKalle Valo 	}
428f988d640SKalle Valo 
429f988d640SKalle Valo 	usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
430f988d640SKalle Valo 			  usb_sndbulkpipe(cardp->udev,
431f988d640SKalle Valo 					  cardp->ep_out),
432f988d640SKalle Valo 			  payload, nb, if_usb_write_bulk_callback, cardp);
433f988d640SKalle Valo 
434f988d640SKalle Valo 	cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
435f988d640SKalle Valo 
436f988d640SKalle Valo 	if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
437f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
438f988d640SKalle Valo 	} else {
439f988d640SKalle Valo 		lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
440f988d640SKalle Valo 		ret = 0;
441f988d640SKalle Valo 	}
442f988d640SKalle Valo 
443f988d640SKalle Valo tx_ret:
444f988d640SKalle Valo 	return ret;
445f988d640SKalle Valo }
446f988d640SKalle Valo 
__if_usb_submit_rx_urb(struct if_usb_card * cardp,void (* callbackfn)(struct urb * urb))447f988d640SKalle Valo static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
448f988d640SKalle Valo 				  void (*callbackfn)(struct urb *urb))
449f988d640SKalle Valo {
450f988d640SKalle Valo 	struct sk_buff *skb;
451f988d640SKalle Valo 	int ret = -1;
452f988d640SKalle Valo 
453f988d640SKalle Valo 	if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {
454f988d640SKalle Valo 		pr_err("No free skb\n");
455f988d640SKalle Valo 		goto rx_ret;
456f988d640SKalle Valo 	}
457f988d640SKalle Valo 
458f988d640SKalle Valo 	cardp->rx_skb = skb;
459f988d640SKalle Valo 
460f988d640SKalle Valo 	/* Fill the receive configuration URB and initialise the Rx call back */
461f988d640SKalle Valo 	usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
462f988d640SKalle Valo 			  usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
463f988d640SKalle Valo 			  skb->data + IPFIELD_ALIGN_OFFSET,
464f988d640SKalle Valo 			  MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
465f988d640SKalle Valo 			  cardp);
466f988d640SKalle Valo 
467f988d640SKalle Valo 	lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
468f988d640SKalle Valo 	if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
469f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
470f988d640SKalle Valo 		kfree_skb(skb);
471f988d640SKalle Valo 		cardp->rx_skb = NULL;
472f988d640SKalle Valo 		ret = -1;
473f988d640SKalle Valo 	} else {
474f988d640SKalle Valo 		lbs_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n");
475f988d640SKalle Valo 		ret = 0;
476f988d640SKalle Valo 	}
477f988d640SKalle Valo 
478f988d640SKalle Valo rx_ret:
479f988d640SKalle Valo 	return ret;
480f988d640SKalle Valo }
481f988d640SKalle Valo 
if_usb_submit_rx_urb_fwload(struct if_usb_card * cardp)482f988d640SKalle Valo static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
483f988d640SKalle Valo {
484f988d640SKalle Valo 	return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
485f988d640SKalle Valo }
486f988d640SKalle Valo 
if_usb_submit_rx_urb(struct if_usb_card * cardp)487f988d640SKalle Valo static int if_usb_submit_rx_urb(struct if_usb_card *cardp)
488f988d640SKalle Valo {
489f988d640SKalle Valo 	return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
490f988d640SKalle Valo }
491f988d640SKalle Valo 
if_usb_receive_fwload(struct urb * urb)492f988d640SKalle Valo static void if_usb_receive_fwload(struct urb *urb)
493f988d640SKalle Valo {
494f988d640SKalle Valo 	struct if_usb_card *cardp = urb->context;
495f988d640SKalle Valo 	struct sk_buff *skb = cardp->rx_skb;
496f988d640SKalle Valo 	struct fwsyncheader *syncfwheader;
497f988d640SKalle Valo 	struct bootcmdresp bootcmdresp;
498f988d640SKalle Valo 
499f988d640SKalle Valo 	if (urb->status) {
500f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev,
501f988d640SKalle Valo 			     "URB status is failed during fw load\n");
502f988d640SKalle Valo 		kfree_skb(skb);
503f988d640SKalle Valo 		return;
504f988d640SKalle Valo 	}
505f988d640SKalle Valo 
506f988d640SKalle Valo 	if (cardp->fwdnldover) {
507f988d640SKalle Valo 		__le32 *tmp = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
508f988d640SKalle Valo 
509f988d640SKalle Valo 		if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) &&
510f988d640SKalle Valo 		    tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) {
511f988d640SKalle Valo 			pr_info("Firmware ready event received\n");
512f988d640SKalle Valo 			wake_up(&cardp->fw_wq);
513f988d640SKalle Valo 		} else {
514f988d640SKalle Valo 			lbs_deb_usb("Waiting for confirmation; got %x %x\n",
515f988d640SKalle Valo 				    le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1]));
516f988d640SKalle Valo 			if_usb_submit_rx_urb_fwload(cardp);
517f988d640SKalle Valo 		}
518f988d640SKalle Valo 		kfree_skb(skb);
519f988d640SKalle Valo 		return;
520f988d640SKalle Valo 	}
521f988d640SKalle Valo 	if (cardp->bootcmdresp <= 0) {
522f988d640SKalle Valo 		memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,
523f988d640SKalle Valo 			sizeof(bootcmdresp));
524f988d640SKalle Valo 
525f988d640SKalle Valo 		if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
526f988d640SKalle Valo 			kfree_skb(skb);
527f988d640SKalle Valo 			if_usb_submit_rx_urb_fwload(cardp);
528f988d640SKalle Valo 			cardp->bootcmdresp = BOOT_CMD_RESP_OK;
529f988d640SKalle Valo 			lbs_deb_usbd(&cardp->udev->dev,
530f988d640SKalle Valo 				     "Received valid boot command response\n");
531f988d640SKalle Valo 			return;
532f988d640SKalle Valo 		}
533f988d640SKalle Valo 		if (bootcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
534f988d640SKalle Valo 			if (bootcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
535f988d640SKalle Valo 			    bootcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
536f988d640SKalle Valo 			    bootcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) {
537f988d640SKalle Valo 				if (!cardp->bootcmdresp)
538f988d640SKalle Valo 					pr_info("Firmware already seems alive; resetting\n");
539f988d640SKalle Valo 				cardp->bootcmdresp = -1;
540f988d640SKalle Valo 			} else {
541f988d640SKalle Valo 				pr_info("boot cmd response wrong magic number (0x%x)\n",
542f988d640SKalle Valo 					    le32_to_cpu(bootcmdresp.magic));
543f988d640SKalle Valo 			}
544f988d640SKalle Valo 		} else if ((bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) &&
545f988d640SKalle Valo 			   (bootcmdresp.cmd != BOOT_CMD_UPDATE_FW) &&
546f988d640SKalle Valo 			   (bootcmdresp.cmd != BOOT_CMD_UPDATE_BOOT2)) {
547f988d640SKalle Valo 			pr_info("boot cmd response cmd_tag error (%d)\n",
548f988d640SKalle Valo 				bootcmdresp.cmd);
549f988d640SKalle Valo 		} else if (bootcmdresp.result != BOOT_CMD_RESP_OK) {
550f988d640SKalle Valo 			pr_info("boot cmd response result error (%d)\n",
551f988d640SKalle Valo 				bootcmdresp.result);
552f988d640SKalle Valo 		} else {
553f988d640SKalle Valo 			cardp->bootcmdresp = 1;
554f988d640SKalle Valo 			lbs_deb_usbd(&cardp->udev->dev,
555f988d640SKalle Valo 				     "Received valid boot command response\n");
556f988d640SKalle Valo 		}
557f988d640SKalle Valo 		kfree_skb(skb);
558f988d640SKalle Valo 		if_usb_submit_rx_urb_fwload(cardp);
559f988d640SKalle Valo 		return;
560f988d640SKalle Valo 	}
561f988d640SKalle Valo 
562f988d640SKalle Valo 	syncfwheader = kmemdup(skb->data + IPFIELD_ALIGN_OFFSET,
563f988d640SKalle Valo 			       sizeof(struct fwsyncheader), GFP_ATOMIC);
564f988d640SKalle Valo 	if (!syncfwheader) {
565f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
566f988d640SKalle Valo 		kfree_skb(skb);
567f988d640SKalle Valo 		return;
568f988d640SKalle Valo 	}
569f988d640SKalle Valo 
570f988d640SKalle Valo 	if (!syncfwheader->cmd) {
571f988d640SKalle Valo 		lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
572f988d640SKalle Valo 		lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
573f988d640SKalle Valo 			     le32_to_cpu(syncfwheader->seqnum));
574f988d640SKalle Valo 		cardp->CRC_OK = 1;
575f988d640SKalle Valo 	} else {
576f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n");
577f988d640SKalle Valo 		cardp->CRC_OK = 0;
578f988d640SKalle Valo 	}
579f988d640SKalle Valo 
580f988d640SKalle Valo 	kfree_skb(skb);
581f988d640SKalle Valo 
582f988d640SKalle Valo 	/* Give device 5s to either write firmware to its RAM or eeprom */
583f988d640SKalle Valo 	mod_timer(&cardp->fw_timeout, jiffies + (HZ*5));
584f988d640SKalle Valo 
585f988d640SKalle Valo 	if (cardp->fwfinalblk) {
586f988d640SKalle Valo 		cardp->fwdnldover = 1;
587f988d640SKalle Valo 		goto exit;
588f988d640SKalle Valo 	}
589f988d640SKalle Valo 
590f988d640SKalle Valo 	if_usb_send_fw_pkt(cardp);
591f988d640SKalle Valo 
592f988d640SKalle Valo  exit:
593f988d640SKalle Valo 	if_usb_submit_rx_urb_fwload(cardp);
594f988d640SKalle Valo 
595f988d640SKalle Valo 	kfree(syncfwheader);
596f988d640SKalle Valo }
597f988d640SKalle Valo 
598f988d640SKalle Valo #define MRVDRV_MIN_PKT_LEN	30
599f988d640SKalle Valo 
process_cmdtypedata(int recvlength,struct sk_buff * skb,struct if_usb_card * cardp,struct lbs_private * priv)600f988d640SKalle Valo static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
601f988d640SKalle Valo 				       struct if_usb_card *cardp,
602f988d640SKalle Valo 				       struct lbs_private *priv)
603f988d640SKalle Valo {
604f988d640SKalle Valo 	if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
605f988d640SKalle Valo 	    || recvlength < MRVDRV_MIN_PKT_LEN) {
606f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n");
607f988d640SKalle Valo 		kfree_skb(skb);
608f988d640SKalle Valo 		return;
609f988d640SKalle Valo 	}
610f988d640SKalle Valo 
611f988d640SKalle Valo 	skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
612f988d640SKalle Valo 	skb_put(skb, recvlength);
613f988d640SKalle Valo 	skb_pull(skb, MESSAGE_HEADER_LEN);
614f988d640SKalle Valo 
615f988d640SKalle Valo 	lbs_process_rxed_packet(priv, skb);
616f988d640SKalle Valo }
617f988d640SKalle Valo 
process_cmdrequest(int recvlength,uint8_t * recvbuff,struct sk_buff * skb,struct if_usb_card * cardp,struct lbs_private * priv)618f988d640SKalle Valo static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
619f988d640SKalle Valo 				      struct sk_buff *skb,
620f988d640SKalle Valo 				      struct if_usb_card *cardp,
621f988d640SKalle Valo 				      struct lbs_private *priv)
622f988d640SKalle Valo {
623a3128feeSSebastian Andrzej Siewior 	unsigned long flags;
624f988d640SKalle Valo 	u8 i;
625f988d640SKalle Valo 
626f988d640SKalle Valo 	if (recvlength > LBS_CMD_BUFFER_SIZE) {
627f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev,
628f988d640SKalle Valo 			     "The receive buffer is too large\n");
629f988d640SKalle Valo 		kfree_skb(skb);
630f988d640SKalle Valo 		return;
631f988d640SKalle Valo 	}
632f988d640SKalle Valo 
633a3128feeSSebastian Andrzej Siewior 	spin_lock_irqsave(&priv->driver_lock, flags);
634f988d640SKalle Valo 
635f988d640SKalle Valo 	i = (priv->resp_idx == 0) ? 1 : 0;
636f988d640SKalle Valo 	BUG_ON(priv->resp_len[i]);
637f988d640SKalle Valo 	priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN);
638f988d640SKalle Valo 	memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN,
639f988d640SKalle Valo 		priv->resp_len[i]);
640*3968e81bSYang Yingliang 	dev_kfree_skb_irq(skb);
641f988d640SKalle Valo 	lbs_notify_command_response(priv, i);
642f988d640SKalle Valo 
643a3128feeSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&priv->driver_lock, flags);
644f988d640SKalle Valo 
645f988d640SKalle Valo 	lbs_deb_usbd(&cardp->udev->dev,
646f988d640SKalle Valo 		    "Wake up main thread to handle cmd response\n");
647f988d640SKalle Valo }
648f988d640SKalle Valo 
649f988d640SKalle Valo /**
650f988d640SKalle Valo  *  if_usb_receive - read the packet into the upload buffer,
651f988d640SKalle Valo  *  wake up the main thread and initialise the Rx callack
652f988d640SKalle Valo  *
653f988d640SKalle Valo  *  @urb:	pointer to &struct urb
654f988d640SKalle Valo  *  returns:	N/A
655f988d640SKalle Valo  */
if_usb_receive(struct urb * urb)656f988d640SKalle Valo static void if_usb_receive(struct urb *urb)
657f988d640SKalle Valo {
658f988d640SKalle Valo 	struct if_usb_card *cardp = urb->context;
659f988d640SKalle Valo 	struct sk_buff *skb = cardp->rx_skb;
660f988d640SKalle Valo 	struct lbs_private *priv = cardp->priv;
661f988d640SKalle Valo 	int recvlength = urb->actual_length;
662f988d640SKalle Valo 	uint8_t *recvbuff = NULL;
663f988d640SKalle Valo 	uint32_t recvtype = 0;
664f988d640SKalle Valo 	__le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
665f988d640SKalle Valo 	uint32_t event;
666f988d640SKalle Valo 
667f988d640SKalle Valo 	if (recvlength) {
668f988d640SKalle Valo 		if (urb->status) {
669f988d640SKalle Valo 			lbs_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
670f988d640SKalle Valo 				     urb->status);
671f988d640SKalle Valo 			kfree_skb(skb);
672f988d640SKalle Valo 			goto setup_for_next;
673f988d640SKalle Valo 		}
674f988d640SKalle Valo 
675f988d640SKalle Valo 		recvbuff = skb->data + IPFIELD_ALIGN_OFFSET;
676f988d640SKalle Valo 		recvtype = le32_to_cpu(pkt[0]);
677f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev,
678f988d640SKalle Valo 			    "Recv length = 0x%x, Recv type = 0x%X\n",
679f988d640SKalle Valo 			    recvlength, recvtype);
680f988d640SKalle Valo 	} else if (urb->status) {
681f988d640SKalle Valo 		kfree_skb(skb);
6824bc606afSKees Cook 		return;
683f988d640SKalle Valo 	}
684f988d640SKalle Valo 
685f988d640SKalle Valo 	switch (recvtype) {
686f988d640SKalle Valo 	case CMD_TYPE_DATA:
687f988d640SKalle Valo 		process_cmdtypedata(recvlength, skb, cardp, priv);
688f988d640SKalle Valo 		break;
689f988d640SKalle Valo 
690f988d640SKalle Valo 	case CMD_TYPE_REQUEST:
691f988d640SKalle Valo 		process_cmdrequest(recvlength, recvbuff, skb, cardp, priv);
692f988d640SKalle Valo 		break;
693f988d640SKalle Valo 
694f988d640SKalle Valo 	case CMD_TYPE_INDICATION:
695f988d640SKalle Valo 		/* Event handling */
696f988d640SKalle Valo 		event = le32_to_cpu(pkt[1]);
697f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event);
698f988d640SKalle Valo 		kfree_skb(skb);
699f988d640SKalle Valo 
700f988d640SKalle Valo 		/* Icky undocumented magic special case */
701f988d640SKalle Valo 		if (event & 0xffff0000) {
702f988d640SKalle Valo 			u32 trycount = (event & 0xffff0000) >> 16;
703f988d640SKalle Valo 
704f988d640SKalle Valo 			lbs_send_tx_feedback(priv, trycount);
705f988d640SKalle Valo 		} else
706f988d640SKalle Valo 			lbs_queue_event(priv, event & 0xFF);
707f988d640SKalle Valo 		break;
708f988d640SKalle Valo 
709f988d640SKalle Valo 	default:
710f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n",
711f988d640SKalle Valo 			     recvtype);
712f988d640SKalle Valo 		kfree_skb(skb);
713f988d640SKalle Valo 		break;
714f988d640SKalle Valo 	}
715f988d640SKalle Valo 
716f988d640SKalle Valo setup_for_next:
717f988d640SKalle Valo 	if_usb_submit_rx_urb(cardp);
718f988d640SKalle Valo }
719f988d640SKalle Valo 
720f988d640SKalle Valo /**
721f988d640SKalle Valo  *  if_usb_host_to_card - downloads data to FW
722f988d640SKalle Valo  *  @priv:	pointer to &struct lbs_private structure
723f988d640SKalle Valo  *  @type:	type of data
724f988d640SKalle Valo  *  @payload:	pointer to data buffer
725f988d640SKalle Valo  *  @nb:	number of bytes
726f988d640SKalle Valo  *  returns:	0 for success or negative error code
727f988d640SKalle Valo  */
if_usb_host_to_card(struct lbs_private * priv,uint8_t type,uint8_t * payload,uint16_t nb)728f988d640SKalle Valo static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
729f988d640SKalle Valo 			       uint8_t *payload, uint16_t nb)
730f988d640SKalle Valo {
731f988d640SKalle Valo 	struct if_usb_card *cardp = priv->card;
732f988d640SKalle Valo 
733f988d640SKalle Valo 	lbs_deb_usbd(&cardp->udev->dev,"*** type = %u\n", type);
734f988d640SKalle Valo 	lbs_deb_usbd(&cardp->udev->dev,"size after = %d\n", nb);
735f988d640SKalle Valo 
736f988d640SKalle Valo 	if (type == MVMS_CMD) {
737f988d640SKalle Valo 		*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
738f988d640SKalle Valo 		priv->dnld_sent = DNLD_CMD_SENT;
739f988d640SKalle Valo 	} else {
740f988d640SKalle Valo 		*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_DATA);
741f988d640SKalle Valo 		priv->dnld_sent = DNLD_DATA_SENT;
742f988d640SKalle Valo 	}
743f988d640SKalle Valo 
744f988d640SKalle Valo 	memcpy((cardp->ep_out_buf + MESSAGE_HEADER_LEN), payload, nb);
745f988d640SKalle Valo 
746f988d640SKalle Valo 	return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN);
747f988d640SKalle Valo }
748f988d640SKalle Valo 
749f988d640SKalle Valo /**
750f988d640SKalle Valo  *  if_usb_issue_boot_command - issues Boot command to the Boot2 code
751f988d640SKalle Valo  *  @cardp:	pointer to &if_usb_card
752f988d640SKalle Valo  *  @ivalue:	1:Boot from FW by USB-Download
753f988d640SKalle Valo  *		2:Boot from FW in EEPROM
754f988d640SKalle Valo  *  returns:	0 for success or negative error code
755f988d640SKalle Valo  */
if_usb_issue_boot_command(struct if_usb_card * cardp,int ivalue)756f988d640SKalle Valo static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue)
757f988d640SKalle Valo {
758f988d640SKalle Valo 	struct bootcmd *bootcmd = cardp->ep_out_buf;
759f988d640SKalle Valo 
760f988d640SKalle Valo 	/* Prepare command */
761f988d640SKalle Valo 	bootcmd->magic = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
762f988d640SKalle Valo 	bootcmd->cmd = ivalue;
763f988d640SKalle Valo 	memset(bootcmd->pad, 0, sizeof(bootcmd->pad));
764f988d640SKalle Valo 
765f988d640SKalle Valo 	/* Issue command */
766f988d640SKalle Valo 	usb_tx_block(cardp, cardp->ep_out_buf, sizeof(*bootcmd));
767f988d640SKalle Valo 
768f988d640SKalle Valo 	return 0;
769f988d640SKalle Valo }
770f988d640SKalle Valo 
771f988d640SKalle Valo 
772f988d640SKalle Valo /**
773f988d640SKalle Valo  *  check_fwfile_format - check the validity of Boot2/FW image
774f988d640SKalle Valo  *
775f988d640SKalle Valo  *  @data:	pointer to image
776f988d640SKalle Valo  *  @totlen:	image length
777f988d640SKalle Valo  *  returns:     0 (good) or 1 (failure)
778f988d640SKalle Valo  */
check_fwfile_format(const uint8_t * data,uint32_t totlen)779f988d640SKalle Valo static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
780f988d640SKalle Valo {
781f988d640SKalle Valo 	uint32_t bincmd, exit;
782f988d640SKalle Valo 	uint32_t blksize, offset, len;
783f988d640SKalle Valo 	int ret;
784f988d640SKalle Valo 
785f988d640SKalle Valo 	ret = 1;
786f988d640SKalle Valo 	exit = len = 0;
787f988d640SKalle Valo 
788f988d640SKalle Valo 	do {
789f988d640SKalle Valo 		struct fwheader *fwh = (void *)data;
790f988d640SKalle Valo 
791f988d640SKalle Valo 		bincmd = le32_to_cpu(fwh->dnldcmd);
792f988d640SKalle Valo 		blksize = le32_to_cpu(fwh->datalength);
793f988d640SKalle Valo 		switch (bincmd) {
794f988d640SKalle Valo 		case FW_HAS_DATA_TO_RECV:
795f988d640SKalle Valo 			offset = sizeof(struct fwheader) + blksize;
796f988d640SKalle Valo 			data += offset;
797f988d640SKalle Valo 			len += offset;
798f988d640SKalle Valo 			if (len >= totlen)
799f988d640SKalle Valo 				exit = 1;
800f988d640SKalle Valo 			break;
801f988d640SKalle Valo 		case FW_HAS_LAST_BLOCK:
802f988d640SKalle Valo 			exit = 1;
803f988d640SKalle Valo 			ret = 0;
804f988d640SKalle Valo 			break;
805f988d640SKalle Valo 		default:
806f988d640SKalle Valo 			exit = 1;
807f988d640SKalle Valo 			break;
808f988d640SKalle Valo 		}
809f988d640SKalle Valo 	} while (!exit);
810f988d640SKalle Valo 
811f988d640SKalle Valo 	if (ret)
812f988d640SKalle Valo 		pr_err("firmware file format check FAIL\n");
813f988d640SKalle Valo 	else
814f988d640SKalle Valo 		lbs_deb_fw("firmware file format check PASS\n");
815f988d640SKalle Valo 
816f988d640SKalle Valo 	return ret;
817f988d640SKalle Valo }
818f988d640SKalle Valo 
if_usb_prog_firmware(struct lbs_private * priv,int ret,const struct firmware * fw,const struct firmware * unused)819f988d640SKalle Valo static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
820f988d640SKalle Valo 				 const struct firmware *fw,
821f988d640SKalle Valo 				 const struct firmware *unused)
822f988d640SKalle Valo {
823f988d640SKalle Valo 	struct if_usb_card *cardp = priv->card;
824f988d640SKalle Valo 	int i = 0;
825f988d640SKalle Valo 	static int reset_count = 10;
826f988d640SKalle Valo 
827f988d640SKalle Valo 	if (ret) {
828f988d640SKalle Valo 		pr_err("failed to find firmware (%d)\n", ret);
829f988d640SKalle Valo 		goto done;
830f988d640SKalle Valo 	}
831f988d640SKalle Valo 
832f988d640SKalle Valo 	cardp->fw = fw;
833f988d640SKalle Valo 	if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
834f988d640SKalle Valo 		ret = -EINVAL;
835f988d640SKalle Valo 		goto done;
836f988d640SKalle Valo 	}
837f988d640SKalle Valo 
838f988d640SKalle Valo 	/* Cancel any pending usb business */
839f988d640SKalle Valo 	usb_kill_urb(cardp->rx_urb);
840f988d640SKalle Valo 	usb_kill_urb(cardp->tx_urb);
841f988d640SKalle Valo 
842f988d640SKalle Valo 	cardp->fwlastblksent = 0;
843f988d640SKalle Valo 	cardp->fwdnldover = 0;
844f988d640SKalle Valo 	cardp->totalbytes = 0;
845f988d640SKalle Valo 	cardp->fwfinalblk = 0;
846f988d640SKalle Valo 	cardp->bootcmdresp = 0;
847f988d640SKalle Valo 
848f988d640SKalle Valo restart:
849f988d640SKalle Valo 	if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
850f988d640SKalle Valo 		lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
851f988d640SKalle Valo 		ret = -EIO;
852f988d640SKalle Valo 		goto done;
853f988d640SKalle Valo 	}
854f988d640SKalle Valo 
855f988d640SKalle Valo 	cardp->bootcmdresp = 0;
856f988d640SKalle Valo 	do {
857f988d640SKalle Valo 		int j = 0;
858f988d640SKalle Valo 		i++;
859f988d640SKalle Valo 		if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
860f988d640SKalle Valo 		/* wait for command response */
861f988d640SKalle Valo 		do {
862f988d640SKalle Valo 			j++;
863f988d640SKalle Valo 			msleep_interruptible(100);
864f988d640SKalle Valo 		} while (cardp->bootcmdresp == 0 && j < 10);
865f988d640SKalle Valo 	} while (cardp->bootcmdresp == 0 && i < 5);
866f988d640SKalle Valo 
867f988d640SKalle Valo 	if (cardp->bootcmdresp == BOOT_CMD_RESP_NOT_SUPPORTED) {
868f988d640SKalle Valo 		/* Return to normal operation */
869f988d640SKalle Valo 		ret = -EOPNOTSUPP;
870f988d640SKalle Valo 		usb_kill_urb(cardp->rx_urb);
871f988d640SKalle Valo 		usb_kill_urb(cardp->tx_urb);
872f988d640SKalle Valo 		if (if_usb_submit_rx_urb(cardp) < 0)
873f988d640SKalle Valo 			ret = -EIO;
874f988d640SKalle Valo 		goto done;
875f988d640SKalle Valo 	} else if (cardp->bootcmdresp <= 0) {
876f988d640SKalle Valo 		if (--reset_count >= 0) {
877f988d640SKalle Valo 			if_usb_reset_device(cardp);
878f988d640SKalle Valo 			goto restart;
879f988d640SKalle Valo 		}
880f988d640SKalle Valo 		ret = -EIO;
881f988d640SKalle Valo 		goto done;
882f988d640SKalle Valo 	}
883f988d640SKalle Valo 
884f988d640SKalle Valo 	i = 0;
885f988d640SKalle Valo 
886f988d640SKalle Valo 	cardp->totalbytes = 0;
887f988d640SKalle Valo 	cardp->fwlastblksent = 0;
888f988d640SKalle Valo 	cardp->CRC_OK = 1;
889f988d640SKalle Valo 	cardp->fwdnldover = 0;
890f988d640SKalle Valo 	cardp->fwseqnum = -1;
891f988d640SKalle Valo 	cardp->totalbytes = 0;
892f988d640SKalle Valo 	cardp->fwfinalblk = 0;
893f988d640SKalle Valo 
894f988d640SKalle Valo 	/* Send the first firmware packet... */
895f988d640SKalle Valo 	if_usb_send_fw_pkt(cardp);
896f988d640SKalle Valo 
897f988d640SKalle Valo 	/* ... and wait for the process to complete */
898f988d640SKalle Valo 	wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover);
899f988d640SKalle Valo 
900f988d640SKalle Valo 	del_timer_sync(&cardp->fw_timeout);
901f988d640SKalle Valo 	usb_kill_urb(cardp->rx_urb);
902f988d640SKalle Valo 
903f988d640SKalle Valo 	if (!cardp->fwdnldover) {
904f988d640SKalle Valo 		pr_info("failed to load fw, resetting device!\n");
905f988d640SKalle Valo 		if (--reset_count >= 0) {
906f988d640SKalle Valo 			if_usb_reset_device(cardp);
907f988d640SKalle Valo 			goto restart;
908f988d640SKalle Valo 		}
909f988d640SKalle Valo 
910f988d640SKalle Valo 		pr_info("FW download failure, time = %d ms\n", i * 100);
911f988d640SKalle Valo 		ret = -EIO;
912f988d640SKalle Valo 		goto done;
913f988d640SKalle Valo 	}
914f988d640SKalle Valo 
915f988d640SKalle Valo 	cardp->priv->fw_ready = 1;
916f988d640SKalle Valo 	if_usb_submit_rx_urb(cardp);
917f988d640SKalle Valo 
918f988d640SKalle Valo 	if (lbs_start_card(priv))
919f988d640SKalle Valo 		goto done;
920f988d640SKalle Valo 
921f988d640SKalle Valo 	if_usb_setup_firmware(priv);
922f988d640SKalle Valo 
923f988d640SKalle Valo 	/*
924f988d640SKalle Valo 	 * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
925f988d640SKalle Valo 	 */
926f988d640SKalle Valo 	priv->wol_criteria = EHS_REMOVE_WAKEUP;
927f988d640SKalle Valo 	if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
928f988d640SKalle Valo 		priv->ehs_remove_supported = false;
929f988d640SKalle Valo 
930f988d640SKalle Valo  done:
931f988d640SKalle Valo 	cardp->fw = NULL;
932f988d640SKalle Valo }
933f988d640SKalle Valo 
934f988d640SKalle Valo 
935f988d640SKalle Valo #ifdef CONFIG_PM
if_usb_suspend(struct usb_interface * intf,pm_message_t message)936f988d640SKalle Valo static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
937f988d640SKalle Valo {
938f988d640SKalle Valo 	struct if_usb_card *cardp = usb_get_intfdata(intf);
939f988d640SKalle Valo 	struct lbs_private *priv = cardp->priv;
940f988d640SKalle Valo 	int ret;
941f988d640SKalle Valo 
942f988d640SKalle Valo 	if (priv->psstate != PS_STATE_FULL_POWER) {
943f988d640SKalle Valo 		ret = -1;
944f988d640SKalle Valo 		goto out;
945f988d640SKalle Valo 	}
946f988d640SKalle Valo 
947f988d640SKalle Valo #ifdef CONFIG_OLPC
948f988d640SKalle Valo 	if (machine_is_olpc()) {
949f988d640SKalle Valo 		if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
950f988d640SKalle Valo 			olpc_ec_wakeup_clear(EC_SCI_SRC_WLAN);
951f988d640SKalle Valo 		else
952f988d640SKalle Valo 			olpc_ec_wakeup_set(EC_SCI_SRC_WLAN);
953f988d640SKalle Valo 	}
954f988d640SKalle Valo #endif
955f988d640SKalle Valo 
956f988d640SKalle Valo 	ret = lbs_suspend(priv);
957f988d640SKalle Valo 	if (ret)
958f988d640SKalle Valo 		goto out;
959f988d640SKalle Valo 
960f988d640SKalle Valo 	/* Unlink tx & rx urb */
961f988d640SKalle Valo 	usb_kill_urb(cardp->tx_urb);
962f988d640SKalle Valo 	usb_kill_urb(cardp->rx_urb);
963f988d640SKalle Valo 
964f988d640SKalle Valo  out:
965f988d640SKalle Valo 	return ret;
966f988d640SKalle Valo }
967f988d640SKalle Valo 
if_usb_resume(struct usb_interface * intf)968f988d640SKalle Valo static int if_usb_resume(struct usb_interface *intf)
969f988d640SKalle Valo {
970f988d640SKalle Valo 	struct if_usb_card *cardp = usb_get_intfdata(intf);
971f988d640SKalle Valo 	struct lbs_private *priv = cardp->priv;
972f988d640SKalle Valo 
973f988d640SKalle Valo 	if_usb_submit_rx_urb(cardp);
974f988d640SKalle Valo 
975f988d640SKalle Valo 	lbs_resume(priv);
976f988d640SKalle Valo 
977f988d640SKalle Valo 	return 0;
978f988d640SKalle Valo }
979f988d640SKalle Valo #else
980f988d640SKalle Valo #define if_usb_suspend NULL
981f988d640SKalle Valo #define if_usb_resume NULL
982f988d640SKalle Valo #endif
983f988d640SKalle Valo 
984f988d640SKalle Valo static struct usb_driver if_usb_driver = {
985f988d640SKalle Valo 	.name = DRV_NAME,
986f988d640SKalle Valo 	.probe = if_usb_probe,
987f988d640SKalle Valo 	.disconnect = if_usb_disconnect,
988f988d640SKalle Valo 	.id_table = if_usb_table,
989f988d640SKalle Valo 	.suspend = if_usb_suspend,
990f988d640SKalle Valo 	.resume = if_usb_resume,
991f988d640SKalle Valo 	.reset_resume = if_usb_resume,
992f988d640SKalle Valo 	.disable_hub_initiated_lpm = 1,
993f988d640SKalle Valo };
994f988d640SKalle Valo 
995f988d640SKalle Valo module_usb_driver(if_usb_driver);
996f988d640SKalle Valo 
997f988d640SKalle Valo MODULE_DESCRIPTION("8388 USB WLAN Driver");
998f988d640SKalle Valo MODULE_AUTHOR("Marvell International Ltd. and Red Hat, Inc.");
999f988d640SKalle Valo MODULE_LICENSE("GPL");
1000