libertas_tf: move under marvell vendor directory
authorKalle Valo <kvalo@codeaurora.org>
Tue, 17 Nov 2015 19:11:21 +0000 (21:11 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 18 Nov 2015 12:28:30 +0000 (14:28 +0200)
Part of reorganising wireless drivers directory and Kconfig.

Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
19 files changed:
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/libertas_tf/Makefile [deleted file]
drivers/net/wireless/libertas_tf/cmd.c [deleted file]
drivers/net/wireless/libertas_tf/deb_defs.h [deleted file]
drivers/net/wireless/libertas_tf/if_usb.c [deleted file]
drivers/net/wireless/libertas_tf/if_usb.h [deleted file]
drivers/net/wireless/libertas_tf/libertas_tf.h [deleted file]
drivers/net/wireless/libertas_tf/main.c [deleted file]
drivers/net/wireless/marvell/Kconfig
drivers/net/wireless/marvell/Makefile
drivers/net/wireless/marvell/libertas_tf/Kconfig [new file with mode: 0644]
drivers/net/wireless/marvell/libertas_tf/Makefile [new file with mode: 0644]
drivers/net/wireless/marvell/libertas_tf/cmd.c [new file with mode: 0644]
drivers/net/wireless/marvell/libertas_tf/deb_defs.h [new file with mode: 0644]
drivers/net/wireless/marvell/libertas_tf/if_usb.c [new file with mode: 0644]
drivers/net/wireless/marvell/libertas_tf/if_usb.h [new file with mode: 0644]
drivers/net/wireless/marvell/libertas_tf/libertas_tf.h [new file with mode: 0644]
drivers/net/wireless/marvell/libertas_tf/main.c [new file with mode: 0644]

index b11a2d3642008308e530d5b65dab12738355633e..25f52b32d725a08a49ae7c835c215b9d1df75c7b 100644 (file)
@@ -40,25 +40,6 @@ config PCMCIA_RAYCS
          To compile this driver as a module, choose M here: the module will be
          called ray_cs.  If unsure, say N.
 
-config LIBERTAS_THINFIRM
-       tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware"
-       depends on MAC80211
-       select FW_LOADER
-       ---help---
-         A library for Marvell Libertas 8xxx devices using thinfirm.
-
-config LIBERTAS_THINFIRM_DEBUG
-       bool "Enable full debugging output in the Libertas thin firmware module."
-       depends on LIBERTAS_THINFIRM
-       ---help---
-         Debugging support.
-
-config LIBERTAS_THINFIRM_USB
-       tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware"
-       depends on LIBERTAS_THINFIRM && USB
-       ---help---
-         A driver for Marvell Libertas 8388 USB devices using thinfirm.
-
 config PCMCIA_WL3501
        tristate "Planet WL3501 PCMCIA cards"
        depends on CFG80211 && PCMCIA
index a974a6edb4b68461edb447cb1d33f4392af69890..72b167742ac7efed9c3125c0c9970c08f6344245 100644 (file)
@@ -26,8 +26,6 @@ obj-$(CONFIG_USB_NET_RNDIS_WLAN)      += rndis_wlan.o
 
 obj-$(CONFIG_USB_ZD1201)       += zd1201.o
 
-obj-$(CONFIG_LIBERTAS_THINFIRM)        += libertas_tf/
-
 obj-$(CONFIG_MWL8K)    += mwl8k.o
 
 obj-$(CONFIG_RT2X00)   += rt2x00/
diff --git a/drivers/net/wireless/libertas_tf/Makefile b/drivers/net/wireless/libertas_tf/Makefile
deleted file mode 100644 (file)
index ff5544d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-libertas_tf-objs := main.o cmd.o
-
-libertas_tf_usb-objs += if_usb.o
-
-obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf.o
-obj-$(CONFIG_LIBERTAS_THINFIRM_USB) += libertas_tf_usb.o
diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c
deleted file mode 100644 (file)
index 909ac36..0000000
+++ /dev/null
@@ -1,807 +0,0 @@
-/*
- *  Copyright (C) 2008, cozybit Inc.
- *  Copyright (C) 2003-2006, Marvell International Ltd.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/hardirq.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-
-#include "libertas_tf.h"
-
-static const struct channel_range channel_ranges[] = {
-       { LBTF_REGDOMAIN_US,            1, 12 },
-       { LBTF_REGDOMAIN_CA,            1, 12 },
-       { LBTF_REGDOMAIN_EU,            1, 14 },
-       { LBTF_REGDOMAIN_JP,            1, 14 },
-       { LBTF_REGDOMAIN_SP,            1, 14 },
-       { LBTF_REGDOMAIN_FR,            1, 14 },
-};
-
-static u16 lbtf_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
-{
-       LBTF_REGDOMAIN_US, LBTF_REGDOMAIN_CA, LBTF_REGDOMAIN_EU,
-       LBTF_REGDOMAIN_SP, LBTF_REGDOMAIN_FR, LBTF_REGDOMAIN_JP,
-};
-
-static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv);
-
-
-/**
- *  lbtf_cmd_copyback - Simple callback that copies response back into command
- *
- *  @priv      A pointer to struct lbtf_private structure
- *  @extra     A pointer to the original command structure for which
- *             'resp' is a response
- *  @resp      A pointer to the command response
- *
- *  Returns: 0 on success, error on failure
- */
-int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra,
-                    struct cmd_header *resp)
-{
-       struct cmd_header *buf = (void *)extra;
-       uint16_t copy_len;
-
-       copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
-       memcpy(buf, resp, copy_len);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(lbtf_cmd_copyback);
-
-#define CHAN_TO_IDX(chan) ((chan) - 1)
-
-static void lbtf_geo_init(struct lbtf_private *priv)
-{
-       const struct channel_range *range = channel_ranges;
-       u8 ch;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(channel_ranges); i++)
-               if (channel_ranges[i].regdomain == priv->regioncode) {
-                       range = &channel_ranges[i];
-                       break;
-               }
-
-       for (ch = priv->range.start; ch < priv->range.end; ch++)
-               priv->channels[CHAN_TO_IDX(ch)].flags = 0;
-}
-
-/**
- *  lbtf_update_hw_spec: Updates the hardware details.
- *
- *  @priv      A pointer to struct lbtf_private structure
- *
- *  Returns: 0 on success, error on failure
- */
-int lbtf_update_hw_spec(struct lbtf_private *priv)
-{
-       struct cmd_ds_get_hw_spec cmd;
-       int ret = -1;
-       u32 i;
-
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       memset(&cmd, 0, sizeof(cmd));
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-       memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
-       ret = lbtf_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
-       if (ret)
-               goto out;
-
-       priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
-
-       /* The firmware release is in an interesting format: the patch
-        * level is in the most significant nibble ... so fix that: */
-       priv->fwrelease = le32_to_cpu(cmd.fwrelease);
-       priv->fwrelease = (priv->fwrelease << 8) |
-               (priv->fwrelease >> 24 & 0xff);
-
-       printk(KERN_INFO "libertastf: %pM, fw %u.%u.%up%u, cap 0x%08x\n",
-               cmd.permanentaddr,
-               priv->fwrelease >> 24 & 0xff,
-               priv->fwrelease >> 16 & 0xff,
-               priv->fwrelease >>  8 & 0xff,
-               priv->fwrelease       & 0xff,
-               priv->fwcapinfo);
-       lbtf_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
-                   cmd.hwifversion, cmd.version);
-
-       /* Clamp region code to 8-bit since FW spec indicates that it should
-        * only ever be 8-bit, even though the field size is 16-bit.  Some
-        * firmware returns non-zero high 8 bits here.
-        */
-       priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
-
-       for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
-               /* use the region code to search for the index */
-               if (priv->regioncode == lbtf_region_code_to_index[i])
-                       break;
-       }
-
-       /* if it's unidentified region code, use the default (USA) */
-       if (i >= MRVDRV_MAX_REGION_CODE) {
-               priv->regioncode = 0x10;
-               pr_info("unidentified region code; using the default (USA)\n");
-       }
-
-       if (priv->current_addr[0] == 0xff)
-               memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
-
-       SET_IEEE80211_PERM_ADDR(priv->hw, priv->current_addr);
-
-       lbtf_geo_init(priv);
-out:
-       lbtf_deb_leave(LBTF_DEB_CMD);
-       return ret;
-}
-
-/**
- *  lbtf_set_channel: Set the radio channel
- *
- *  @priv      A pointer to struct lbtf_private structure
- *  @channel   The desired channel, or 0 to clear a locked channel
- *
- *  Returns: 0 on success, error on failure
- */
-int lbtf_set_channel(struct lbtf_private *priv, u8 channel)
-{
-       int ret = 0;
-       struct cmd_ds_802_11_rf_channel cmd;
-
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-       cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
-       cmd.channel = cpu_to_le16(channel);
-
-       ret = lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
-       lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
-       return ret;
-}
-
-int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
-{
-       struct cmd_ds_802_11_beacon_set cmd;
-       int size;
-
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       if (beacon->len > MRVL_MAX_BCN_SIZE) {
-               lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", -1);
-               return -1;
-       }
-       size =  sizeof(cmd) - sizeof(cmd.beacon) + beacon->len;
-       cmd.hdr.size = cpu_to_le16(size);
-       cmd.len = cpu_to_le16(beacon->len);
-       memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len);
-
-       lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size);
-
-       lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", 0);
-       return 0;
-}
-
-int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
-                    int beacon_int)
-{
-       struct cmd_ds_802_11_beacon_control cmd;
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-       cmd.action = cpu_to_le16(CMD_ACT_SET);
-       cmd.beacon_enable = cpu_to_le16(beacon_enable);
-       cmd.beacon_period = cpu_to_le16(beacon_int);
-
-       lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd));
-
-       lbtf_deb_leave(LBTF_DEB_CMD);
-       return 0;
-}
-
-static void lbtf_queue_cmd(struct lbtf_private *priv,
-                         struct cmd_ctrl_node *cmdnode)
-{
-       unsigned long flags;
-       lbtf_deb_enter(LBTF_DEB_HOST);
-
-       if (!cmdnode) {
-               lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n");
-               goto qcmd_done;
-       }
-
-       if (!cmdnode->cmdbuf->size) {
-               lbtf_deb_host("DNLD_CMD: cmd size is zero\n");
-               goto qcmd_done;
-       }
-
-       cmdnode->result = 0;
-       spin_lock_irqsave(&priv->driver_lock, flags);
-       list_add_tail(&cmdnode->list, &priv->cmdpendingq);
-       spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-       lbtf_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
-                    le16_to_cpu(cmdnode->cmdbuf->command));
-
-qcmd_done:
-       lbtf_deb_leave(LBTF_DEB_HOST);
-}
-
-static void lbtf_submit_command(struct lbtf_private *priv,
-                              struct cmd_ctrl_node *cmdnode)
-{
-       unsigned long flags;
-       struct cmd_header *cmd;
-       uint16_t cmdsize;
-       uint16_t command;
-       int timeo = 5 * HZ;
-       int ret;
-
-       lbtf_deb_enter(LBTF_DEB_HOST);
-
-       cmd = cmdnode->cmdbuf;
-
-       spin_lock_irqsave(&priv->driver_lock, flags);
-       priv->cur_cmd = cmdnode;
-       cmdsize = le16_to_cpu(cmd->size);
-       command = le16_to_cpu(cmd->command);
-
-       lbtf_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
-                    command, le16_to_cpu(cmd->seqnum), cmdsize);
-       lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
-
-       ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
-       spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-       if (ret) {
-               pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
-               /* Let the timer kick in and retry, and potentially reset
-                  the whole thing if the condition persists */
-               timeo = HZ;
-       }
-
-       /* Setup the timer after transmit command */
-       mod_timer(&priv->command_timer, jiffies + timeo);
-
-       lbtf_deb_leave(LBTF_DEB_HOST);
-}
-
-/**
- *  This function inserts command node to cmdfreeq
- *  after cleans it. Requires priv->driver_lock held.
- */
-static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
-                                        struct cmd_ctrl_node *cmdnode)
-{
-       lbtf_deb_enter(LBTF_DEB_HOST);
-
-       if (!cmdnode)
-               goto cl_ins_out;
-
-       cmdnode->callback = NULL;
-       cmdnode->callback_arg = 0;
-
-       memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
-
-       list_add_tail(&cmdnode->list, &priv->cmdfreeq);
-
-cl_ins_out:
-       lbtf_deb_leave(LBTF_DEB_HOST);
-}
-
-static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
-       struct cmd_ctrl_node *ptempcmd)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->driver_lock, flags);
-       __lbtf_cleanup_and_insert_cmd(priv, ptempcmd);
-       spin_unlock_irqrestore(&priv->driver_lock, flags);
-}
-
-void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd,
-                         int result)
-{
-       cmd->result = result;
-       cmd->cmdwaitqwoken = 1;
-       wake_up_interruptible(&cmd->cmdwait_q);
-
-       if (!cmd->callback)
-               __lbtf_cleanup_and_insert_cmd(priv, cmd);
-       priv->cur_cmd = NULL;
-}
-
-int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv)
-{
-       struct cmd_ds_mac_multicast_addr cmd;
-
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-       cmd.action = cpu_to_le16(CMD_ACT_SET);
-
-       cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
-
-       lbtf_deb_cmd("MULTICAST_ADR: setting %d addresses\n", cmd.nr_of_adrs);
-
-       memcpy(cmd.maclist, priv->multicastlist,
-              priv->nr_of_multicastmacaddr * ETH_ALEN);
-
-       lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd));
-
-       lbtf_deb_leave(LBTF_DEB_CMD);
-       return 0;
-}
-
-void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)
-{
-       struct cmd_ds_set_mode cmd;
-       lbtf_deb_enter(LBTF_DEB_WEXT);
-
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-       cmd.mode = cpu_to_le16(mode);
-       lbtf_deb_wext("Switching to mode: 0x%x\n", mode);
-       lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd));
-
-       lbtf_deb_leave(LBTF_DEB_WEXT);
-}
-
-void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
-{
-       struct cmd_ds_set_bssid cmd;
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-       cmd.activate = activate ? 1 : 0;
-       if (activate)
-               memcpy(cmd.bssid, bssid, ETH_ALEN);
-
-       lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd));
-       lbtf_deb_leave(LBTF_DEB_CMD);
-}
-
-int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
-{
-       struct cmd_ds_802_11_mac_address cmd;
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-       cmd.action = cpu_to_le16(CMD_ACT_SET);
-
-       memcpy(cmd.macadd, mac_addr, ETH_ALEN);
-
-       lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd));
-       lbtf_deb_leave(LBTF_DEB_CMD);
-       return 0;
-}
-
-int lbtf_set_radio_control(struct lbtf_private *priv)
-{
-       int ret = 0;
-       struct cmd_ds_802_11_radio_control cmd;
-
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-       cmd.action = cpu_to_le16(CMD_ACT_SET);
-
-       switch (priv->preamble) {
-       case CMD_TYPE_SHORT_PREAMBLE:
-               cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE);
-               break;
-
-       case CMD_TYPE_LONG_PREAMBLE:
-               cmd.control = cpu_to_le16(SET_LONG_PREAMBLE);
-               break;
-
-       case CMD_TYPE_AUTO_PREAMBLE:
-       default:
-               cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE);
-               break;
-       }
-
-       if (priv->radioon)
-               cmd.control |= cpu_to_le16(TURN_ON_RF);
-       else
-               cmd.control &= cpu_to_le16(~TURN_ON_RF);
-
-       lbtf_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
-                   priv->preamble);
-
-       ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
-
-       lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
-       return ret;
-}
-
-void lbtf_set_mac_control(struct lbtf_private *priv)
-{
-       struct cmd_ds_mac_control cmd;
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-       cmd.action = cpu_to_le16(priv->mac_control);
-       cmd.reserved = 0;
-
-       lbtf_cmd_async(priv, CMD_MAC_CONTROL,
-               &cmd.hdr, sizeof(cmd));
-
-       lbtf_deb_leave(LBTF_DEB_CMD);
-}
-
-/**
- *  lbtf_allocate_cmd_buffer - Allocates cmd buffer, links it to free cmd queue
- *
- *  @priv      A pointer to struct lbtf_private structure
- *
- *  Returns: 0 on success.
- */
-int lbtf_allocate_cmd_buffer(struct lbtf_private *priv)
-{
-       int ret = 0;
-       u32 bufsize;
-       u32 i;
-       struct cmd_ctrl_node *cmdarray;
-
-       lbtf_deb_enter(LBTF_DEB_HOST);
-
-       /* Allocate and initialize the command array */
-       bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
-       cmdarray = kzalloc(bufsize, GFP_KERNEL);
-       if (!cmdarray) {
-               lbtf_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
-               ret = -1;
-               goto done;
-       }
-       priv->cmd_array = cmdarray;
-
-       /* Allocate and initialize each command buffer in the command array */
-       for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
-               cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
-               if (!cmdarray[i].cmdbuf) {
-                       lbtf_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
-                       ret = -1;
-                       goto done;
-               }
-       }
-
-       for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
-               init_waitqueue_head(&cmdarray[i].cmdwait_q);
-               lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]);
-       }
-
-       ret = 0;
-
-done:
-       lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
-       return ret;
-}
-
-/**
- *  lbtf_free_cmd_buffer - Frees the cmd buffer.
- *
- *  @priv      A pointer to struct lbtf_private structure
- *
- *  Returns: 0
- */
-int lbtf_free_cmd_buffer(struct lbtf_private *priv)
-{
-       struct cmd_ctrl_node *cmdarray;
-       unsigned int i;
-
-       lbtf_deb_enter(LBTF_DEB_HOST);
-
-       /* need to check if cmd array is allocated or not */
-       if (priv->cmd_array == NULL) {
-               lbtf_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
-               goto done;
-       }
-
-       cmdarray = priv->cmd_array;
-
-       /* Release shared memory buffers */
-       for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
-               kfree(cmdarray[i].cmdbuf);
-               cmdarray[i].cmdbuf = NULL;
-       }
-
-       /* Release cmd_ctrl_node */
-       kfree(priv->cmd_array);
-       priv->cmd_array = NULL;
-
-done:
-       lbtf_deb_leave(LBTF_DEB_HOST);
-       return 0;
-}
-
-/**
- *  lbtf_get_cmd_ctrl_node - Gets free cmd node from free cmd queue.
- *
- *  @priv              A pointer to struct lbtf_private structure
- *
- *  Returns: pointer to a struct cmd_ctrl_node or NULL if none available.
- */
-static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)
-{
-       struct cmd_ctrl_node *tempnode;
-       unsigned long flags;
-
-       lbtf_deb_enter(LBTF_DEB_HOST);
-
-       if (!priv)
-               return NULL;
-
-       spin_lock_irqsave(&priv->driver_lock, flags);
-
-       if (!list_empty(&priv->cmdfreeq)) {
-               tempnode = list_first_entry(&priv->cmdfreeq,
-                                           struct cmd_ctrl_node, list);
-               list_del(&tempnode->list);
-       } else {
-               lbtf_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
-               tempnode = NULL;
-       }
-
-       spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-       lbtf_deb_leave(LBTF_DEB_HOST);
-       return tempnode;
-}
-
-/**
- *  lbtf_execute_next_command: execute next command in cmd pending queue.
- *
- *  @priv     A pointer to struct lbtf_private structure
- *
- *  Returns: 0 on success.
- */
-int lbtf_execute_next_command(struct lbtf_private *priv)
-{
-       struct cmd_ctrl_node *cmdnode = NULL;
-       struct cmd_header *cmd;
-       unsigned long flags;
-       int ret = 0;
-
-       /* Debug group is lbtf_deb_THREAD and not lbtf_deb_HOST, because the
-        * only caller to us is lbtf_thread() and we get even when a
-        * data packet is received */
-       lbtf_deb_enter(LBTF_DEB_THREAD);
-
-       spin_lock_irqsave(&priv->driver_lock, flags);
-
-       if (priv->cur_cmd) {
-               pr_alert("EXEC_NEXT_CMD: already processing command!\n");
-               spin_unlock_irqrestore(&priv->driver_lock, flags);
-               ret = -1;
-               goto done;
-       }
-
-       if (!list_empty(&priv->cmdpendingq)) {
-               cmdnode = list_first_entry(&priv->cmdpendingq,
-                                          struct cmd_ctrl_node, list);
-       }
-
-       if (cmdnode) {
-               cmd = cmdnode->cmdbuf;
-
-               list_del(&cmdnode->list);
-               lbtf_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
-                           le16_to_cpu(cmd->command));
-               spin_unlock_irqrestore(&priv->driver_lock, flags);
-               lbtf_submit_command(priv, cmdnode);
-       } else
-               spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-       ret = 0;
-done:
-       lbtf_deb_leave(LBTF_DEB_THREAD);
-       return ret;
-}
-
-static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
-       uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
-       int (*callback)(struct lbtf_private *, unsigned long,
-                       struct cmd_header *),
-       unsigned long callback_arg)
-{
-       struct cmd_ctrl_node *cmdnode;
-
-       lbtf_deb_enter(LBTF_DEB_HOST);
-
-       if (priv->surpriseremoved) {
-               lbtf_deb_host("PREP_CMD: card removed\n");
-               cmdnode = ERR_PTR(-ENOENT);
-               goto done;
-       }
-
-       cmdnode = lbtf_get_cmd_ctrl_node(priv);
-       if (cmdnode == NULL) {
-               lbtf_deb_host("PREP_CMD: cmdnode is NULL\n");
-
-               /* Wake up main thread to execute next command */
-               queue_work(lbtf_wq, &priv->cmd_work);
-               cmdnode = ERR_PTR(-ENOBUFS);
-               goto done;
-       }
-
-       cmdnode->callback = callback;
-       cmdnode->callback_arg = callback_arg;
-
-       /* Copy the incoming command to the buffer */
-       memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
-
-       /* Set sequence number, clean result, move to buffer */
-       priv->seqnum++;
-       cmdnode->cmdbuf->command = cpu_to_le16(command);
-       cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
-       cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);
-       cmdnode->cmdbuf->result  = 0;
-
-       lbtf_deb_host("PREP_CMD: command 0x%04x\n", command);
-
-       cmdnode->cmdwaitqwoken = 0;
-       lbtf_queue_cmd(priv, cmdnode);
-       queue_work(lbtf_wq, &priv->cmd_work);
-
- done:
-       lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %p", cmdnode);
-       return cmdnode;
-}
-
-void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
-       struct cmd_header *in_cmd, int in_cmd_size)
-{
-       lbtf_deb_enter(LBTF_DEB_CMD);
-       __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0);
-       lbtf_deb_leave(LBTF_DEB_CMD);
-}
-
-int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
-             struct cmd_header *in_cmd, int in_cmd_size,
-             int (*callback)(struct lbtf_private *,
-                             unsigned long, struct cmd_header *),
-             unsigned long callback_arg)
-{
-       struct cmd_ctrl_node *cmdnode;
-       unsigned long flags;
-       int ret = 0;
-
-       lbtf_deb_enter(LBTF_DEB_HOST);
-
-       cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size,
-                                 callback, callback_arg);
-       if (IS_ERR(cmdnode)) {
-               ret = PTR_ERR(cmdnode);
-               goto done;
-       }
-
-       might_sleep();
-       ret = wait_event_interruptible(cmdnode->cmdwait_q,
-                                      cmdnode->cmdwaitqwoken);
-       if (ret) {
-               pr_info("PREP_CMD: command 0x%04x interrupted by signal: %d\n",
-                           command, ret);
-               goto done;
-       }
-
-       spin_lock_irqsave(&priv->driver_lock, flags);
-       ret = cmdnode->result;
-       if (ret)
-               pr_info("PREP_CMD: command 0x%04x failed: %d\n",
-                           command, ret);
-
-       __lbtf_cleanup_and_insert_cmd(priv, cmdnode);
-       spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-done:
-       lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(__lbtf_cmd);
-
-/* Call holding driver_lock */
-void lbtf_cmd_response_rx(struct lbtf_private *priv)
-{
-       priv->cmd_response_rxed = 1;
-       queue_work(lbtf_wq, &priv->cmd_work);
-}
-EXPORT_SYMBOL_GPL(lbtf_cmd_response_rx);
-
-int lbtf_process_rx_command(struct lbtf_private *priv)
-{
-       uint16_t respcmd, curcmd;
-       struct cmd_header *resp;
-       int ret = 0;
-       unsigned long flags;
-       uint16_t result;
-
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       mutex_lock(&priv->lock);
-       spin_lock_irqsave(&priv->driver_lock, flags);
-
-       if (!priv->cur_cmd) {
-               ret = -1;
-               spin_unlock_irqrestore(&priv->driver_lock, flags);
-               goto done;
-       }
-
-       resp = (void *)priv->cmd_resp_buff;
-       curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
-       respcmd = le16_to_cpu(resp->command);
-       result = le16_to_cpu(resp->result);
-
-       if (net_ratelimit())
-               pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n",
-                       respcmd, le16_to_cpu(resp->seqnum),
-                       le16_to_cpu(resp->size));
-
-       if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
-               spin_unlock_irqrestore(&priv->driver_lock, flags);
-               ret = -1;
-               goto done;
-       }
-       if (respcmd != CMD_RET(curcmd)) {
-               spin_unlock_irqrestore(&priv->driver_lock, flags);
-               ret = -1;
-               goto done;
-       }
-
-       if (resp->result == cpu_to_le16(0x0004)) {
-               /* 0x0004 means -EAGAIN. Drop the response, let it time out
-                  and be resubmitted */
-               spin_unlock_irqrestore(&priv->driver_lock, flags);
-               ret = -1;
-               goto done;
-       }
-
-       /* Now we got response from FW, cancel the command timer */
-       del_timer(&priv->command_timer);
-       priv->cmd_timed_out = 0;
-       if (priv->nr_retries)
-               priv->nr_retries = 0;
-
-       /* If the command is not successful, cleanup and return failure */
-       if ((result != 0 || !(respcmd & 0x8000))) {
-               /*
-                * Handling errors here
-                */
-               switch (respcmd) {
-               case CMD_RET(CMD_GET_HW_SPEC):
-               case CMD_RET(CMD_802_11_RESET):
-                       pr_info("libertastf: reset failed\n");
-                       break;
-
-               }
-               lbtf_complete_command(priv, priv->cur_cmd, result);
-               spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-               ret = -1;
-               goto done;
-       }
-
-       spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-       if (priv->cur_cmd && priv->cur_cmd->callback) {
-               ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
-                               resp);
-       }
-       spin_lock_irqsave(&priv->driver_lock, flags);
-
-       if (priv->cur_cmd) {
-               /* Clean up and Put current command back to cmdfreeq */
-               lbtf_complete_command(priv, priv->cur_cmd, result);
-       }
-       spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-done:
-       mutex_unlock(&priv->lock);
-       lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
-       return ret;
-}
diff --git a/drivers/net/wireless/libertas_tf/deb_defs.h b/drivers/net/wireless/libertas_tf/deb_defs.h
deleted file mode 100644 (file)
index 4bd3dc5..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
-  * This header file contains global constant/enum definitions,
-  * global variable declaration.
-  */
-#ifndef _LBS_DEB_DEFS_H_
-#define _LBS_DEB_DEFS_H_
-
-#ifndef DRV_NAME
-#define DRV_NAME "libertas_tf"
-#endif
-
-#include <linux/spinlock.h>
-
-#ifdef CONFIG_LIBERTAS_THINFIRM_DEBUG
-#define DEBUG
-#define PROC_DEBUG
-#endif
-
-#define LBTF_DEB_ENTER 0x00000001
-#define LBTF_DEB_LEAVE 0x00000002
-#define LBTF_DEB_MAIN  0x00000004
-#define LBTF_DEB_NET   0x00000008
-#define LBTF_DEB_MESH  0x00000010
-#define LBTF_DEB_WEXT  0x00000020
-#define LBTF_DEB_IOCTL 0x00000040
-#define LBTF_DEB_SCAN  0x00000080
-#define LBTF_DEB_ASSOC 0x00000100
-#define LBTF_DEB_JOIN  0x00000200
-#define LBTF_DEB_11D   0x00000400
-#define LBTF_DEB_DEBUGFS       0x00000800
-#define LBTF_DEB_ETHTOOL       0x00001000
-#define LBTF_DEB_HOST  0x00002000
-#define LBTF_DEB_CMD   0x00004000
-#define LBTF_DEB_RX    0x00008000
-#define LBTF_DEB_TX    0x00010000
-#define LBTF_DEB_USB   0x00020000
-#define LBTF_DEB_CS    0x00040000
-#define LBTF_DEB_FW    0x00080000
-#define LBTF_DEB_THREAD        0x00100000
-#define LBTF_DEB_HEX   0x00200000
-#define LBTF_DEB_SDIO  0x00400000
-#define LBTF_DEB_MACOPS        0x00800000
-
-extern unsigned int lbtf_debug;
-
-
-#ifdef DEBUG
-#define LBTF_DEB_LL(grp, grpnam, fmt, args...) \
-do { if ((lbtf_debug & (grp)) == (grp)) \
-  printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
-         in_interrupt() ? " (INT)" : "", ## args); } while (0)
-#else
-#define LBTF_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
-#endif
-
-#define lbtf_deb_enter(grp) \
-  LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s()\n", __func__);
-#define lbtf_deb_enter_args(grp, fmt, args...) \
-  LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
-#define lbtf_deb_leave(grp) \
-  LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s()\n", __func__);
-#define lbtf_deb_leave_args(grp, fmt, args...) \
-  LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
-  __func__, ##args);
-#define lbtf_deb_main(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MAIN, " main", fmt, ##args)
-#define lbtf_deb_net(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_NET, " net", fmt, ##args)
-#define lbtf_deb_mesh(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MESH, " mesh", fmt, ##args)
-#define lbtf_deb_wext(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_WEXT, " wext", fmt, ##args)
-#define lbtf_deb_ioctl(fmt, args...)     LBTF_DEB_LL(LBTF_DEB_IOCTL, " ioctl", fmt, ##args)
-#define lbtf_deb_scan(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_SCAN, " scan", fmt, ##args)
-#define lbtf_deb_assoc(fmt, args...)     LBTF_DEB_LL(LBTF_DEB_ASSOC, " assoc", fmt, ##args)
-#define lbtf_deb_join(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_JOIN, " join", fmt, ##args)
-#define lbtf_deb_11d(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_11D, " 11d", fmt, ##args)
-#define lbtf_deb_debugfs(fmt, args...)   LBTF_DEB_LL(LBTF_DEB_DEBUGFS, " debugfs", fmt, ##args)
-#define lbtf_deb_ethtool(fmt, args...)   LBTF_DEB_LL(LBTF_DEB_ETHTOOL, " ethtool", fmt, ##args)
-#define lbtf_deb_host(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_HOST, " host", fmt, ##args)
-#define lbtf_deb_cmd(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_CMD, " cmd", fmt, ##args)
-#define lbtf_deb_rx(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_RX, " rx", fmt, ##args)
-#define lbtf_deb_tx(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_TX, " tx", fmt, ##args)
-#define lbtf_deb_fw(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_FW, " fw", fmt, ##args)
-#define lbtf_deb_usb(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_USB, " usb", fmt, ##args)
-#define lbtf_deb_usbd(dev, fmt, args...) LBTF_DEB_LL(LBTF_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args)
-#define lbtf_deb_cs(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_CS, " cs", fmt, ##args)
-#define lbtf_deb_thread(fmt, args...)    LBTF_DEB_LL(LBTF_DEB_THREAD, " thread", fmt, ##args)
-#define lbtf_deb_sdio(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_SDIO, " thread", fmt, ##args)
-#define lbtf_deb_macops(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MACOPS, " thread", fmt, ##args)
-
-#ifdef DEBUG
-static inline void lbtf_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)
-{
-       char newprompt[32];
-
-       if (len &&
-           (lbtf_debug & LBTF_DEB_HEX) &&
-           (lbtf_debug & grp)) {
-               snprintf(newprompt, sizeof(newprompt), DRV_NAME " %s: ", prompt);
-               print_hex_dump_bytes(prompt, DUMP_PREFIX_NONE, buf, len);
-       }
-}
-#else
-#define lbtf_deb_hex(grp, prompt, buf, len)    do {} while (0)
-#endif
-
-#endif
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
deleted file mode 100644 (file)
index 799a2ef..0000000
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- *  Copyright (C) 2008, cozybit Inc.
- *  Copyright (C) 2003-2006, Marvell International Ltd.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- */
-#define DRV_NAME "lbtf_usb"
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "libertas_tf.h"
-#include "if_usb.h"
-
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/netdevice.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#define INSANEDEBUG    0
-#define lbtf_deb_usb2(...) do { if (INSANEDEBUG) lbtf_deb_usbd(__VA_ARGS__); } while (0)
-
-#define MESSAGE_HEADER_LEN     4
-
-static char *lbtf_fw_name = "lbtf_usb.bin";
-module_param_named(fw_name, lbtf_fw_name, charp, 0644);
-
-MODULE_FIRMWARE("lbtf_usb.bin");
-
-static struct usb_device_id if_usb_table[] = {
-       /* Enter the device signature inside */
-       { USB_DEVICE(0x1286, 0x2001) },
-       { USB_DEVICE(0x05a3, 0x8388) },
-       {}      /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, if_usb_table);
-
-static void if_usb_receive(struct urb *urb);
-static void if_usb_receive_fwload(struct urb *urb);
-static int if_usb_prog_firmware(struct if_usb_card *cardp);
-static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
-                              uint8_t *payload, uint16_t nb);
-static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
-                       uint16_t nb, u8 data);
-static void if_usb_free(struct if_usb_card *cardp);
-static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
-static int if_usb_reset_device(struct if_usb_card *cardp);
-
-/**
- *  if_usb_wrike_bulk_callback -  call back to handle URB status
- *
- *  @param urb         pointer to urb structure
- */
-static void if_usb_write_bulk_callback(struct urb *urb)
-{
-       if (urb->status != 0) {
-               /* print the failure status number for debug */
-               pr_info("URB in failure status: %d\n", urb->status);
-       } else {
-               lbtf_deb_usb2(&urb->dev->dev, "URB status is successful\n");
-               lbtf_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
-                            urb->actual_length);
-       }
-}
-
-/**
- *  if_usb_free - free tx/rx urb, skb and rx buffer
- *
- *  @param cardp       pointer if_usb_card
- */
-static void if_usb_free(struct if_usb_card *cardp)
-{
-       lbtf_deb_enter(LBTF_DEB_USB);
-
-       /* Unlink tx & rx urb */
-       usb_kill_urb(cardp->tx_urb);
-       usb_kill_urb(cardp->rx_urb);
-       usb_kill_urb(cardp->cmd_urb);
-
-       usb_free_urb(cardp->tx_urb);
-       cardp->tx_urb = NULL;
-
-       usb_free_urb(cardp->rx_urb);
-       cardp->rx_urb = NULL;
-
-       usb_free_urb(cardp->cmd_urb);
-       cardp->cmd_urb = NULL;
-
-       kfree(cardp->ep_out_buf);
-       cardp->ep_out_buf = NULL;
-
-       lbtf_deb_leave(LBTF_DEB_USB);
-}
-
-static void if_usb_setup_firmware(struct lbtf_private *priv)
-{
-       struct if_usb_card *cardp = priv->card;
-       struct cmd_ds_set_boot2_ver b2_cmd;
-
-       lbtf_deb_enter(LBTF_DEB_USB);
-
-       if_usb_submit_rx_urb(cardp);
-       b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
-       b2_cmd.action = 0;
-       b2_cmd.version = cardp->boot2_version;
-
-       if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
-               lbtf_deb_usb("Setting boot2 version failed\n");
-
-       lbtf_deb_leave(LBTF_DEB_USB);
-}
-
-static void if_usb_fw_timeo(unsigned long priv)
-{
-       struct if_usb_card *cardp = (void *)priv;
-
-       lbtf_deb_enter(LBTF_DEB_USB);
-       if (!cardp->fwdnldover) {
-               /* Download timed out */
-               cardp->priv->surpriseremoved = 1;
-               pr_err("Download timed out\n");
-       } else {
-               lbtf_deb_usb("Download complete, no event. Assuming success\n");
-       }
-       wake_up(&cardp->fw_wq);
-       lbtf_deb_leave(LBTF_DEB_USB);
-}
-
-/**
- *  if_usb_probe - sets the configuration values
- *
- *  @ifnum     interface number
- *  @id                pointer to usb_device_id
- *
- *  Returns: 0 on success, error code on failure
- */
-static int if_usb_probe(struct usb_interface *intf,
-                       const struct usb_device_id *id)
-{
-       struct usb_device *udev;
-       struct usb_host_interface *iface_desc;
-       struct usb_endpoint_descriptor *endpoint;
-       struct lbtf_private *priv;
-       struct if_usb_card *cardp;
-       int i;
-
-       lbtf_deb_enter(LBTF_DEB_USB);
-       udev = interface_to_usbdev(intf);
-
-       cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
-       if (!cardp)
-               goto error;
-
-       setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
-       init_waitqueue_head(&cardp->fw_wq);
-
-       cardp->udev = udev;
-       iface_desc = intf->cur_altsetting;
-
-       lbtf_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
-                    " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
-                    le16_to_cpu(udev->descriptor.bcdUSB),
-                    udev->descriptor.bDeviceClass,
-                    udev->descriptor.bDeviceSubClass,
-                    udev->descriptor.bDeviceProtocol);
-
-       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-               endpoint = &iface_desc->endpoint[i].desc;
-               if (usb_endpoint_is_bulk_in(endpoint)) {
-                       cardp->ep_in_size =
-                               le16_to_cpu(endpoint->wMaxPacketSize);
-                       cardp->ep_in = usb_endpoint_num(endpoint);
-
-                       lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n",
-                               cardp->ep_in);
-                       lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n",
-                               cardp->ep_in_size);
-               } else if (usb_endpoint_is_bulk_out(endpoint)) {
-                       cardp->ep_out_size =
-                               le16_to_cpu(endpoint->wMaxPacketSize);
-                       cardp->ep_out = usb_endpoint_num(endpoint);
-
-                       lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n",
-                               cardp->ep_out);
-                       lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n",
-                               cardp->ep_out_size);
-               }
-       }
-       if (!cardp->ep_out_size || !cardp->ep_in_size) {
-               lbtf_deb_usbd(&udev->dev, "Endpoints not found\n");
-               /* Endpoints not found */
-               goto dealloc;
-       }
-
-       cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!cardp->rx_urb) {
-               lbtf_deb_usbd(&udev->dev, "Rx URB allocation failed\n");
-               goto dealloc;
-       }
-
-       cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!cardp->tx_urb) {
-               lbtf_deb_usbd(&udev->dev, "Tx URB allocation failed\n");
-               goto dealloc;
-       }
-
-       cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!cardp->cmd_urb) {
-               lbtf_deb_usbd(&udev->dev, "Cmd URB allocation failed\n");
-               goto dealloc;
-       }
-
-       cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
-                                   GFP_KERNEL);
-       if (!cardp->ep_out_buf) {
-               lbtf_deb_usbd(&udev->dev, "Could not allocate buffer\n");
-               goto dealloc;
-       }
-
-       priv = lbtf_add_card(cardp, &udev->dev);
-       if (!priv)
-               goto dealloc;
-
-       cardp->priv = priv;
-
-       priv->hw_host_to_card = if_usb_host_to_card;
-       priv->hw_prog_firmware = if_usb_prog_firmware;
-       priv->hw_reset_device = if_usb_reset_device;
-       cardp->boot2_version = udev->descriptor.bcdDevice;
-
-       usb_get_dev(udev);
-       usb_set_intfdata(intf, cardp);
-
-       return 0;
-
-dealloc:
-       if_usb_free(cardp);
-error:
-lbtf_deb_leave(LBTF_DEB_MAIN);
-       return -ENOMEM;
-}
-
-/**
- *  if_usb_disconnect -  free resource and cleanup
- *
- *  @intf      USB interface structure
- */
-static void if_usb_disconnect(struct usb_interface *intf)
-{
-       struct if_usb_card *cardp = usb_get_intfdata(intf);
-       struct lbtf_private *priv = cardp->priv;
-
-       lbtf_deb_enter(LBTF_DEB_MAIN);
-
-       if_usb_reset_device(cardp);
-
-       if (priv)
-               lbtf_remove_card(priv);
-
-       /* Unlink and free urb */
-       if_usb_free(cardp);
-
-       usb_set_intfdata(intf, NULL);
-       usb_put_dev(interface_to_usbdev(intf));
-
-       lbtf_deb_leave(LBTF_DEB_MAIN);
-}
-
-/**
- *  if_usb_send_fw_pkt -  This function downloads the FW
- *
- *  @priv      pointer to struct lbtf_private
- *
- *  Returns: 0
- */
-static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
-{
-       struct fwdata *fwdata = cardp->ep_out_buf;
-       u8 *firmware = (u8 *) cardp->fw->data;
-
-       lbtf_deb_enter(LBTF_DEB_FW);
-
-       /* If we got a CRC failure on the last block, back
-          up and retry it */
-       if (!cardp->CRC_OK) {
-               cardp->totalbytes = cardp->fwlastblksent;
-               cardp->fwseqnum--;
-       }
-
-       lbtf_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n",
-                    cardp->totalbytes);
-
-       /* struct fwdata (which we sent to the card) has an
-          extra __le32 field in between the header and the data,
-          which is not in the struct fwheader in the actual
-          firmware binary. Insert the seqnum in the middle... */
-       memcpy(&fwdata->hdr, &firmware[cardp->totalbytes],
-              sizeof(struct fwheader));
-
-       cardp->fwlastblksent = cardp->totalbytes;
-       cardp->totalbytes += sizeof(struct fwheader);
-
-       memcpy(fwdata->data, &firmware[cardp->totalbytes],
-              le32_to_cpu(fwdata->hdr.datalength));
-
-       lbtf_deb_usb2(&cardp->udev->dev, "Data length = %d\n",
-                    le32_to_cpu(fwdata->hdr.datalength));
-
-       fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
-       cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
-
-       usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
-                    le32_to_cpu(fwdata->hdr.datalength), 0);
-
-       if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
-               lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
-               lbtf_deb_usb2(&cardp->udev->dev,
-                       "seqnum = %d totalbytes = %d\n",
-                       cardp->fwseqnum, cardp->totalbytes);
-       } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
-               lbtf_deb_usb2(&cardp->udev->dev,
-                       "Host has finished FW downloading\n");
-               lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n");
-
-               /* Host has finished FW downloading
-                * Donwloading FW JUMP BLOCK
-                */
-               cardp->fwfinalblk = 1;
-       }
-
-       lbtf_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n",
-                    cardp->totalbytes);
-
-       lbtf_deb_leave(LBTF_DEB_FW);
-       return 0;
-}
-
-static int if_usb_reset_device(struct if_usb_card *cardp)
-{
-       struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
-       int ret;
-
-       lbtf_deb_enter(LBTF_DEB_USB);
-
-       *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
-
-       cmd->hdr.command = cpu_to_le16(CMD_802_11_RESET);
-       cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset));
-       cmd->hdr.result = cpu_to_le16(0);
-       cmd->hdr.seqnum = cpu_to_le16(0x5a5a);
-       cmd->action = cpu_to_le16(CMD_ACT_HALT);
-       usb_tx_block(cardp, cardp->ep_out_buf,
-                    4 + sizeof(struct cmd_ds_802_11_reset), 0);
-
-       msleep(100);
-       ret = usb_reset_device(cardp->udev);
-       msleep(100);
-
-       lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret);
-
-       return ret;
-}
-
-/**
- *  usb_tx_block - transfer data to the device
- *
- *  @priv      pointer to struct lbtf_private
- *  @payload   pointer to payload data
- *  @nb                data length
- *  @data      non-zero for data, zero for commands
- *
- *  Returns: 0 on success, nonzero otherwise.
- */
-static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
-                       uint16_t nb, u8 data)
-{
-       int ret = -1;
-       struct urb *urb;
-
-       lbtf_deb_enter(LBTF_DEB_USB);
-       /* check if device is removed */
-       if (cardp->priv->surpriseremoved) {
-               lbtf_deb_usbd(&cardp->udev->dev, "Device removed\n");
-               goto tx_ret;
-       }
-
-       if (data)
-               urb = cardp->tx_urb;
-       else
-               urb = cardp->cmd_urb;
-
-       usb_fill_bulk_urb(urb, cardp->udev,
-                         usb_sndbulkpipe(cardp->udev,
-                                         cardp->ep_out),
-                         payload, nb, if_usb_write_bulk_callback, cardp);
-
-       urb->transfer_flags |= URB_ZERO_PACKET;
-
-       if (usb_submit_urb(urb, GFP_ATOMIC)) {
-               lbtf_deb_usbd(&cardp->udev->dev,
-                       "usb_submit_urb failed: %d\n", ret);
-               goto tx_ret;
-       }
-
-       lbtf_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
-
-       ret = 0;
-
-tx_ret:
-       lbtf_deb_leave(LBTF_DEB_USB);
-       return ret;
-}
-
-static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
-                                 void (*callbackfn)(struct urb *urb))
-{
-       struct sk_buff *skb;
-       int ret = -1;
-
-       lbtf_deb_enter(LBTF_DEB_USB);
-
-       skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
-       if (!skb) {
-               pr_err("No free skb\n");
-               lbtf_deb_leave(LBTF_DEB_USB);
-               return -1;
-       }
-
-       cardp->rx_skb = skb;
-
-       /* Fill the receive configuration URB and initialise the Rx call back */
-       usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
-                         usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
-                         skb_tail_pointer(skb),
-                         MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp);
-
-       cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
-
-       lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n",
-               cardp->rx_urb);
-       ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC);
-       if (ret) {
-               lbtf_deb_usbd(&cardp->udev->dev,
-                       "Submit Rx URB failed: %d\n", ret);
-               kfree_skb(skb);
-               cardp->rx_skb = NULL;
-               lbtf_deb_leave(LBTF_DEB_USB);
-               return -1;
-       } else {
-               lbtf_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n");
-               lbtf_deb_leave(LBTF_DEB_USB);
-               return 0;
-       }
-}
-
-static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
-{
-       return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
-}
-
-static int if_usb_submit_rx_urb(struct if_usb_card *cardp)
-{
-       return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
-}
-
-static void if_usb_receive_fwload(struct urb *urb)
-{
-       struct if_usb_card *cardp = urb->context;
-       struct sk_buff *skb = cardp->rx_skb;
-       struct fwsyncheader *syncfwheader;
-       struct bootcmdresp bcmdresp;
-
-       lbtf_deb_enter(LBTF_DEB_USB);
-       if (urb->status) {
-               lbtf_deb_usbd(&cardp->udev->dev,
-                            "URB status is failed during fw load\n");
-               kfree_skb(skb);
-               lbtf_deb_leave(LBTF_DEB_USB);
-               return;
-       }
-
-       if (cardp->fwdnldover) {
-               __le32 *tmp = (__le32 *)(skb->data);
-
-               if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) &&
-                   tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) {
-                       /* Firmware ready event received */
-                       pr_info("Firmware ready event received\n");
-                       wake_up(&cardp->fw_wq);
-               } else {
-                       lbtf_deb_usb("Waiting for confirmation; got %x %x\n",
-                                   le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1]));
-                       if_usb_submit_rx_urb_fwload(cardp);
-               }
-               kfree_skb(skb);
-               lbtf_deb_leave(LBTF_DEB_USB);
-               return;
-       }
-       if (cardp->bootcmdresp <= 0) {
-               memcpy(&bcmdresp, skb->data, sizeof(bcmdresp));
-
-               if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
-                       kfree_skb(skb);
-                       if_usb_submit_rx_urb_fwload(cardp);
-                       cardp->bootcmdresp = 1;
-                       /* Received valid boot command response */
-                       lbtf_deb_usbd(&cardp->udev->dev,
-                                    "Received valid boot command response\n");
-                       lbtf_deb_leave(LBTF_DEB_USB);
-                       return;
-               }
-               if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
-                       if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
-                           bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
-                           bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) {
-                               if (!cardp->bootcmdresp)
-                                       pr_info("Firmware already seems alive; resetting\n");
-                               cardp->bootcmdresp = -1;
-                       } else {
-                               pr_info("boot cmd response wrong magic number (0x%x)\n",
-                                           le32_to_cpu(bcmdresp.magic));
-                       }
-               } else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
-                       pr_info("boot cmd response cmd_tag error (%d)\n",
-                               bcmdresp.cmd);
-               } else if (bcmdresp.result != BOOT_CMD_RESP_OK) {
-                       pr_info("boot cmd response result error (%d)\n",
-                               bcmdresp.result);
-               } else {
-                       cardp->bootcmdresp = 1;
-                       lbtf_deb_usbd(&cardp->udev->dev,
-                               "Received valid boot command response\n");
-               }
-
-               kfree_skb(skb);
-               if_usb_submit_rx_urb_fwload(cardp);
-               lbtf_deb_leave(LBTF_DEB_USB);
-               return;
-       }
-
-       syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader),
-                              GFP_ATOMIC);
-       if (!syncfwheader) {
-               lbtf_deb_usbd(&cardp->udev->dev,
-                       "Failure to allocate syncfwheader\n");
-               kfree_skb(skb);
-               lbtf_deb_leave(LBTF_DEB_USB);
-               return;
-       }
-
-       if (!syncfwheader->cmd) {
-               lbtf_deb_usb2(&cardp->udev->dev,
-                       "FW received Blk with correct CRC\n");
-               lbtf_deb_usb2(&cardp->udev->dev,
-                       "FW received Blk seqnum = %d\n",
-                       le32_to_cpu(syncfwheader->seqnum));
-               cardp->CRC_OK = 1;
-       } else {
-               lbtf_deb_usbd(&cardp->udev->dev,
-                       "FW received Blk with CRC error\n");
-               cardp->CRC_OK = 0;
-       }
-
-       kfree_skb(skb);
-
-       /* reschedule timer for 200ms hence */
-       mod_timer(&cardp->fw_timeout, jiffies + (HZ/5));
-
-       if (cardp->fwfinalblk) {
-               cardp->fwdnldover = 1;
-               goto exit;
-       }
-
-       if_usb_send_fw_pkt(cardp);
-
- exit:
-       if_usb_submit_rx_urb_fwload(cardp);
-
-       kfree(syncfwheader);
-
-       lbtf_deb_leave(LBTF_DEB_USB);
-}
-
-#define MRVDRV_MIN_PKT_LEN     30
-
-static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
-                                      struct if_usb_card *cardp,
-                                      struct lbtf_private *priv)
-{
-       if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
-           || recvlength < MRVDRV_MIN_PKT_LEN) {
-               lbtf_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n");
-               kfree_skb(skb);
-               return;
-       }
-
-       skb_put(skb, recvlength);
-       skb_pull(skb, MESSAGE_HEADER_LEN);
-       lbtf_rx(priv, skb);
-}
-
-static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
-                                     struct sk_buff *skb,
-                                     struct if_usb_card *cardp,
-                                     struct lbtf_private *priv)
-{
-       if (recvlength > LBS_CMD_BUFFER_SIZE) {
-               lbtf_deb_usbd(&cardp->udev->dev,
-                            "The receive buffer is too large\n");
-               kfree_skb(skb);
-               return;
-       }
-
-       BUG_ON(!in_interrupt());
-
-       spin_lock(&priv->driver_lock);
-       memcpy(priv->cmd_resp_buff, recvbuff + MESSAGE_HEADER_LEN,
-              recvlength - MESSAGE_HEADER_LEN);
-       kfree_skb(skb);
-       lbtf_cmd_response_rx(priv);
-       spin_unlock(&priv->driver_lock);
-}
-
-/**
- *  if_usb_receive - read data received from the device.
- *
- *  @urb               pointer to struct urb
- */
-static void if_usb_receive(struct urb *urb)
-{
-       struct if_usb_card *cardp = urb->context;
-       struct sk_buff *skb = cardp->rx_skb;
-       struct lbtf_private *priv = cardp->priv;
-       int recvlength = urb->actual_length;
-       uint8_t *recvbuff = NULL;
-       uint32_t recvtype = 0;
-       __le32 *pkt = (__le32 *) skb->data;
-
-       lbtf_deb_enter(LBTF_DEB_USB);
-
-       if (recvlength) {
-               if (urb->status) {
-                       lbtf_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
-                                    urb->status);
-                       kfree_skb(skb);
-                       goto setup_for_next;
-               }
-
-               recvbuff = skb->data;
-               recvtype = le32_to_cpu(pkt[0]);
-               lbtf_deb_usbd(&cardp->udev->dev,
-                           "Recv length = 0x%x, Recv type = 0x%X\n",
-                           recvlength, recvtype);
-       } else if (urb->status) {
-               kfree_skb(skb);
-               lbtf_deb_leave(LBTF_DEB_USB);
-               return;
-       }
-
-       switch (recvtype) {
-       case CMD_TYPE_DATA:
-               process_cmdtypedata(recvlength, skb, cardp, priv);
-               break;
-
-       case CMD_TYPE_REQUEST:
-               process_cmdrequest(recvlength, recvbuff, skb, cardp, priv);
-               break;
-
-       case CMD_TYPE_INDICATION:
-       {
-               /* Event cause handling */
-               u32 event_cause = le32_to_cpu(pkt[1]);
-               lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n",
-                       event_cause);
-
-               /* Icky undocumented magic special case */
-               if (event_cause & 0xffff0000) {
-                       u16 tmp;
-                       u8 retrycnt;
-                       u8 failure;
-
-                       tmp = event_cause >> 16;
-                       retrycnt = tmp & 0x00ff;
-                       failure = (tmp & 0xff00) >> 8;
-                       lbtf_send_tx_feedback(priv, retrycnt, failure);
-               } else if (event_cause == LBTF_EVENT_BCN_SENT)
-                       lbtf_bcn_sent(priv);
-               else
-                       lbtf_deb_usbd(&cardp->udev->dev,
-                              "Unsupported notification %d received\n",
-                              event_cause);
-               kfree_skb(skb);
-               break;
-       }
-       default:
-               lbtf_deb_usbd(&cardp->udev->dev,
-                       "libertastf: unknown command type 0x%X\n", recvtype);
-               kfree_skb(skb);
-               break;
-       }
-
-setup_for_next:
-       if_usb_submit_rx_urb(cardp);
-       lbtf_deb_leave(LBTF_DEB_USB);
-}
-
-/**
- *  if_usb_host_to_card -  Download data to the device
- *
- *  @priv              pointer to struct lbtf_private structure
- *  @type              type of data
- *  @buf               pointer to data buffer
- *  @len               number of bytes
- *
- *  Returns: 0 on success, nonzero otherwise
- */
-static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
-                              uint8_t *payload, uint16_t nb)
-{
-       struct if_usb_card *cardp = priv->card;
-       u8 data = 0;
-
-       lbtf_deb_usbd(&cardp->udev->dev, "*** type = %u\n", type);
-       lbtf_deb_usbd(&cardp->udev->dev, "size after = %d\n", nb);
-
-       if (type == MVMS_CMD) {
-               *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
-       } else {
-               *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_DATA);
-               data = 1;
-       }
-
-       memcpy((cardp->ep_out_buf + MESSAGE_HEADER_LEN), payload, nb);
-
-       return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN,
-                           data);
-}
-
-/**
- *  if_usb_issue_boot_command - Issue boot command to Boot2.
- *
- *  @ivalue   1 boots from FW by USB-Download, 2 boots from FW in EEPROM.
- *
- *  Returns: 0
- */
-static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue)
-{
-       struct bootcmd *bootcmd = cardp->ep_out_buf;
-
-       /* Prepare command */
-       bootcmd->magic = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
-       bootcmd->cmd = ivalue;
-       memset(bootcmd->pad, 0, sizeof(bootcmd->pad));
-
-       /* Issue command */
-       usb_tx_block(cardp, cardp->ep_out_buf, sizeof(*bootcmd), 0);
-
-       return 0;
-}
-
-
-/**
- *  check_fwfile_format - Check the validity of Boot2/FW image.
- *
- *  @data      pointer to image
- *  @totlen    image length
- *
- *  Returns: 0 if the image is valid, nonzero otherwise.
- */
-static int check_fwfile_format(const u8 *data, u32 totlen)
-{
-       u32 bincmd, exit;
-       u32 blksize, offset, len;
-       int ret;
-
-       ret = 1;
-       exit = len = 0;
-
-       do {
-               struct fwheader *fwh = (void *) data;
-
-               bincmd = le32_to_cpu(fwh->dnldcmd);
-               blksize = le32_to_cpu(fwh->datalength);
-               switch (bincmd) {
-               case FW_HAS_DATA_TO_RECV:
-                       offset = sizeof(struct fwheader) + blksize;
-                       data += offset;
-                       len += offset;
-                       if (len >= totlen)
-                               exit = 1;
-                       break;
-               case FW_HAS_LAST_BLOCK:
-                       exit = 1;
-                       ret = 0;
-                       break;
-               default:
-                       exit = 1;
-                       break;
-               }
-       } while (!exit);
-
-       if (ret)
-               pr_err("firmware file format check FAIL\n");
-       else
-               lbtf_deb_fw("firmware file format check PASS\n");
-
-       return ret;
-}
-
-
-static int if_usb_prog_firmware(struct if_usb_card *cardp)
-{
-       int i = 0;
-       static int reset_count = 10;
-       int ret = 0;
-
-       lbtf_deb_enter(LBTF_DEB_USB);
-
-       kernel_param_lock(THIS_MODULE);
-       ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
-       if (ret < 0) {
-               pr_err("request_firmware() failed with %#x\n", ret);
-               pr_err("firmware %s not found\n", lbtf_fw_name);
-               kernel_param_unlock(THIS_MODULE);
-               goto done;
-       }
-       kernel_param_unlock(THIS_MODULE);
-
-       if (check_fwfile_format(cardp->fw->data, cardp->fw->size))
-               goto release_fw;
-
-restart:
-       if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
-               lbtf_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
-               ret = -1;
-               goto release_fw;
-       }
-
-       cardp->bootcmdresp = 0;
-       do {
-               int j = 0;
-               i++;
-               /* Issue Boot command = 1, Boot from Download-FW */
-               if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
-               /* wait for command response */
-               do {
-                       j++;
-                       msleep_interruptible(100);
-               } while (cardp->bootcmdresp == 0 && j < 10);
-       } while (cardp->bootcmdresp == 0 && i < 5);
-
-       if (cardp->bootcmdresp <= 0) {
-               if (--reset_count >= 0) {
-                       if_usb_reset_device(cardp);
-                       goto restart;
-               }
-               return -1;
-       }
-
-       i = 0;
-
-       cardp->totalbytes = 0;
-       cardp->fwlastblksent = 0;
-       cardp->CRC_OK = 1;
-       cardp->fwdnldover = 0;
-       cardp->fwseqnum = -1;
-       cardp->totalbytes = 0;
-       cardp->fwfinalblk = 0;
-
-       /* Send the first firmware packet... */
-       if_usb_send_fw_pkt(cardp);
-
-       /* ... and wait for the process to complete */
-       wait_event_interruptible(cardp->fw_wq, cardp->priv->surpriseremoved ||
-                                              cardp->fwdnldover);
-
-       del_timer_sync(&cardp->fw_timeout);
-       usb_kill_urb(cardp->rx_urb);
-
-       if (!cardp->fwdnldover) {
-               pr_info("failed to load fw, resetting device!\n");
-               if (--reset_count >= 0) {
-                       if_usb_reset_device(cardp);
-                       goto restart;
-               }
-
-               pr_info("FW download failure, time = %d ms\n", i * 100);
-               ret = -1;
-               goto release_fw;
-       }
-
-       cardp->priv->fw_ready = 1;
-
- release_fw:
-       release_firmware(cardp->fw);
-       cardp->fw = NULL;
-
-       if_usb_setup_firmware(cardp->priv);
-
- done:
-       lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret);
-       return ret;
-}
-
-
-#define if_usb_suspend NULL
-#define if_usb_resume NULL
-
-static struct usb_driver if_usb_driver = {
-       .name = DRV_NAME,
-       .probe = if_usb_probe,
-       .disconnect = if_usb_disconnect,
-       .id_table = if_usb_table,
-       .suspend = if_usb_suspend,
-       .resume = if_usb_resume,
-       .disable_hub_initiated_lpm = 1,
-};
-
-module_usb_driver(if_usb_driver);
-
-MODULE_DESCRIPTION("8388 USB WLAN Thinfirm Driver");
-MODULE_AUTHOR("Cozybit Inc.");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas_tf/if_usb.h b/drivers/net/wireless/libertas_tf/if_usb.h
deleted file mode 100644 (file)
index 6fa5b3f..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *  Copyright (C) 2008, cozybit Inc.
- *  Copyright (C) 2003-2006, Marvell International Ltd.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- */
-#include <linux/wait.h>
-#include <linux/timer.h>
-
-struct lbtf_private;
-
-/**
-  * This file contains definition for USB interface.
-  */
-#define CMD_TYPE_REQUEST               0xF00DFACE
-#define CMD_TYPE_DATA                  0xBEADC0DE
-#define CMD_TYPE_INDICATION            0xBEEFFACE
-
-#define BOOT_CMD_FW_BY_USB             0x01
-#define BOOT_CMD_FW_IN_EEPROM          0x02
-#define BOOT_CMD_UPDATE_BOOT2          0x03
-#define BOOT_CMD_UPDATE_FW             0x04
-#define BOOT_CMD_MAGIC_NUMBER          0x4C56524D   /* LVRM */
-
-struct bootcmd {
-       __le32  magic;
-       uint8_t cmd;
-       uint8_t pad[11];
-};
-
-#define BOOT_CMD_RESP_OK               0x0001
-#define BOOT_CMD_RESP_FAIL             0x0000
-
-struct bootcmdresp {
-       __le32  magic;
-       uint8_t cmd;
-       uint8_t result;
-       uint8_t pad[2];
-};
-
-/** USB card description structure*/
-struct if_usb_card {
-       struct usb_device *udev;
-       struct urb *rx_urb, *tx_urb, *cmd_urb;
-       struct lbtf_private *priv;
-
-       struct sk_buff *rx_skb;
-
-       uint8_t ep_in;
-       uint8_t ep_out;
-
-       int8_t bootcmdresp;
-
-       int ep_in_size;
-
-       void *ep_out_buf;
-       int ep_out_size;
-
-       const struct firmware *fw;
-       struct timer_list fw_timeout;
-       wait_queue_head_t fw_wq;
-       uint32_t fwseqnum;
-       uint32_t totalbytes;
-       uint32_t fwlastblksent;
-       uint8_t CRC_OK;
-       uint8_t fwdnldover;
-       uint8_t fwfinalblk;
-
-       __le16 boot2_version;
-};
-
-/** fwheader */
-struct fwheader {
-       __le32 dnldcmd;
-       __le32 baseaddr;
-       __le32 datalength;
-       __le32 CRC;
-};
-
-#define FW_MAX_DATA_BLK_SIZE   600
-/** FWData */
-struct fwdata {
-       struct fwheader hdr;
-       __le32 seqnum;
-       uint8_t data[0];
-};
-
-/** fwsyncheader */
-struct fwsyncheader {
-       __le32 cmd;
-       __le32 seqnum;
-};
-
-#define FW_HAS_DATA_TO_RECV            0x00000001
-#define FW_HAS_LAST_BLOCK              0x00000004
diff --git a/drivers/net/wireless/libertas_tf/libertas_tf.h b/drivers/net/wireless/libertas_tf/libertas_tf.h
deleted file mode 100644 (file)
index ad77b92..0000000
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- *  Copyright (C) 2008, cozybit Inc.
- *  Copyright (C) 2007, Red Hat, Inc.
- *  Copyright (C) 2003-2006, Marvell International Ltd.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- */
-#include <linux/spinlock.h>
-#include <linux/device.h>
-#include <linux/kthread.h>
-#include <net/mac80211.h>
-
-#include "deb_defs.h"
-
-#ifndef DRV_NAME
-#define DRV_NAME "libertas_tf"
-#endif
-
-#define        MRVL_DEFAULT_RETRIES                    9
-#define MRVL_PER_PACKET_RATE                   0x10
-#define MRVL_MAX_BCN_SIZE                      440
-#define CMD_OPTION_WAITFORRSP                  0x0002
-
-/* Return command are almost always the same as the host command, but with
- * bit 15 set high.  There are a few exceptions, though...
- */
-#define CMD_RET(cmd)                   (0x8000 | cmd)
-
-/* Command codes */
-#define CMD_GET_HW_SPEC                                0x0003
-#define CMD_802_11_RESET                       0x0005
-#define CMD_MAC_MULTICAST_ADR                  0x0010
-#define CMD_802_11_RADIO_CONTROL               0x001c
-#define CMD_802_11_RF_CHANNEL                  0x001d
-#define CMD_802_11_RF_TX_POWER                 0x001e
-#define CMD_MAC_CONTROL                                0x0028
-#define CMD_802_11_MAC_ADDRESS                 0x004d
-#define        CMD_SET_BOOT2_VER                       0x00a5
-#define CMD_802_11_BEACON_CTRL                 0x00b0
-#define CMD_802_11_BEACON_SET                  0x00cb
-#define CMD_802_11_SET_MODE                    0x00cc
-#define CMD_802_11_SET_BSSID                   0x00cd
-
-#define CMD_ACT_GET                    0x0000
-#define CMD_ACT_SET                    0x0001
-
-/* Define action or option for CMD_802_11_RESET */
-#define CMD_ACT_HALT                   0x0003
-
-/* Define action or option for CMD_MAC_CONTROL */
-#define CMD_ACT_MAC_RX_ON                      0x0001
-#define CMD_ACT_MAC_TX_ON                      0x0002
-#define CMD_ACT_MAC_MULTICAST_ENABLE           0x0020
-#define CMD_ACT_MAC_BROADCAST_ENABLE           0x0040
-#define CMD_ACT_MAC_PROMISCUOUS_ENABLE         0x0080
-#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE       0x0100
-
-/* Define action or option for CMD_802_11_RADIO_CONTROL */
-#define CMD_TYPE_AUTO_PREAMBLE         0x0001
-#define CMD_TYPE_SHORT_PREAMBLE                0x0002
-#define CMD_TYPE_LONG_PREAMBLE         0x0003
-
-#define TURN_ON_RF                     0x01
-#define RADIO_ON                       0x01
-#define RADIO_OFF                      0x00
-
-#define SET_AUTO_PREAMBLE              0x05
-#define SET_SHORT_PREAMBLE             0x03
-#define SET_LONG_PREAMBLE              0x01
-
-/* Define action or option for CMD_802_11_RF_CHANNEL */
-#define CMD_OPT_802_11_RF_CHANNEL_GET  0x00
-#define CMD_OPT_802_11_RF_CHANNEL_SET  0x01
-
-/* Codes for CMD_802_11_SET_MODE */
-enum lbtf_mode {
-       LBTF_PASSIVE_MODE,
-       LBTF_STA_MODE,
-       LBTF_AP_MODE,
-};
-
-/** Card Event definition */
-#define MACREG_INT_CODE_FIRMWARE_READY         48
-/** Buffer Constants */
-
-/*     The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical
-*      addresses of TxPD buffers. Station has only 8 TxPD available, Whereas
-*      driver has more local TxPDs. Each TxPD on the host memory is associated
-*      with a Tx control node. The driver maintains 8 RxPD descriptors for
-*      station firmware to store Rx packet information.
-*
-*      Current version of MAC has a 32x6 multicast address buffer.
-*
-*      802.11b can have up to  14 channels, the driver keeps the
-*      BSSID(MAC address) of each APs or Ad hoc stations it has sensed.
-*/
-
-#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
-#define LBS_NUM_CMD_BUFFERS             10
-#define LBS_CMD_BUFFER_SIZE             (2 * 1024)
-#define MRVDRV_MAX_CHANNEL_SIZE                14
-#define MRVDRV_SNAP_HEADER_LEN          8
-
-#define        LBS_UPLD_SIZE                   2312
-#define DEV_NAME_LEN                   32
-
-/** Misc constants */
-/* This section defines 802.11 specific contants */
-
-#define MRVDRV_MAX_REGION_CODE                 6
-/**
- * the table to keep region code
- */
-#define LBTF_REGDOMAIN_US      0x10
-#define LBTF_REGDOMAIN_CA      0x20
-#define LBTF_REGDOMAIN_EU      0x30
-#define LBTF_REGDOMAIN_SP      0x31
-#define LBTF_REGDOMAIN_FR      0x32
-#define LBTF_REGDOMAIN_JP      0x40
-
-#define SBI_EVENT_CAUSE_SHIFT          3
-
-/** RxPD status */
-
-#define MRVDRV_RXPD_STATUS_OK                0x0001
-
-
-/* This is for firmware specific length */
-#define EXTRA_LEN      36
-
-#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
-       (ETH_FRAME_LEN + sizeof(struct txpd) + EXTRA_LEN)
-
-#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
-       (ETH_FRAME_LEN + sizeof(struct rxpd) \
-        + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
-
-#define        CMD_F_HOSTCMD           (1 << 0)
-#define FW_CAPINFO_WPA         (1 << 0)
-
-#define RF_ANTENNA_1           0x1
-#define RF_ANTENNA_2           0x2
-#define RF_ANTENNA_AUTO                0xFFFF
-
-#define LBTF_EVENT_BCN_SENT    55
-
-/** Global Variable Declaration */
-/** mv_ms_type */
-enum mv_ms_type {
-       MVMS_DAT = 0,
-       MVMS_CMD = 1,
-       MVMS_TXDONE = 2,
-       MVMS_EVENT
-};
-
-extern struct workqueue_struct *lbtf_wq;
-
-struct lbtf_private;
-
-struct lbtf_offset_value {
-       u32 offset;
-       u32 value;
-};
-
-struct channel_range {
-       u8 regdomain;
-       u8 start;
-       u8 end; /* exclusive (channel must be less than end) */
-};
-
-struct if_usb_card;
-
-/** Private structure for the MV device */
-struct lbtf_private {
-       void *card;
-       struct ieee80211_hw *hw;
-
-       /* Command response buffer */
-       u8 cmd_resp_buff[LBS_UPLD_SIZE];
-       /* Download sent:
-          bit0 1/0=data_sent/data_tx_done,
-          bit1 1/0=cmd_sent/cmd_tx_done,
-          all other bits reserved 0 */
-       struct ieee80211_vif *vif;
-
-       struct work_struct cmd_work;
-       struct work_struct tx_work;
-       /** Hardware access */
-       int (*hw_host_to_card) (struct lbtf_private *priv, u8 type, u8 *payload, u16 nb);
-       int (*hw_prog_firmware) (struct if_usb_card *cardp);
-       int (*hw_reset_device) (struct if_usb_card *cardp);
-
-
-       /** Wlan adapter data structure*/
-       /** STATUS variables */
-       u32 fwrelease;
-       u32 fwcapinfo;
-       /* protected with big lock */
-
-       struct mutex lock;
-
-       /** command-related variables */
-       u16 seqnum;
-       /* protected by big lock */
-
-       struct cmd_ctrl_node *cmd_array;
-       /** Current command */
-       struct cmd_ctrl_node *cur_cmd;
-       /** command Queues */
-       /** Free command buffers */
-       struct list_head cmdfreeq;
-       /** Pending command buffers */
-       struct list_head cmdpendingq;
-
-       /** spin locks */
-       spinlock_t driver_lock;
-
-       /** Timers */
-       struct timer_list command_timer;
-       int nr_retries;
-       int cmd_timed_out;
-
-       u8 cmd_response_rxed;
-
-       /** capability Info used in Association, start, join */
-       u16 capability;
-
-       /** MAC address information */
-       u8 current_addr[ETH_ALEN];
-       u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
-       u32 nr_of_multicastmacaddr;
-       int cur_freq;
-
-       struct sk_buff *skb_to_tx;
-       struct sk_buff *tx_skb;
-
-       /** NIC Operation characteristics */
-       u16 mac_control;
-       u16 regioncode;
-       struct channel_range range;
-
-       u8 radioon;
-       u32 preamble;
-
-       struct ieee80211_channel channels[14];
-       struct ieee80211_rate rates[12];
-       struct ieee80211_supported_band band;
-       struct lbtf_offset_value offsetvalue;
-
-       u8 fw_ready;
-       u8 surpriseremoved;
-       struct sk_buff_head bc_ps_buf;
-
-       /* Most recently reported noise in dBm */
-       s8 noise;
-};
-
-/* 802.11-related definitions */
-
-/* TxPD descriptor */
-struct txpd {
-       /* Current Tx packet status */
-       __le32 tx_status;
-       /* Tx control */
-       __le32 tx_control;
-       __le32 tx_packet_location;
-       /* Tx packet length */
-       __le16 tx_packet_length;
-       /* First 2 byte of destination MAC address */
-       u8 tx_dest_addr_high[2];
-       /* Last 4 byte of destination MAC address */
-       u8 tx_dest_addr_low[4];
-       /* Pkt Priority */
-       u8 priority;
-       /* Pkt Trasnit Power control */
-       u8 powermgmt;
-       /* Time the packet has been queued in the driver (units = 2ms) */
-       u8 pktdelay_2ms;
-       /* reserved */
-       u8 reserved1;
-};
-
-/* RxPD Descriptor */
-struct rxpd {
-       /* Current Rx packet status */
-       __le16 status;
-
-       /* SNR */
-       u8 snr;
-
-       /* Tx control */
-       u8 rx_control;
-
-       /* Pkt length */
-       __le16 pkt_len;
-
-       /* Noise Floor */
-       u8 nf;
-
-       /* Rx Packet Rate */
-       u8 rx_rate;
-
-       /* Pkt addr */
-       __le32 pkt_ptr;
-
-       /* Next Rx RxPD addr */
-       __le32 next_rxpd_ptr;
-
-       /* Pkt Priority */
-       u8 priority;
-       u8 reserved[3];
-};
-
-struct cmd_header {
-       __le16 command;
-       __le16 size;
-       __le16 seqnum;
-       __le16 result;
-} __packed;
-
-struct cmd_ctrl_node {
-       struct list_head list;
-       int result;
-       /* command response */
-       int (*callback)(struct lbtf_private *,
-                       unsigned long, struct cmd_header *);
-       unsigned long callback_arg;
-       /* command data */
-       struct cmd_header *cmdbuf;
-       /* wait queue */
-       u16 cmdwaitqwoken;
-       wait_queue_head_t cmdwait_q;
-};
-
-/*
- * Define data structure for CMD_GET_HW_SPEC
- * This structure defines the response for the GET_HW_SPEC command
- */
-struct cmd_ds_get_hw_spec {
-       struct cmd_header hdr;
-
-       /* HW Interface version number */
-       __le16 hwifversion;
-       /* HW version number */
-       __le16 version;
-       /* Max number of TxPD FW can handle */
-       __le16 nr_txpd;
-       /* Max no of Multicast address */
-       __le16 nr_mcast_adr;
-       /* MAC address */
-       u8 permanentaddr[6];
-
-       /* region Code */
-       __le16 regioncode;
-
-       /* Number of antenna used */
-       __le16 nr_antenna;
-
-       /* FW release number, example 0x01030304 = 2.3.4p1 */
-       __le32 fwrelease;
-
-       /* Base Address of TxPD queue */
-       __le32 wcb_base;
-       /* Read Pointer of RxPd queue */
-       __le32 rxpd_rdptr;
-
-       /* Write Pointer of RxPd queue */
-       __le32 rxpd_wrptr;
-
-       /*FW/HW capability */
-       __le32 fwcapinfo;
-} __packed;
-
-struct cmd_ds_mac_control {
-       struct cmd_header hdr;
-       __le16 action;
-       u16 reserved;
-};
-
-struct cmd_ds_802_11_mac_address {
-       struct cmd_header hdr;
-
-       __le16 action;
-       uint8_t macadd[ETH_ALEN];
-};
-
-struct cmd_ds_mac_multicast_addr {
-       struct cmd_header hdr;
-
-       __le16 action;
-       __le16 nr_of_adrs;
-       u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
-};
-
-struct cmd_ds_set_mode {
-       struct cmd_header hdr;
-
-       __le16 mode;
-};
-
-struct cmd_ds_set_bssid {
-       struct cmd_header hdr;
-
-       u8 bssid[6];
-       u8 activate;
-};
-
-struct cmd_ds_802_11_radio_control {
-       struct cmd_header hdr;
-
-       __le16 action;
-       __le16 control;
-};
-
-
-struct cmd_ds_802_11_rf_channel {
-       struct cmd_header hdr;
-
-       __le16 action;
-       __le16 channel;
-       __le16 rftype;      /* unused */
-       __le16 reserved;    /* unused */
-       u8 channellist[32]; /* unused */
-};
-
-struct cmd_ds_set_boot2_ver {
-       struct cmd_header hdr;
-
-       __le16 action;
-       __le16 version;
-};
-
-struct cmd_ds_802_11_reset {
-       struct cmd_header hdr;
-
-       __le16 action;
-};
-
-struct cmd_ds_802_11_beacon_control {
-       struct cmd_header hdr;
-
-       __le16 action;
-       __le16 beacon_enable;
-       __le16 beacon_period;
-};
-
-struct cmd_ds_802_11_beacon_set {
-       struct cmd_header hdr;
-
-       __le16 len;
-       u8 beacon[MRVL_MAX_BCN_SIZE];
-};
-
-struct lbtf_private;
-struct cmd_ctrl_node;
-
-/** Function Prototype Declaration */
-void lbtf_set_mac_control(struct lbtf_private *priv);
-
-int lbtf_free_cmd_buffer(struct lbtf_private *priv);
-
-int lbtf_allocate_cmd_buffer(struct lbtf_private *priv);
-int lbtf_execute_next_command(struct lbtf_private *priv);
-int lbtf_set_radio_control(struct lbtf_private *priv);
-int lbtf_update_hw_spec(struct lbtf_private *priv);
-int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv);
-void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode);
-void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid);
-int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr);
-
-int lbtf_set_channel(struct lbtf_private *priv, u8 channel);
-
-int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon);
-int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
-                    int beacon_int);
-
-
-int lbtf_process_rx_command(struct lbtf_private *priv);
-void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd,
-                         int result);
-void lbtf_cmd_response_rx(struct lbtf_private *priv);
-
-/* main.c */
-struct chan_freq_power *lbtf_get_region_cfp_table(u8 region,
-       int *cfp_no);
-struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev);
-int lbtf_remove_card(struct lbtf_private *priv);
-int lbtf_start_card(struct lbtf_private *priv);
-int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb);
-void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail);
-void lbtf_bcn_sent(struct lbtf_private *priv);
-
-/* support functions for cmd.c */
-/* lbtf_cmd() infers the size of the buffer to copy data back into, from
-   the size of the target of the pointer. Since the command to be sent
-   may often be smaller, that size is set in cmd->size by the caller.*/
-#define lbtf_cmd(priv, cmdnr, cmd, cb, cb_arg) ({              \
-       uint16_t __sz = le16_to_cpu((cmd)->hdr.size);           \
-       (cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd)));          \
-       __lbtf_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \
-})
-
-#define lbtf_cmd_with_response(priv, cmdnr, cmd)       \
-       lbtf_cmd(priv, cmdnr, cmd, lbtf_cmd_copyback, (unsigned long) (cmd))
-
-void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
-       struct cmd_header *in_cmd, int in_cmd_size);
-
-int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
-             struct cmd_header *in_cmd, int in_cmd_size,
-             int (*callback)(struct lbtf_private *, unsigned long,
-                             struct cmd_header *),
-             unsigned long callback_arg);
-
-int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra,
-                    struct cmd_header *resp);
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
deleted file mode 100644 (file)
index a47f0ac..0000000
+++ /dev/null
@@ -1,766 +0,0 @@
-/*
- *  Copyright (C) 2008, cozybit Inc.
- *  Copyright (C) 2003-2006, Marvell International Ltd.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/hardirq.h>
-#include <linux/slab.h>
-
-#include <linux/etherdevice.h>
-#include <linux/module.h>
-#include "libertas_tf.h"
-
-#define DRIVER_RELEASE_VERSION "004.p0"
-/* thinfirm version: 5.132.X.pX */
-#define LBTF_FW_VER_MIN                0x05840300
-#define LBTF_FW_VER_MAX                0x0584ffff
-#define QOS_CONTROL_LEN                2
-
-/* Module parameters */
-unsigned int lbtf_debug;
-EXPORT_SYMBOL_GPL(lbtf_debug);
-module_param_named(libertas_tf_debug, lbtf_debug, int, 0644);
-
-static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION
-#ifdef DEBUG
-       "-dbg"
-#endif
-       "";
-
-struct workqueue_struct *lbtf_wq;
-
-static const struct ieee80211_channel lbtf_channels[] = {
-       { .center_freq = 2412, .hw_value = 1 },
-       { .center_freq = 2417, .hw_value = 2 },
-       { .center_freq = 2422, .hw_value = 3 },
-       { .center_freq = 2427, .hw_value = 4 },
-       { .center_freq = 2432, .hw_value = 5 },
-       { .center_freq = 2437, .hw_value = 6 },
-       { .center_freq = 2442, .hw_value = 7 },
-       { .center_freq = 2447, .hw_value = 8 },
-       { .center_freq = 2452, .hw_value = 9 },
-       { .center_freq = 2457, .hw_value = 10 },
-       { .center_freq = 2462, .hw_value = 11 },
-       { .center_freq = 2467, .hw_value = 12 },
-       { .center_freq = 2472, .hw_value = 13 },
-       { .center_freq = 2484, .hw_value = 14 },
-};
-
-/* This table contains the hardware specific values for the modulation rates. */
-static const struct ieee80211_rate lbtf_rates[] = {
-       { .bitrate = 10,
-         .hw_value = 0, },
-       { .bitrate = 20,
-         .hw_value = 1,
-         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-       { .bitrate = 55,
-         .hw_value = 2,
-         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-       { .bitrate = 110,
-         .hw_value = 3,
-         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-       { .bitrate = 60,
-         .hw_value = 5,
-         .flags = 0 },
-       { .bitrate = 90,
-         .hw_value = 6,
-         .flags = 0 },
-       { .bitrate = 120,
-         .hw_value = 7,
-         .flags = 0 },
-       { .bitrate = 180,
-         .hw_value = 8,
-         .flags = 0 },
-       { .bitrate = 240,
-         .hw_value = 9,
-         .flags = 0 },
-       { .bitrate = 360,
-         .hw_value = 10,
-         .flags = 0 },
-       { .bitrate = 480,
-         .hw_value = 11,
-         .flags = 0 },
-       { .bitrate = 540,
-         .hw_value = 12,
-         .flags = 0 },
-};
-
-static void lbtf_cmd_work(struct work_struct *work)
-{
-       struct lbtf_private *priv = container_of(work, struct lbtf_private,
-                                        cmd_work);
-
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       spin_lock_irq(&priv->driver_lock);
-       /* command response? */
-       if (priv->cmd_response_rxed) {
-               priv->cmd_response_rxed = 0;
-               spin_unlock_irq(&priv->driver_lock);
-               lbtf_process_rx_command(priv);
-               spin_lock_irq(&priv->driver_lock);
-       }
-
-       if (priv->cmd_timed_out && priv->cur_cmd) {
-               struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
-
-               if (++priv->nr_retries > 10) {
-                       lbtf_complete_command(priv, cmdnode,
-                                             -ETIMEDOUT);
-                       priv->nr_retries = 0;
-               } else {
-                       priv->cur_cmd = NULL;
-
-                       /* Stick it back at the _top_ of the pending
-                        * queue for immediate resubmission */
-                       list_add(&cmdnode->list, &priv->cmdpendingq);
-               }
-       }
-       priv->cmd_timed_out = 0;
-       spin_unlock_irq(&priv->driver_lock);
-
-       if (!priv->fw_ready) {
-               lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready");
-               return;
-       }
-
-       /* Execute the next command */
-       if (!priv->cur_cmd)
-               lbtf_execute_next_command(priv);
-
-       lbtf_deb_leave(LBTF_DEB_CMD);
-}
-
-/**
- *  lbtf_setup_firmware: initialize firmware.
- *
- *  @priv    A pointer to struct lbtf_private structure
- *
- *  Returns: 0 on success.
- */
-static int lbtf_setup_firmware(struct lbtf_private *priv)
-{
-       int ret = -1;
-
-       lbtf_deb_enter(LBTF_DEB_FW);
-       /*
-        * Read priv address from HW
-        */
-       eth_broadcast_addr(priv->current_addr);
-       ret = lbtf_update_hw_spec(priv);
-       if (ret) {
-               ret = -1;
-               goto done;
-       }
-
-       lbtf_set_mac_control(priv);
-       lbtf_set_radio_control(priv);
-
-       ret = 0;
-done:
-       lbtf_deb_leave_args(LBTF_DEB_FW, "ret: %d", ret);
-       return ret;
-}
-
-/**
- *  This function handles the timeout of command sending.
- *  It will re-send the same command again.
- */
-static void command_timer_fn(unsigned long data)
-{
-       struct lbtf_private *priv = (struct lbtf_private *)data;
-       unsigned long flags;
-       lbtf_deb_enter(LBTF_DEB_CMD);
-
-       spin_lock_irqsave(&priv->driver_lock, flags);
-
-       if (!priv->cur_cmd) {
-               printk(KERN_DEBUG "libertastf: command timer expired; "
-                                 "no pending command\n");
-               goto out;
-       }
-
-       printk(KERN_DEBUG "libertas: command %x timed out\n",
-               le16_to_cpu(priv->cur_cmd->cmdbuf->command));
-
-       priv->cmd_timed_out = 1;
-       queue_work(lbtf_wq, &priv->cmd_work);
-out:
-       spin_unlock_irqrestore(&priv->driver_lock, flags);
-       lbtf_deb_leave(LBTF_DEB_CMD);
-}
-
-static int lbtf_init_adapter(struct lbtf_private *priv)
-{
-       lbtf_deb_enter(LBTF_DEB_MAIN);
-       eth_broadcast_addr(priv->current_addr);
-       mutex_init(&priv->lock);
-
-       priv->vif = NULL;
-       setup_timer(&priv->command_timer, command_timer_fn,
-               (unsigned long)priv);
-
-       INIT_LIST_HEAD(&priv->cmdfreeq);
-       INIT_LIST_HEAD(&priv->cmdpendingq);
-
-       spin_lock_init(&priv->driver_lock);
-
-       /* Allocate the command buffers */
-       if (lbtf_allocate_cmd_buffer(priv))
-               return -1;
-
-       lbtf_deb_leave(LBTF_DEB_MAIN);
-       return 0;
-}
-
-static void lbtf_free_adapter(struct lbtf_private *priv)
-{
-       lbtf_deb_enter(LBTF_DEB_MAIN);
-       lbtf_free_cmd_buffer(priv);
-       del_timer(&priv->command_timer);
-       lbtf_deb_leave(LBTF_DEB_MAIN);
-}
-
-static void lbtf_op_tx(struct ieee80211_hw *hw,
-                      struct ieee80211_tx_control *control,
-                      struct sk_buff *skb)
-{
-       struct lbtf_private *priv = hw->priv;
-
-       priv->skb_to_tx = skb;
-       queue_work(lbtf_wq, &priv->tx_work);
-       /*
-        * queue will be restarted when we receive transmission feedback if
-        * there are no buffered multicast frames to send
-        */
-       ieee80211_stop_queues(priv->hw);
-}
-
-static void lbtf_tx_work(struct work_struct *work)
-{
-       struct lbtf_private *priv = container_of(work, struct lbtf_private,
-                                        tx_work);
-       unsigned int len;
-       struct ieee80211_tx_info *info;
-       struct txpd *txpd;
-       struct sk_buff *skb = NULL;
-       int err;
-
-       lbtf_deb_enter(LBTF_DEB_MACOPS | LBTF_DEB_TX);
-
-       if ((priv->vif->type == NL80211_IFTYPE_AP) &&
-           (!skb_queue_empty(&priv->bc_ps_buf)))
-               skb = skb_dequeue(&priv->bc_ps_buf);
-       else if (priv->skb_to_tx) {
-               skb = priv->skb_to_tx;
-               priv->skb_to_tx = NULL;
-       } else {
-               lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
-               return;
-       }
-
-       len = skb->len;
-       info  = IEEE80211_SKB_CB(skb);
-       txpd = (struct txpd *)  skb_push(skb, sizeof(struct txpd));
-
-       if (priv->surpriseremoved) {
-               dev_kfree_skb_any(skb);
-               lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
-               return;
-       }
-
-       memset(txpd, 0, sizeof(struct txpd));
-       /* Activate per-packet rate selection */
-       txpd->tx_control |= cpu_to_le32(MRVL_PER_PACKET_RATE |
-                            ieee80211_get_tx_rate(priv->hw, info)->hw_value);
-
-       /* copy destination address from 802.11 header */
-       memcpy(txpd->tx_dest_addr_high, skb->data + sizeof(struct txpd) + 4,
-               ETH_ALEN);
-       txpd->tx_packet_length = cpu_to_le16(len);
-       txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
-       lbtf_deb_hex(LBTF_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
-       BUG_ON(priv->tx_skb);
-       spin_lock_irq(&priv->driver_lock);
-       priv->tx_skb = skb;
-       err = priv->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len);
-       spin_unlock_irq(&priv->driver_lock);
-       if (err) {
-               dev_kfree_skb_any(skb);
-               priv->tx_skb = NULL;
-               pr_err("TX error: %d", err);
-       }
-       lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
-}
-
-static int lbtf_op_start(struct ieee80211_hw *hw)
-{
-       struct lbtf_private *priv = hw->priv;
-       void *card = priv->card;
-       int ret = -1;
-
-       lbtf_deb_enter(LBTF_DEB_MACOPS);
-
-       if (!priv->fw_ready)
-               /* Upload firmware */
-               if (priv->hw_prog_firmware(card))
-                       goto err_prog_firmware;
-
-       /* poke the firmware */
-       priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
-       priv->radioon = RADIO_ON;
-       priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
-       ret = lbtf_setup_firmware(priv);
-       if (ret)
-               goto err_prog_firmware;
-
-       if ((priv->fwrelease < LBTF_FW_VER_MIN) ||
-           (priv->fwrelease > LBTF_FW_VER_MAX)) {
-               ret = -1;
-               goto err_prog_firmware;
-       }
-
-       printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
-       lbtf_deb_leave(LBTF_DEB_MACOPS);
-       return 0;
-
-err_prog_firmware:
-       priv->hw_reset_device(card);
-       lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret);
-       return ret;
-}
-
-static void lbtf_op_stop(struct ieee80211_hw *hw)
-{
-       struct lbtf_private *priv = hw->priv;
-       unsigned long flags;
-       struct sk_buff *skb;
-
-       struct cmd_ctrl_node *cmdnode;
-
-       lbtf_deb_enter(LBTF_DEB_MACOPS);
-
-       /* Flush pending command nodes */
-       spin_lock_irqsave(&priv->driver_lock, flags);
-       list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
-               cmdnode->result = -ENOENT;
-               cmdnode->cmdwaitqwoken = 1;
-               wake_up_interruptible(&cmdnode->cmdwait_q);
-       }
-
-       spin_unlock_irqrestore(&priv->driver_lock, flags);
-       cancel_work_sync(&priv->cmd_work);
-       cancel_work_sync(&priv->tx_work);
-       while ((skb = skb_dequeue(&priv->bc_ps_buf)))
-               dev_kfree_skb_any(skb);
-       priv->radioon = RADIO_OFF;
-       lbtf_set_radio_control(priv);
-
-       lbtf_deb_leave(LBTF_DEB_MACOPS);
-}
-
-static int lbtf_op_add_interface(struct ieee80211_hw *hw,
-                       struct ieee80211_vif *vif)
-{
-       struct lbtf_private *priv = hw->priv;
-       lbtf_deb_enter(LBTF_DEB_MACOPS);
-       if (priv->vif != NULL)
-               return -EOPNOTSUPP;
-
-       priv->vif = vif;
-       switch (vif->type) {
-       case NL80211_IFTYPE_MESH_POINT:
-       case NL80211_IFTYPE_AP:
-               lbtf_set_mode(priv, LBTF_AP_MODE);
-               break;
-       case NL80211_IFTYPE_STATION:
-               lbtf_set_mode(priv, LBTF_STA_MODE);
-               break;
-       default:
-               priv->vif = NULL;
-               return -EOPNOTSUPP;
-       }
-       lbtf_set_mac_address(priv, (u8 *) vif->addr);
-       lbtf_deb_leave(LBTF_DEB_MACOPS);
-       return 0;
-}
-
-static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
-                       struct ieee80211_vif *vif)
-{
-       struct lbtf_private *priv = hw->priv;
-       lbtf_deb_enter(LBTF_DEB_MACOPS);
-
-       if (priv->vif->type == NL80211_IFTYPE_AP ||
-           priv->vif->type == NL80211_IFTYPE_MESH_POINT)
-               lbtf_beacon_ctrl(priv, 0, 0);
-       lbtf_set_mode(priv, LBTF_PASSIVE_MODE);
-       lbtf_set_bssid(priv, 0, NULL);
-       priv->vif = NULL;
-       lbtf_deb_leave(LBTF_DEB_MACOPS);
-}
-
-static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
-{
-       struct lbtf_private *priv = hw->priv;
-       struct ieee80211_conf *conf = &hw->conf;
-       lbtf_deb_enter(LBTF_DEB_MACOPS);
-
-       if (conf->chandef.chan->center_freq != priv->cur_freq) {
-               priv->cur_freq = conf->chandef.chan->center_freq;
-               lbtf_set_channel(priv, conf->chandef.chan->hw_value);
-       }
-       lbtf_deb_leave(LBTF_DEB_MACOPS);
-       return 0;
-}
-
-static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw,
-                                    struct netdev_hw_addr_list *mc_list)
-{
-       struct lbtf_private *priv = hw->priv;
-       int i;
-       struct netdev_hw_addr *ha;
-       int mc_count = netdev_hw_addr_list_count(mc_list);
-
-       if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE)
-               return mc_count;
-
-       priv->nr_of_multicastmacaddr = mc_count;
-       i = 0;
-       netdev_hw_addr_list_for_each(ha, mc_list)
-               memcpy(&priv->multicastlist[i++], ha->addr, ETH_ALEN);
-
-       return mc_count;
-}
-
-#define SUPPORTED_FIF_FLAGS  FIF_ALLMULTI
-static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
-                       unsigned int changed_flags,
-                       unsigned int *new_flags,
-                       u64 multicast)
-{
-       struct lbtf_private *priv = hw->priv;
-       int old_mac_control = priv->mac_control;
-
-       lbtf_deb_enter(LBTF_DEB_MACOPS);
-
-       changed_flags &= SUPPORTED_FIF_FLAGS;
-       *new_flags &= SUPPORTED_FIF_FLAGS;
-
-       if (!changed_flags) {
-               lbtf_deb_leave(LBTF_DEB_MACOPS);
-               return;
-       }
-
-       priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
-       if (*new_flags & (FIF_ALLMULTI) ||
-           multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
-               priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
-               priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE;
-       } else if (multicast) {
-               priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE;
-               priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
-               lbtf_cmd_set_mac_multicast_addr(priv);
-       } else {
-               priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE |
-                                      CMD_ACT_MAC_ALL_MULTICAST_ENABLE);
-               if (priv->nr_of_multicastmacaddr) {
-                       priv->nr_of_multicastmacaddr = 0;
-                       lbtf_cmd_set_mac_multicast_addr(priv);
-               }
-       }
-
-
-       if (priv->mac_control != old_mac_control)
-               lbtf_set_mac_control(priv);
-
-       lbtf_deb_leave(LBTF_DEB_MACOPS);
-}
-
-static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
-                       struct ieee80211_vif *vif,
-                       struct ieee80211_bss_conf *bss_conf,
-                       u32 changes)
-{
-       struct lbtf_private *priv = hw->priv;
-       struct sk_buff *beacon;
-       lbtf_deb_enter(LBTF_DEB_MACOPS);
-
-       if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) {
-               switch (priv->vif->type) {
-               case NL80211_IFTYPE_AP:
-               case NL80211_IFTYPE_MESH_POINT:
-                       beacon = ieee80211_beacon_get(hw, vif);
-                       if (beacon) {
-                               lbtf_beacon_set(priv, beacon);
-                               kfree_skb(beacon);
-                               lbtf_beacon_ctrl(priv, 1,
-                                                bss_conf->beacon_int);
-                       }
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       if (changes & BSS_CHANGED_BSSID) {
-               bool activate = !is_zero_ether_addr(bss_conf->bssid);
-               lbtf_set_bssid(priv, activate, bss_conf->bssid);
-       }
-
-       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-               if (bss_conf->use_short_preamble)
-                       priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
-               else
-                       priv->preamble = CMD_TYPE_LONG_PREAMBLE;
-               lbtf_set_radio_control(priv);
-       }
-
-       lbtf_deb_leave(LBTF_DEB_MACOPS);
-}
-
-static int lbtf_op_get_survey(struct ieee80211_hw *hw, int idx,
-                               struct survey_info *survey)
-{
-       struct lbtf_private *priv = hw->priv;
-       struct ieee80211_conf *conf = &hw->conf;
-
-       if (idx != 0)
-               return -ENOENT;
-
-       survey->channel = conf->chandef.chan;
-       survey->filled = SURVEY_INFO_NOISE_DBM;
-       survey->noise = priv->noise;
-
-       return 0;
-}
-
-static const struct ieee80211_ops lbtf_ops = {
-       .tx                     = lbtf_op_tx,
-       .start                  = lbtf_op_start,
-       .stop                   = lbtf_op_stop,
-       .add_interface          = lbtf_op_add_interface,
-       .remove_interface       = lbtf_op_remove_interface,
-       .config                 = lbtf_op_config,
-       .prepare_multicast      = lbtf_op_prepare_multicast,
-       .configure_filter       = lbtf_op_configure_filter,
-       .bss_info_changed       = lbtf_op_bss_info_changed,
-       .get_survey             = lbtf_op_get_survey,
-};
-
-int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
-{
-       struct ieee80211_rx_status stats;
-       struct rxpd *prxpd;
-       int need_padding;
-       unsigned int flags;
-       struct ieee80211_hdr *hdr;
-
-       lbtf_deb_enter(LBTF_DEB_RX);
-
-       prxpd = (struct rxpd *) skb->data;
-
-       memset(&stats, 0, sizeof(stats));
-       if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
-               stats.flag |= RX_FLAG_FAILED_FCS_CRC;
-       stats.freq = priv->cur_freq;
-       stats.band = IEEE80211_BAND_2GHZ;
-       stats.signal = prxpd->snr;
-       priv->noise = prxpd->nf;
-       /* Marvell rate index has a hole at value 4 */
-       if (prxpd->rx_rate > 4)
-               --prxpd->rx_rate;
-       stats.rate_idx = prxpd->rx_rate;
-       skb_pull(skb, sizeof(struct rxpd));
-
-       hdr = (struct ieee80211_hdr *)skb->data;
-       flags = le32_to_cpu(*(__le32 *)(skb->data + 4));
-
-       need_padding = ieee80211_is_data_qos(hdr->frame_control);
-       need_padding ^= ieee80211_has_a4(hdr->frame_control);
-       need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
-                       (*ieee80211_get_qos_ctl(hdr) &
-                        IEEE80211_QOS_CTL_A_MSDU_PRESENT);
-
-       if (need_padding) {
-               memmove(skb->data + 2, skb->data, skb->len);
-               skb_reserve(skb, 2);
-       }
-
-       memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
-
-       lbtf_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
-              skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
-       lbtf_deb_hex(LBTF_DEB_RX, "RX Data", skb->data,
-                    min_t(unsigned int, skb->len, 100));
-
-       ieee80211_rx_irqsafe(priv->hw, skb);
-
-       lbtf_deb_leave(LBTF_DEB_RX);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(lbtf_rx);
-
-/**
- * lbtf_add_card: Add and initialize the card, no fw upload yet.
- *
- *  @card    A pointer to card
- *
- *  Returns: pointer to struct lbtf_priv.
- */
-struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
-{
-       struct ieee80211_hw *hw;
-       struct lbtf_private *priv = NULL;
-
-       lbtf_deb_enter(LBTF_DEB_MAIN);
-
-       hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops);
-       if (!hw)
-               goto done;
-
-       priv = hw->priv;
-       if (lbtf_init_adapter(priv))
-               goto err_init_adapter;
-
-       priv->hw = hw;
-       priv->card = card;
-       priv->tx_skb = NULL;
-
-       hw->queues = 1;
-       ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
-       hw->extra_tx_headroom = sizeof(struct txpd);
-       memcpy(priv->channels, lbtf_channels, sizeof(lbtf_channels));
-       memcpy(priv->rates, lbtf_rates, sizeof(lbtf_rates));
-       priv->band.n_bitrates = ARRAY_SIZE(lbtf_rates);
-       priv->band.bitrates = priv->rates;
-       priv->band.n_channels = ARRAY_SIZE(lbtf_channels);
-       priv->band.channels = priv->channels;
-       hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
-       hw->wiphy->interface_modes =
-               BIT(NL80211_IFTYPE_STATION) |
-               BIT(NL80211_IFTYPE_ADHOC);
-       skb_queue_head_init(&priv->bc_ps_buf);
-
-       SET_IEEE80211_DEV(hw, dmdev);
-
-       INIT_WORK(&priv->cmd_work, lbtf_cmd_work);
-       INIT_WORK(&priv->tx_work, lbtf_tx_work);
-       if (ieee80211_register_hw(hw))
-               goto err_init_adapter;
-
-       goto done;
-
-err_init_adapter:
-       lbtf_free_adapter(priv);
-       ieee80211_free_hw(hw);
-       priv = NULL;
-
-done:
-       lbtf_deb_leave_args(LBTF_DEB_MAIN, "priv %p", priv);
-       return priv;
-}
-EXPORT_SYMBOL_GPL(lbtf_add_card);
-
-
-int lbtf_remove_card(struct lbtf_private *priv)
-{
-       struct ieee80211_hw *hw = priv->hw;
-
-       lbtf_deb_enter(LBTF_DEB_MAIN);
-
-       priv->surpriseremoved = 1;
-       del_timer(&priv->command_timer);
-       lbtf_free_adapter(priv);
-       priv->hw = NULL;
-       ieee80211_unregister_hw(hw);
-       ieee80211_free_hw(hw);
-
-    lbtf_deb_leave(LBTF_DEB_MAIN);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(lbtf_remove_card);
-
-void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail)
-{
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb);
-
-       ieee80211_tx_info_clear_status(info);
-       /*
-        * Commented out, otherwise we never go beyond 1Mbit/s using mac80211
-        * default pid rc algorithm.
-        *
-        * info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt;
-        */
-       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail)
-               info->flags |= IEEE80211_TX_STAT_ACK;
-       skb_pull(priv->tx_skb, sizeof(struct txpd));
-       ieee80211_tx_status_irqsafe(priv->hw, priv->tx_skb);
-       priv->tx_skb = NULL;
-       if (!priv->skb_to_tx && skb_queue_empty(&priv->bc_ps_buf))
-               ieee80211_wake_queues(priv->hw);
-       else
-               queue_work(lbtf_wq, &priv->tx_work);
-}
-EXPORT_SYMBOL_GPL(lbtf_send_tx_feedback);
-
-void lbtf_bcn_sent(struct lbtf_private *priv)
-{
-       struct sk_buff *skb = NULL;
-
-       if (priv->vif->type != NL80211_IFTYPE_AP)
-               return;
-
-       if (skb_queue_empty(&priv->bc_ps_buf)) {
-               bool tx_buff_bc = false;
-
-               while ((skb = ieee80211_get_buffered_bc(priv->hw, priv->vif))) {
-                       skb_queue_tail(&priv->bc_ps_buf, skb);
-                       tx_buff_bc = true;
-               }
-               if (tx_buff_bc) {
-                       ieee80211_stop_queues(priv->hw);
-                       queue_work(lbtf_wq, &priv->tx_work);
-               }
-       }
-
-       skb = ieee80211_beacon_get(priv->hw, priv->vif);
-
-       if (skb) {
-               lbtf_beacon_set(priv, skb);
-               kfree_skb(skb);
-       }
-}
-EXPORT_SYMBOL_GPL(lbtf_bcn_sent);
-
-static int __init lbtf_init_module(void)
-{
-       lbtf_deb_enter(LBTF_DEB_MAIN);
-       lbtf_wq = create_workqueue("libertastf");
-       if (lbtf_wq == NULL) {
-               printk(KERN_ERR "libertastf: couldn't create workqueue\n");
-               return -ENOMEM;
-       }
-       lbtf_deb_leave(LBTF_DEB_MAIN);
-       return 0;
-}
-
-static void __exit lbtf_exit_module(void)
-{
-       lbtf_deb_enter(LBTF_DEB_MAIN);
-       destroy_workqueue(lbtf_wq);
-       lbtf_deb_leave(LBTF_DEB_MAIN);
-}
-
-module_init(lbtf_init_module);
-module_exit(lbtf_exit_module);
-
-MODULE_DESCRIPTION("Libertas WLAN Thinfirm Driver Library");
-MODULE_AUTHOR("Cozybit Inc.");
-MODULE_LICENSE("GPL");
index 7842096bea53b526b69d5a28a29a45e47aa2f48d..97ec8f35745e06b748a1bb43957c4e0af91dc86b 100644 (file)
@@ -12,5 +12,6 @@ config WLAN_VENDOR_MARVELL
 if WLAN_VENDOR_MARVELL
 
 source "drivers/net/wireless/marvell/libertas/Kconfig"
+source "drivers/net/wireless/marvell/libertas_tf/Kconfig"
 
 endif # WLAN_VENDOR_MARVELL
index 6f7ac46ded33f846fbad773658f8c73e51dec6f8..8f5eb423b71afcfa22a800467e7f8c4c5a631dd3 100644 (file)
@@ -1 +1,3 @@
 obj-$(CONFIG_LIBERTAS)         += libertas/
+
+obj-$(CONFIG_LIBERTAS_THINFIRM)        += libertas_tf/
diff --git a/drivers/net/wireless/marvell/libertas_tf/Kconfig b/drivers/net/wireless/marvell/libertas_tf/Kconfig
new file mode 100644 (file)
index 0000000..b5557af
--- /dev/null
@@ -0,0 +1,18 @@
+config LIBERTAS_THINFIRM
+       tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware"
+       depends on MAC80211
+       select FW_LOADER
+       ---help---
+         A library for Marvell Libertas 8xxx devices using thinfirm.
+
+config LIBERTAS_THINFIRM_DEBUG
+       bool "Enable full debugging output in the Libertas thin firmware module."
+       depends on LIBERTAS_THINFIRM
+       ---help---
+         Debugging support.
+
+config LIBERTAS_THINFIRM_USB
+       tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware"
+       depends on LIBERTAS_THINFIRM && USB
+       ---help---
+         A driver for Marvell Libertas 8388 USB devices using thinfirm.
diff --git a/drivers/net/wireless/marvell/libertas_tf/Makefile b/drivers/net/wireless/marvell/libertas_tf/Makefile
new file mode 100644 (file)
index 0000000..ff5544d
--- /dev/null
@@ -0,0 +1,6 @@
+libertas_tf-objs := main.o cmd.o
+
+libertas_tf_usb-objs += if_usb.o
+
+obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf.o
+obj-$(CONFIG_LIBERTAS_THINFIRM_USB) += libertas_tf_usb.o
diff --git a/drivers/net/wireless/marvell/libertas_tf/cmd.c b/drivers/net/wireless/marvell/libertas_tf/cmd.c
new file mode 100644 (file)
index 0000000..909ac36
--- /dev/null
@@ -0,0 +1,807 @@
+/*
+ *  Copyright (C) 2008, cozybit Inc.
+ *  Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/hardirq.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include "libertas_tf.h"
+
+static const struct channel_range channel_ranges[] = {
+       { LBTF_REGDOMAIN_US,            1, 12 },
+       { LBTF_REGDOMAIN_CA,            1, 12 },
+       { LBTF_REGDOMAIN_EU,            1, 14 },
+       { LBTF_REGDOMAIN_JP,            1, 14 },
+       { LBTF_REGDOMAIN_SP,            1, 14 },
+       { LBTF_REGDOMAIN_FR,            1, 14 },
+};
+
+static u16 lbtf_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
+{
+       LBTF_REGDOMAIN_US, LBTF_REGDOMAIN_CA, LBTF_REGDOMAIN_EU,
+       LBTF_REGDOMAIN_SP, LBTF_REGDOMAIN_FR, LBTF_REGDOMAIN_JP,
+};
+
+static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv);
+
+
+/**
+ *  lbtf_cmd_copyback - Simple callback that copies response back into command
+ *
+ *  @priv      A pointer to struct lbtf_private structure
+ *  @extra     A pointer to the original command structure for which
+ *             'resp' is a response
+ *  @resp      A pointer to the command response
+ *
+ *  Returns: 0 on success, error on failure
+ */
+int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra,
+                    struct cmd_header *resp)
+{
+       struct cmd_header *buf = (void *)extra;
+       uint16_t copy_len;
+
+       copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
+       memcpy(buf, resp, copy_len);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lbtf_cmd_copyback);
+
+#define CHAN_TO_IDX(chan) ((chan) - 1)
+
+static void lbtf_geo_init(struct lbtf_private *priv)
+{
+       const struct channel_range *range = channel_ranges;
+       u8 ch;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(channel_ranges); i++)
+               if (channel_ranges[i].regdomain == priv->regioncode) {
+                       range = &channel_ranges[i];
+                       break;
+               }
+
+       for (ch = priv->range.start; ch < priv->range.end; ch++)
+               priv->channels[CHAN_TO_IDX(ch)].flags = 0;
+}
+
+/**
+ *  lbtf_update_hw_spec: Updates the hardware details.
+ *
+ *  @priv      A pointer to struct lbtf_private structure
+ *
+ *  Returns: 0 on success, error on failure
+ */
+int lbtf_update_hw_spec(struct lbtf_private *priv)
+{
+       struct cmd_ds_get_hw_spec cmd;
+       int ret = -1;
+       u32 i;
+
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
+       ret = lbtf_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
+       if (ret)
+               goto out;
+
+       priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
+
+       /* The firmware release is in an interesting format: the patch
+        * level is in the most significant nibble ... so fix that: */
+       priv->fwrelease = le32_to_cpu(cmd.fwrelease);
+       priv->fwrelease = (priv->fwrelease << 8) |
+               (priv->fwrelease >> 24 & 0xff);
+
+       printk(KERN_INFO "libertastf: %pM, fw %u.%u.%up%u, cap 0x%08x\n",
+               cmd.permanentaddr,
+               priv->fwrelease >> 24 & 0xff,
+               priv->fwrelease >> 16 & 0xff,
+               priv->fwrelease >>  8 & 0xff,
+               priv->fwrelease       & 0xff,
+               priv->fwcapinfo);
+       lbtf_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
+                   cmd.hwifversion, cmd.version);
+
+       /* Clamp region code to 8-bit since FW spec indicates that it should
+        * only ever be 8-bit, even though the field size is 16-bit.  Some
+        * firmware returns non-zero high 8 bits here.
+        */
+       priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
+
+       for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+               /* use the region code to search for the index */
+               if (priv->regioncode == lbtf_region_code_to_index[i])
+                       break;
+       }
+
+       /* if it's unidentified region code, use the default (USA) */
+       if (i >= MRVDRV_MAX_REGION_CODE) {
+               priv->regioncode = 0x10;
+               pr_info("unidentified region code; using the default (USA)\n");
+       }
+
+       if (priv->current_addr[0] == 0xff)
+               memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
+
+       SET_IEEE80211_PERM_ADDR(priv->hw, priv->current_addr);
+
+       lbtf_geo_init(priv);
+out:
+       lbtf_deb_leave(LBTF_DEB_CMD);
+       return ret;
+}
+
+/**
+ *  lbtf_set_channel: Set the radio channel
+ *
+ *  @priv      A pointer to struct lbtf_private structure
+ *  @channel   The desired channel, or 0 to clear a locked channel
+ *
+ *  Returns: 0 on success, error on failure
+ */
+int lbtf_set_channel(struct lbtf_private *priv, u8 channel)
+{
+       int ret = 0;
+       struct cmd_ds_802_11_rf_channel cmd;
+
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
+       cmd.channel = cpu_to_le16(channel);
+
+       ret = lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
+       lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
+       return ret;
+}
+
+int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
+{
+       struct cmd_ds_802_11_beacon_set cmd;
+       int size;
+
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       if (beacon->len > MRVL_MAX_BCN_SIZE) {
+               lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", -1);
+               return -1;
+       }
+       size =  sizeof(cmd) - sizeof(cmd.beacon) + beacon->len;
+       cmd.hdr.size = cpu_to_le16(size);
+       cmd.len = cpu_to_le16(beacon->len);
+       memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len);
+
+       lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size);
+
+       lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", 0);
+       return 0;
+}
+
+int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
+                    int beacon_int)
+{
+       struct cmd_ds_802_11_beacon_control cmd;
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.action = cpu_to_le16(CMD_ACT_SET);
+       cmd.beacon_enable = cpu_to_le16(beacon_enable);
+       cmd.beacon_period = cpu_to_le16(beacon_int);
+
+       lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd));
+
+       lbtf_deb_leave(LBTF_DEB_CMD);
+       return 0;
+}
+
+static void lbtf_queue_cmd(struct lbtf_private *priv,
+                         struct cmd_ctrl_node *cmdnode)
+{
+       unsigned long flags;
+       lbtf_deb_enter(LBTF_DEB_HOST);
+
+       if (!cmdnode) {
+               lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n");
+               goto qcmd_done;
+       }
+
+       if (!cmdnode->cmdbuf->size) {
+               lbtf_deb_host("DNLD_CMD: cmd size is zero\n");
+               goto qcmd_done;
+       }
+
+       cmdnode->result = 0;
+       spin_lock_irqsave(&priv->driver_lock, flags);
+       list_add_tail(&cmdnode->list, &priv->cmdpendingq);
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+       lbtf_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
+                    le16_to_cpu(cmdnode->cmdbuf->command));
+
+qcmd_done:
+       lbtf_deb_leave(LBTF_DEB_HOST);
+}
+
+static void lbtf_submit_command(struct lbtf_private *priv,
+                              struct cmd_ctrl_node *cmdnode)
+{
+       unsigned long flags;
+       struct cmd_header *cmd;
+       uint16_t cmdsize;
+       uint16_t command;
+       int timeo = 5 * HZ;
+       int ret;
+
+       lbtf_deb_enter(LBTF_DEB_HOST);
+
+       cmd = cmdnode->cmdbuf;
+
+       spin_lock_irqsave(&priv->driver_lock, flags);
+       priv->cur_cmd = cmdnode;
+       cmdsize = le16_to_cpu(cmd->size);
+       command = le16_to_cpu(cmd->command);
+
+       lbtf_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
+                    command, le16_to_cpu(cmd->seqnum), cmdsize);
+       lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
+
+       ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+       if (ret) {
+               pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
+               /* Let the timer kick in and retry, and potentially reset
+                  the whole thing if the condition persists */
+               timeo = HZ;
+       }
+
+       /* Setup the timer after transmit command */
+       mod_timer(&priv->command_timer, jiffies + timeo);
+
+       lbtf_deb_leave(LBTF_DEB_HOST);
+}
+
+/**
+ *  This function inserts command node to cmdfreeq
+ *  after cleans it. Requires priv->driver_lock held.
+ */
+static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
+                                        struct cmd_ctrl_node *cmdnode)
+{
+       lbtf_deb_enter(LBTF_DEB_HOST);
+
+       if (!cmdnode)
+               goto cl_ins_out;
+
+       cmdnode->callback = NULL;
+       cmdnode->callback_arg = 0;
+
+       memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
+
+       list_add_tail(&cmdnode->list, &priv->cmdfreeq);
+
+cl_ins_out:
+       lbtf_deb_leave(LBTF_DEB_HOST);
+}
+
+static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
+       struct cmd_ctrl_node *ptempcmd)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->driver_lock, flags);
+       __lbtf_cleanup_and_insert_cmd(priv, ptempcmd);
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+}
+
+void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd,
+                         int result)
+{
+       cmd->result = result;
+       cmd->cmdwaitqwoken = 1;
+       wake_up_interruptible(&cmd->cmdwait_q);
+
+       if (!cmd->callback)
+               __lbtf_cleanup_and_insert_cmd(priv, cmd);
+       priv->cur_cmd = NULL;
+}
+
+int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv)
+{
+       struct cmd_ds_mac_multicast_addr cmd;
+
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+       cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
+
+       lbtf_deb_cmd("MULTICAST_ADR: setting %d addresses\n", cmd.nr_of_adrs);
+
+       memcpy(cmd.maclist, priv->multicastlist,
+              priv->nr_of_multicastmacaddr * ETH_ALEN);
+
+       lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd));
+
+       lbtf_deb_leave(LBTF_DEB_CMD);
+       return 0;
+}
+
+void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)
+{
+       struct cmd_ds_set_mode cmd;
+       lbtf_deb_enter(LBTF_DEB_WEXT);
+
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.mode = cpu_to_le16(mode);
+       lbtf_deb_wext("Switching to mode: 0x%x\n", mode);
+       lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd));
+
+       lbtf_deb_leave(LBTF_DEB_WEXT);
+}
+
+void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
+{
+       struct cmd_ds_set_bssid cmd;
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.activate = activate ? 1 : 0;
+       if (activate)
+               memcpy(cmd.bssid, bssid, ETH_ALEN);
+
+       lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd));
+       lbtf_deb_leave(LBTF_DEB_CMD);
+}
+
+int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
+{
+       struct cmd_ds_802_11_mac_address cmd;
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+       memcpy(cmd.macadd, mac_addr, ETH_ALEN);
+
+       lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd));
+       lbtf_deb_leave(LBTF_DEB_CMD);
+       return 0;
+}
+
+int lbtf_set_radio_control(struct lbtf_private *priv)
+{
+       int ret = 0;
+       struct cmd_ds_802_11_radio_control cmd;
+
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+       switch (priv->preamble) {
+       case CMD_TYPE_SHORT_PREAMBLE:
+               cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE);
+               break;
+
+       case CMD_TYPE_LONG_PREAMBLE:
+               cmd.control = cpu_to_le16(SET_LONG_PREAMBLE);
+               break;
+
+       case CMD_TYPE_AUTO_PREAMBLE:
+       default:
+               cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE);
+               break;
+       }
+
+       if (priv->radioon)
+               cmd.control |= cpu_to_le16(TURN_ON_RF);
+       else
+               cmd.control &= cpu_to_le16(~TURN_ON_RF);
+
+       lbtf_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
+                   priv->preamble);
+
+       ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
+
+       lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
+       return ret;
+}
+
+void lbtf_set_mac_control(struct lbtf_private *priv)
+{
+       struct cmd_ds_mac_control cmd;
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.action = cpu_to_le16(priv->mac_control);
+       cmd.reserved = 0;
+
+       lbtf_cmd_async(priv, CMD_MAC_CONTROL,
+               &cmd.hdr, sizeof(cmd));
+
+       lbtf_deb_leave(LBTF_DEB_CMD);
+}
+
+/**
+ *  lbtf_allocate_cmd_buffer - Allocates cmd buffer, links it to free cmd queue
+ *
+ *  @priv      A pointer to struct lbtf_private structure
+ *
+ *  Returns: 0 on success.
+ */
+int lbtf_allocate_cmd_buffer(struct lbtf_private *priv)
+{
+       int ret = 0;
+       u32 bufsize;
+       u32 i;
+       struct cmd_ctrl_node *cmdarray;
+
+       lbtf_deb_enter(LBTF_DEB_HOST);
+
+       /* Allocate and initialize the command array */
+       bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
+       cmdarray = kzalloc(bufsize, GFP_KERNEL);
+       if (!cmdarray) {
+               lbtf_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
+               ret = -1;
+               goto done;
+       }
+       priv->cmd_array = cmdarray;
+
+       /* Allocate and initialize each command buffer in the command array */
+       for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+               cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
+               if (!cmdarray[i].cmdbuf) {
+                       lbtf_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
+                       ret = -1;
+                       goto done;
+               }
+       }
+
+       for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+               init_waitqueue_head(&cmdarray[i].cmdwait_q);
+               lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]);
+       }
+
+       ret = 0;
+
+done:
+       lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
+       return ret;
+}
+
+/**
+ *  lbtf_free_cmd_buffer - Frees the cmd buffer.
+ *
+ *  @priv      A pointer to struct lbtf_private structure
+ *
+ *  Returns: 0
+ */
+int lbtf_free_cmd_buffer(struct lbtf_private *priv)
+{
+       struct cmd_ctrl_node *cmdarray;
+       unsigned int i;
+
+       lbtf_deb_enter(LBTF_DEB_HOST);
+
+       /* need to check if cmd array is allocated or not */
+       if (priv->cmd_array == NULL) {
+               lbtf_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
+               goto done;
+       }
+
+       cmdarray = priv->cmd_array;
+
+       /* Release shared memory buffers */
+       for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+               kfree(cmdarray[i].cmdbuf);
+               cmdarray[i].cmdbuf = NULL;
+       }
+
+       /* Release cmd_ctrl_node */
+       kfree(priv->cmd_array);
+       priv->cmd_array = NULL;
+
+done:
+       lbtf_deb_leave(LBTF_DEB_HOST);
+       return 0;
+}
+
+/**
+ *  lbtf_get_cmd_ctrl_node - Gets free cmd node from free cmd queue.
+ *
+ *  @priv              A pointer to struct lbtf_private structure
+ *
+ *  Returns: pointer to a struct cmd_ctrl_node or NULL if none available.
+ */
+static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)
+{
+       struct cmd_ctrl_node *tempnode;
+       unsigned long flags;
+
+       lbtf_deb_enter(LBTF_DEB_HOST);
+
+       if (!priv)
+               return NULL;
+
+       spin_lock_irqsave(&priv->driver_lock, flags);
+
+       if (!list_empty(&priv->cmdfreeq)) {
+               tempnode = list_first_entry(&priv->cmdfreeq,
+                                           struct cmd_ctrl_node, list);
+               list_del(&tempnode->list);
+       } else {
+               lbtf_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
+               tempnode = NULL;
+       }
+
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+       lbtf_deb_leave(LBTF_DEB_HOST);
+       return tempnode;
+}
+
+/**
+ *  lbtf_execute_next_command: execute next command in cmd pending queue.
+ *
+ *  @priv     A pointer to struct lbtf_private structure
+ *
+ *  Returns: 0 on success.
+ */
+int lbtf_execute_next_command(struct lbtf_private *priv)
+{
+       struct cmd_ctrl_node *cmdnode = NULL;
+       struct cmd_header *cmd;
+       unsigned long flags;
+       int ret = 0;
+
+       /* Debug group is lbtf_deb_THREAD and not lbtf_deb_HOST, because the
+        * only caller to us is lbtf_thread() and we get even when a
+        * data packet is received */
+       lbtf_deb_enter(LBTF_DEB_THREAD);
+
+       spin_lock_irqsave(&priv->driver_lock, flags);
+
+       if (priv->cur_cmd) {
+               pr_alert("EXEC_NEXT_CMD: already processing command!\n");
+               spin_unlock_irqrestore(&priv->driver_lock, flags);
+               ret = -1;
+               goto done;
+       }
+
+       if (!list_empty(&priv->cmdpendingq)) {
+               cmdnode = list_first_entry(&priv->cmdpendingq,
+                                          struct cmd_ctrl_node, list);
+       }
+
+       if (cmdnode) {
+               cmd = cmdnode->cmdbuf;
+
+               list_del(&cmdnode->list);
+               lbtf_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
+                           le16_to_cpu(cmd->command));
+               spin_unlock_irqrestore(&priv->driver_lock, flags);
+               lbtf_submit_command(priv, cmdnode);
+       } else
+               spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+       ret = 0;
+done:
+       lbtf_deb_leave(LBTF_DEB_THREAD);
+       return ret;
+}
+
+static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
+       uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
+       int (*callback)(struct lbtf_private *, unsigned long,
+                       struct cmd_header *),
+       unsigned long callback_arg)
+{
+       struct cmd_ctrl_node *cmdnode;
+
+       lbtf_deb_enter(LBTF_DEB_HOST);
+
+       if (priv->surpriseremoved) {
+               lbtf_deb_host("PREP_CMD: card removed\n");
+               cmdnode = ERR_PTR(-ENOENT);
+               goto done;
+       }
+
+       cmdnode = lbtf_get_cmd_ctrl_node(priv);
+       if (cmdnode == NULL) {
+               lbtf_deb_host("PREP_CMD: cmdnode is NULL\n");
+
+               /* Wake up main thread to execute next command */
+               queue_work(lbtf_wq, &priv->cmd_work);
+               cmdnode = ERR_PTR(-ENOBUFS);
+               goto done;
+       }
+
+       cmdnode->callback = callback;
+       cmdnode->callback_arg = callback_arg;
+
+       /* Copy the incoming command to the buffer */
+       memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
+
+       /* Set sequence number, clean result, move to buffer */
+       priv->seqnum++;
+       cmdnode->cmdbuf->command = cpu_to_le16(command);
+       cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
+       cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);
+       cmdnode->cmdbuf->result  = 0;
+
+       lbtf_deb_host("PREP_CMD: command 0x%04x\n", command);
+
+       cmdnode->cmdwaitqwoken = 0;
+       lbtf_queue_cmd(priv, cmdnode);
+       queue_work(lbtf_wq, &priv->cmd_work);
+
+ done:
+       lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %p", cmdnode);
+       return cmdnode;
+}
+
+void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
+       struct cmd_header *in_cmd, int in_cmd_size)
+{
+       lbtf_deb_enter(LBTF_DEB_CMD);
+       __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0);
+       lbtf_deb_leave(LBTF_DEB_CMD);
+}
+
+int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
+             struct cmd_header *in_cmd, int in_cmd_size,
+             int (*callback)(struct lbtf_private *,
+                             unsigned long, struct cmd_header *),
+             unsigned long callback_arg)
+{
+       struct cmd_ctrl_node *cmdnode;
+       unsigned long flags;
+       int ret = 0;
+
+       lbtf_deb_enter(LBTF_DEB_HOST);
+
+       cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size,
+                                 callback, callback_arg);
+       if (IS_ERR(cmdnode)) {
+               ret = PTR_ERR(cmdnode);
+               goto done;
+       }
+
+       might_sleep();
+       ret = wait_event_interruptible(cmdnode->cmdwait_q,
+                                      cmdnode->cmdwaitqwoken);
+       if (ret) {
+               pr_info("PREP_CMD: command 0x%04x interrupted by signal: %d\n",
+                           command, ret);
+               goto done;
+       }
+
+       spin_lock_irqsave(&priv->driver_lock, flags);
+       ret = cmdnode->result;
+       if (ret)
+               pr_info("PREP_CMD: command 0x%04x failed: %d\n",
+                           command, ret);
+
+       __lbtf_cleanup_and_insert_cmd(priv, cmdnode);
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+done:
+       lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(__lbtf_cmd);
+
+/* Call holding driver_lock */
+void lbtf_cmd_response_rx(struct lbtf_private *priv)
+{
+       priv->cmd_response_rxed = 1;
+       queue_work(lbtf_wq, &priv->cmd_work);
+}
+EXPORT_SYMBOL_GPL(lbtf_cmd_response_rx);
+
+int lbtf_process_rx_command(struct lbtf_private *priv)
+{
+       uint16_t respcmd, curcmd;
+       struct cmd_header *resp;
+       int ret = 0;
+       unsigned long flags;
+       uint16_t result;
+
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       mutex_lock(&priv->lock);
+       spin_lock_irqsave(&priv->driver_lock, flags);
+
+       if (!priv->cur_cmd) {
+               ret = -1;
+               spin_unlock_irqrestore(&priv->driver_lock, flags);
+               goto done;
+       }
+
+       resp = (void *)priv->cmd_resp_buff;
+       curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
+       respcmd = le16_to_cpu(resp->command);
+       result = le16_to_cpu(resp->result);
+
+       if (net_ratelimit())
+               pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n",
+                       respcmd, le16_to_cpu(resp->seqnum),
+                       le16_to_cpu(resp->size));
+
+       if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
+               spin_unlock_irqrestore(&priv->driver_lock, flags);
+               ret = -1;
+               goto done;
+       }
+       if (respcmd != CMD_RET(curcmd)) {
+               spin_unlock_irqrestore(&priv->driver_lock, flags);
+               ret = -1;
+               goto done;
+       }
+
+       if (resp->result == cpu_to_le16(0x0004)) {
+               /* 0x0004 means -EAGAIN. Drop the response, let it time out
+                  and be resubmitted */
+               spin_unlock_irqrestore(&priv->driver_lock, flags);
+               ret = -1;
+               goto done;
+       }
+
+       /* Now we got response from FW, cancel the command timer */
+       del_timer(&priv->command_timer);
+       priv->cmd_timed_out = 0;
+       if (priv->nr_retries)
+               priv->nr_retries = 0;
+
+       /* If the command is not successful, cleanup and return failure */
+       if ((result != 0 || !(respcmd & 0x8000))) {
+               /*
+                * Handling errors here
+                */
+               switch (respcmd) {
+               case CMD_RET(CMD_GET_HW_SPEC):
+               case CMD_RET(CMD_802_11_RESET):
+                       pr_info("libertastf: reset failed\n");
+                       break;
+
+               }
+               lbtf_complete_command(priv, priv->cur_cmd, result);
+               spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+               ret = -1;
+               goto done;
+       }
+
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+       if (priv->cur_cmd && priv->cur_cmd->callback) {
+               ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
+                               resp);
+       }
+       spin_lock_irqsave(&priv->driver_lock, flags);
+
+       if (priv->cur_cmd) {
+               /* Clean up and Put current command back to cmdfreeq */
+               lbtf_complete_command(priv, priv->cur_cmd, result);
+       }
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+done:
+       mutex_unlock(&priv->lock);
+       lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
+       return ret;
+}
diff --git a/drivers/net/wireless/marvell/libertas_tf/deb_defs.h b/drivers/net/wireless/marvell/libertas_tf/deb_defs.h
new file mode 100644 (file)
index 0000000..4bd3dc5
--- /dev/null
@@ -0,0 +1,104 @@
+/**
+  * This header file contains global constant/enum definitions,
+  * global variable declaration.
+  */
+#ifndef _LBS_DEB_DEFS_H_
+#define _LBS_DEB_DEFS_H_
+
+#ifndef DRV_NAME
+#define DRV_NAME "libertas_tf"
+#endif
+
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_LIBERTAS_THINFIRM_DEBUG
+#define DEBUG
+#define PROC_DEBUG
+#endif
+
+#define LBTF_DEB_ENTER 0x00000001
+#define LBTF_DEB_LEAVE 0x00000002
+#define LBTF_DEB_MAIN  0x00000004
+#define LBTF_DEB_NET   0x00000008
+#define LBTF_DEB_MESH  0x00000010
+#define LBTF_DEB_WEXT  0x00000020
+#define LBTF_DEB_IOCTL 0x00000040
+#define LBTF_DEB_SCAN  0x00000080
+#define LBTF_DEB_ASSOC 0x00000100
+#define LBTF_DEB_JOIN  0x00000200
+#define LBTF_DEB_11D   0x00000400
+#define LBTF_DEB_DEBUGFS       0x00000800
+#define LBTF_DEB_ETHTOOL       0x00001000
+#define LBTF_DEB_HOST  0x00002000
+#define LBTF_DEB_CMD   0x00004000
+#define LBTF_DEB_RX    0x00008000
+#define LBTF_DEB_TX    0x00010000
+#define LBTF_DEB_USB   0x00020000
+#define LBTF_DEB_CS    0x00040000
+#define LBTF_DEB_FW    0x00080000
+#define LBTF_DEB_THREAD        0x00100000
+#define LBTF_DEB_HEX   0x00200000
+#define LBTF_DEB_SDIO  0x00400000
+#define LBTF_DEB_MACOPS        0x00800000
+
+extern unsigned int lbtf_debug;
+
+
+#ifdef DEBUG
+#define LBTF_DEB_LL(grp, grpnam, fmt, args...) \
+do { if ((lbtf_debug & (grp)) == (grp)) \
+  printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
+         in_interrupt() ? " (INT)" : "", ## args); } while (0)
+#else
+#define LBTF_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
+#endif
+
+#define lbtf_deb_enter(grp) \
+  LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s()\n", __func__);
+#define lbtf_deb_enter_args(grp, fmt, args...) \
+  LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
+#define lbtf_deb_leave(grp) \
+  LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s()\n", __func__);
+#define lbtf_deb_leave_args(grp, fmt, args...) \
+  LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
+  __func__, ##args);
+#define lbtf_deb_main(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MAIN, " main", fmt, ##args)
+#define lbtf_deb_net(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_NET, " net", fmt, ##args)
+#define lbtf_deb_mesh(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MESH, " mesh", fmt, ##args)
+#define lbtf_deb_wext(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_WEXT, " wext", fmt, ##args)
+#define lbtf_deb_ioctl(fmt, args...)     LBTF_DEB_LL(LBTF_DEB_IOCTL, " ioctl", fmt, ##args)
+#define lbtf_deb_scan(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_SCAN, " scan", fmt, ##args)
+#define lbtf_deb_assoc(fmt, args...)     LBTF_DEB_LL(LBTF_DEB_ASSOC, " assoc", fmt, ##args)
+#define lbtf_deb_join(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_JOIN, " join", fmt, ##args)
+#define lbtf_deb_11d(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_11D, " 11d", fmt, ##args)
+#define lbtf_deb_debugfs(fmt, args...)   LBTF_DEB_LL(LBTF_DEB_DEBUGFS, " debugfs", fmt, ##args)
+#define lbtf_deb_ethtool(fmt, args...)   LBTF_DEB_LL(LBTF_DEB_ETHTOOL, " ethtool", fmt, ##args)
+#define lbtf_deb_host(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_HOST, " host", fmt, ##args)
+#define lbtf_deb_cmd(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_CMD, " cmd", fmt, ##args)
+#define lbtf_deb_rx(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_RX, " rx", fmt, ##args)
+#define lbtf_deb_tx(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_TX, " tx", fmt, ##args)
+#define lbtf_deb_fw(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_FW, " fw", fmt, ##args)
+#define lbtf_deb_usb(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_USB, " usb", fmt, ##args)
+#define lbtf_deb_usbd(dev, fmt, args...) LBTF_DEB_LL(LBTF_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args)
+#define lbtf_deb_cs(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_CS, " cs", fmt, ##args)
+#define lbtf_deb_thread(fmt, args...)    LBTF_DEB_LL(LBTF_DEB_THREAD, " thread", fmt, ##args)
+#define lbtf_deb_sdio(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_SDIO, " thread", fmt, ##args)
+#define lbtf_deb_macops(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MACOPS, " thread", fmt, ##args)
+
+#ifdef DEBUG
+static inline void lbtf_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)
+{
+       char newprompt[32];
+
+       if (len &&
+           (lbtf_debug & LBTF_DEB_HEX) &&
+           (lbtf_debug & grp)) {
+               snprintf(newprompt, sizeof(newprompt), DRV_NAME " %s: ", prompt);
+               print_hex_dump_bytes(prompt, DUMP_PREFIX_NONE, buf, len);
+       }
+}
+#else
+#define lbtf_deb_hex(grp, prompt, buf, len)    do {} while (0)
+#endif
+
+#endif
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
new file mode 100644 (file)
index 0000000..799a2ef
--- /dev/null
@@ -0,0 +1,928 @@
+/*
+ *  Copyright (C) 2008, cozybit Inc.
+ *  Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ */
+#define DRV_NAME "lbtf_usb"
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "libertas_tf.h"
+#include "if_usb.h"
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#define INSANEDEBUG    0
+#define lbtf_deb_usb2(...) do { if (INSANEDEBUG) lbtf_deb_usbd(__VA_ARGS__); } while (0)
+
+#define MESSAGE_HEADER_LEN     4
+
+static char *lbtf_fw_name = "lbtf_usb.bin";
+module_param_named(fw_name, lbtf_fw_name, charp, 0644);
+
+MODULE_FIRMWARE("lbtf_usb.bin");
+
+static struct usb_device_id if_usb_table[] = {
+       /* Enter the device signature inside */
+       { USB_DEVICE(0x1286, 0x2001) },
+       { USB_DEVICE(0x05a3, 0x8388) },
+       {}      /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, if_usb_table);
+
+static void if_usb_receive(struct urb *urb);
+static void if_usb_receive_fwload(struct urb *urb);
+static int if_usb_prog_firmware(struct if_usb_card *cardp);
+static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
+                              uint8_t *payload, uint16_t nb);
+static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
+                       uint16_t nb, u8 data);
+static void if_usb_free(struct if_usb_card *cardp);
+static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
+static int if_usb_reset_device(struct if_usb_card *cardp);
+
+/**
+ *  if_usb_wrike_bulk_callback -  call back to handle URB status
+ *
+ *  @param urb         pointer to urb structure
+ */
+static void if_usb_write_bulk_callback(struct urb *urb)
+{
+       if (urb->status != 0) {
+               /* print the failure status number for debug */
+               pr_info("URB in failure status: %d\n", urb->status);
+       } else {
+               lbtf_deb_usb2(&urb->dev->dev, "URB status is successful\n");
+               lbtf_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
+                            urb->actual_length);
+       }
+}
+
+/**
+ *  if_usb_free - free tx/rx urb, skb and rx buffer
+ *
+ *  @param cardp       pointer if_usb_card
+ */
+static void if_usb_free(struct if_usb_card *cardp)
+{
+       lbtf_deb_enter(LBTF_DEB_USB);
+
+       /* Unlink tx & rx urb */
+       usb_kill_urb(cardp->tx_urb);
+       usb_kill_urb(cardp->rx_urb);
+       usb_kill_urb(cardp->cmd_urb);
+
+       usb_free_urb(cardp->tx_urb);
+       cardp->tx_urb = NULL;
+
+       usb_free_urb(cardp->rx_urb);
+       cardp->rx_urb = NULL;
+
+       usb_free_urb(cardp->cmd_urb);
+       cardp->cmd_urb = NULL;
+
+       kfree(cardp->ep_out_buf);
+       cardp->ep_out_buf = NULL;
+
+       lbtf_deb_leave(LBTF_DEB_USB);
+}
+
+static void if_usb_setup_firmware(struct lbtf_private *priv)
+{
+       struct if_usb_card *cardp = priv->card;
+       struct cmd_ds_set_boot2_ver b2_cmd;
+
+       lbtf_deb_enter(LBTF_DEB_USB);
+
+       if_usb_submit_rx_urb(cardp);
+       b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
+       b2_cmd.action = 0;
+       b2_cmd.version = cardp->boot2_version;
+
+       if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
+               lbtf_deb_usb("Setting boot2 version failed\n");
+
+       lbtf_deb_leave(LBTF_DEB_USB);
+}
+
+static void if_usb_fw_timeo(unsigned long priv)
+{
+       struct if_usb_card *cardp = (void *)priv;
+
+       lbtf_deb_enter(LBTF_DEB_USB);
+       if (!cardp->fwdnldover) {
+               /* Download timed out */
+               cardp->priv->surpriseremoved = 1;
+               pr_err("Download timed out\n");
+       } else {
+               lbtf_deb_usb("Download complete, no event. Assuming success\n");
+       }
+       wake_up(&cardp->fw_wq);
+       lbtf_deb_leave(LBTF_DEB_USB);
+}
+
+/**
+ *  if_usb_probe - sets the configuration values
+ *
+ *  @ifnum     interface number
+ *  @id                pointer to usb_device_id
+ *
+ *  Returns: 0 on success, error code on failure
+ */
+static int if_usb_probe(struct usb_interface *intf,
+                       const struct usb_device_id *id)
+{
+       struct usb_device *udev;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       struct lbtf_private *priv;
+       struct if_usb_card *cardp;
+       int i;
+
+       lbtf_deb_enter(LBTF_DEB_USB);
+       udev = interface_to_usbdev(intf);
+
+       cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
+       if (!cardp)
+               goto error;
+
+       setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
+       init_waitqueue_head(&cardp->fw_wq);
+
+       cardp->udev = udev;
+       iface_desc = intf->cur_altsetting;
+
+       lbtf_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
+                    " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
+                    le16_to_cpu(udev->descriptor.bcdUSB),
+                    udev->descriptor.bDeviceClass,
+                    udev->descriptor.bDeviceSubClass,
+                    udev->descriptor.bDeviceProtocol);
+
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+               if (usb_endpoint_is_bulk_in(endpoint)) {
+                       cardp->ep_in_size =
+                               le16_to_cpu(endpoint->wMaxPacketSize);
+                       cardp->ep_in = usb_endpoint_num(endpoint);
+
+                       lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n",
+                               cardp->ep_in);
+                       lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n",
+                               cardp->ep_in_size);
+               } else if (usb_endpoint_is_bulk_out(endpoint)) {
+                       cardp->ep_out_size =
+                               le16_to_cpu(endpoint->wMaxPacketSize);
+                       cardp->ep_out = usb_endpoint_num(endpoint);
+
+                       lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n",
+                               cardp->ep_out);
+                       lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n",
+                               cardp->ep_out_size);
+               }
+       }
+       if (!cardp->ep_out_size || !cardp->ep_in_size) {
+               lbtf_deb_usbd(&udev->dev, "Endpoints not found\n");
+               /* Endpoints not found */
+               goto dealloc;
+       }
+
+       cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!cardp->rx_urb) {
+               lbtf_deb_usbd(&udev->dev, "Rx URB allocation failed\n");
+               goto dealloc;
+       }
+
+       cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!cardp->tx_urb) {
+               lbtf_deb_usbd(&udev->dev, "Tx URB allocation failed\n");
+               goto dealloc;
+       }
+
+       cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!cardp->cmd_urb) {
+               lbtf_deb_usbd(&udev->dev, "Cmd URB allocation failed\n");
+               goto dealloc;
+       }
+
+       cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
+                                   GFP_KERNEL);
+       if (!cardp->ep_out_buf) {
+               lbtf_deb_usbd(&udev->dev, "Could not allocate buffer\n");
+               goto dealloc;
+       }
+
+       priv = lbtf_add_card(cardp, &udev->dev);
+       if (!priv)
+               goto dealloc;
+
+       cardp->priv = priv;
+
+       priv->hw_host_to_card = if_usb_host_to_card;
+       priv->hw_prog_firmware = if_usb_prog_firmware;
+       priv->hw_reset_device = if_usb_reset_device;
+       cardp->boot2_version = udev->descriptor.bcdDevice;
+
+       usb_get_dev(udev);
+       usb_set_intfdata(intf, cardp);
+
+       return 0;
+
+dealloc:
+       if_usb_free(cardp);
+error:
+lbtf_deb_leave(LBTF_DEB_MAIN);
+       return -ENOMEM;
+}
+
+/**
+ *  if_usb_disconnect -  free resource and cleanup
+ *
+ *  @intf      USB interface structure
+ */
+static void if_usb_disconnect(struct usb_interface *intf)
+{
+       struct if_usb_card *cardp = usb_get_intfdata(intf);
+       struct lbtf_private *priv = cardp->priv;
+
+       lbtf_deb_enter(LBTF_DEB_MAIN);
+
+       if_usb_reset_device(cardp);
+
+       if (priv)
+               lbtf_remove_card(priv);
+
+       /* Unlink and free urb */
+       if_usb_free(cardp);
+
+       usb_set_intfdata(intf, NULL);
+       usb_put_dev(interface_to_usbdev(intf));
+
+       lbtf_deb_leave(LBTF_DEB_MAIN);
+}
+
+/**
+ *  if_usb_send_fw_pkt -  This function downloads the FW
+ *
+ *  @priv      pointer to struct lbtf_private
+ *
+ *  Returns: 0
+ */
+static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
+{
+       struct fwdata *fwdata = cardp->ep_out_buf;
+       u8 *firmware = (u8 *) cardp->fw->data;
+
+       lbtf_deb_enter(LBTF_DEB_FW);
+
+       /* If we got a CRC failure on the last block, back
+          up and retry it */
+       if (!cardp->CRC_OK) {
+               cardp->totalbytes = cardp->fwlastblksent;
+               cardp->fwseqnum--;
+       }
+
+       lbtf_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n",
+                    cardp->totalbytes);
+
+       /* struct fwdata (which we sent to the card) has an
+          extra __le32 field in between the header and the data,
+          which is not in the struct fwheader in the actual
+          firmware binary. Insert the seqnum in the middle... */
+       memcpy(&fwdata->hdr, &firmware[cardp->totalbytes],
+              sizeof(struct fwheader));
+
+       cardp->fwlastblksent = cardp->totalbytes;
+       cardp->totalbytes += sizeof(struct fwheader);
+
+       memcpy(fwdata->data, &firmware[cardp->totalbytes],
+              le32_to_cpu(fwdata->hdr.datalength));
+
+       lbtf_deb_usb2(&cardp->udev->dev, "Data length = %d\n",
+                    le32_to_cpu(fwdata->hdr.datalength));
+
+       fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
+       cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
+
+       usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
+                    le32_to_cpu(fwdata->hdr.datalength), 0);
+
+       if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
+               lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
+               lbtf_deb_usb2(&cardp->udev->dev,
+                       "seqnum = %d totalbytes = %d\n",
+                       cardp->fwseqnum, cardp->totalbytes);
+       } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
+               lbtf_deb_usb2(&cardp->udev->dev,
+                       "Host has finished FW downloading\n");
+               lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n");
+
+               /* Host has finished FW downloading
+                * Donwloading FW JUMP BLOCK
+                */
+               cardp->fwfinalblk = 1;
+       }
+
+       lbtf_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n",
+                    cardp->totalbytes);
+
+       lbtf_deb_leave(LBTF_DEB_FW);
+       return 0;
+}
+
+static int if_usb_reset_device(struct if_usb_card *cardp)
+{
+       struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
+       int ret;
+
+       lbtf_deb_enter(LBTF_DEB_USB);
+
+       *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
+
+       cmd->hdr.command = cpu_to_le16(CMD_802_11_RESET);
+       cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset));
+       cmd->hdr.result = cpu_to_le16(0);
+       cmd->hdr.seqnum = cpu_to_le16(0x5a5a);
+       cmd->action = cpu_to_le16(CMD_ACT_HALT);
+       usb_tx_block(cardp, cardp->ep_out_buf,
+                    4 + sizeof(struct cmd_ds_802_11_reset), 0);
+
+       msleep(100);
+       ret = usb_reset_device(cardp->udev);
+       msleep(100);
+
+       lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret);
+
+       return ret;
+}
+
+/**
+ *  usb_tx_block - transfer data to the device
+ *
+ *  @priv      pointer to struct lbtf_private
+ *  @payload   pointer to payload data
+ *  @nb                data length
+ *  @data      non-zero for data, zero for commands
+ *
+ *  Returns: 0 on success, nonzero otherwise.
+ */
+static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
+                       uint16_t nb, u8 data)
+{
+       int ret = -1;
+       struct urb *urb;
+
+       lbtf_deb_enter(LBTF_DEB_USB);
+       /* check if device is removed */
+       if (cardp->priv->surpriseremoved) {
+               lbtf_deb_usbd(&cardp->udev->dev, "Device removed\n");
+               goto tx_ret;
+       }
+
+       if (data)
+               urb = cardp->tx_urb;
+       else
+               urb = cardp->cmd_urb;
+
+       usb_fill_bulk_urb(urb, cardp->udev,
+                         usb_sndbulkpipe(cardp->udev,
+                                         cardp->ep_out),
+                         payload, nb, if_usb_write_bulk_callback, cardp);
+
+       urb->transfer_flags |= URB_ZERO_PACKET;
+
+       if (usb_submit_urb(urb, GFP_ATOMIC)) {
+               lbtf_deb_usbd(&cardp->udev->dev,
+                       "usb_submit_urb failed: %d\n", ret);
+               goto tx_ret;
+       }
+
+       lbtf_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
+
+       ret = 0;
+
+tx_ret:
+       lbtf_deb_leave(LBTF_DEB_USB);
+       return ret;
+}
+
+static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
+                                 void (*callbackfn)(struct urb *urb))
+{
+       struct sk_buff *skb;
+       int ret = -1;
+
+       lbtf_deb_enter(LBTF_DEB_USB);
+
+       skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+       if (!skb) {
+               pr_err("No free skb\n");
+               lbtf_deb_leave(LBTF_DEB_USB);
+               return -1;
+       }
+
+       cardp->rx_skb = skb;
+
+       /* Fill the receive configuration URB and initialise the Rx call back */
+       usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
+                         usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
+                         skb_tail_pointer(skb),
+                         MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp);
+
+       cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
+
+       lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n",
+               cardp->rx_urb);
+       ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC);
+       if (ret) {
+               lbtf_deb_usbd(&cardp->udev->dev,
+                       "Submit Rx URB failed: %d\n", ret);
+               kfree_skb(skb);
+               cardp->rx_skb = NULL;
+               lbtf_deb_leave(LBTF_DEB_USB);
+               return -1;
+       } else {
+               lbtf_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n");
+               lbtf_deb_leave(LBTF_DEB_USB);
+               return 0;
+       }
+}
+
+static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
+{
+       return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
+}
+
+static int if_usb_submit_rx_urb(struct if_usb_card *cardp)
+{
+       return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
+}
+
+static void if_usb_receive_fwload(struct urb *urb)
+{
+       struct if_usb_card *cardp = urb->context;
+       struct sk_buff *skb = cardp->rx_skb;
+       struct fwsyncheader *syncfwheader;
+       struct bootcmdresp bcmdresp;
+
+       lbtf_deb_enter(LBTF_DEB_USB);
+       if (urb->status) {
+               lbtf_deb_usbd(&cardp->udev->dev,
+                            "URB status is failed during fw load\n");
+               kfree_skb(skb);
+               lbtf_deb_leave(LBTF_DEB_USB);
+               return;
+       }
+
+       if (cardp->fwdnldover) {
+               __le32 *tmp = (__le32 *)(skb->data);
+
+               if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) &&
+                   tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) {
+                       /* Firmware ready event received */
+                       pr_info("Firmware ready event received\n");
+                       wake_up(&cardp->fw_wq);
+               } else {
+                       lbtf_deb_usb("Waiting for confirmation; got %x %x\n",
+                                   le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1]));
+                       if_usb_submit_rx_urb_fwload(cardp);
+               }
+               kfree_skb(skb);
+               lbtf_deb_leave(LBTF_DEB_USB);
+               return;
+       }
+       if (cardp->bootcmdresp <= 0) {
+               memcpy(&bcmdresp, skb->data, sizeof(bcmdresp));
+
+               if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
+                       kfree_skb(skb);
+                       if_usb_submit_rx_urb_fwload(cardp);
+                       cardp->bootcmdresp = 1;
+                       /* Received valid boot command response */
+                       lbtf_deb_usbd(&cardp->udev->dev,
+                                    "Received valid boot command response\n");
+                       lbtf_deb_leave(LBTF_DEB_USB);
+                       return;
+               }
+               if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
+                       if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
+                           bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
+                           bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) {
+                               if (!cardp->bootcmdresp)
+                                       pr_info("Firmware already seems alive; resetting\n");
+                               cardp->bootcmdresp = -1;
+                       } else {
+                               pr_info("boot cmd response wrong magic number (0x%x)\n",
+                                           le32_to_cpu(bcmdresp.magic));
+                       }
+               } else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
+                       pr_info("boot cmd response cmd_tag error (%d)\n",
+                               bcmdresp.cmd);
+               } else if (bcmdresp.result != BOOT_CMD_RESP_OK) {
+                       pr_info("boot cmd response result error (%d)\n",
+                               bcmdresp.result);
+               } else {
+                       cardp->bootcmdresp = 1;
+                       lbtf_deb_usbd(&cardp->udev->dev,
+                               "Received valid boot command response\n");
+               }
+
+               kfree_skb(skb);
+               if_usb_submit_rx_urb_fwload(cardp);
+               lbtf_deb_leave(LBTF_DEB_USB);
+               return;
+       }
+
+       syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader),
+                              GFP_ATOMIC);
+       if (!syncfwheader) {
+               lbtf_deb_usbd(&cardp->udev->dev,
+                       "Failure to allocate syncfwheader\n");
+               kfree_skb(skb);
+               lbtf_deb_leave(LBTF_DEB_USB);
+               return;
+       }
+
+       if (!syncfwheader->cmd) {
+               lbtf_deb_usb2(&cardp->udev->dev,
+                       "FW received Blk with correct CRC\n");
+               lbtf_deb_usb2(&cardp->udev->dev,
+                       "FW received Blk seqnum = %d\n",
+                       le32_to_cpu(syncfwheader->seqnum));
+               cardp->CRC_OK = 1;
+       } else {
+               lbtf_deb_usbd(&cardp->udev->dev,
+                       "FW received Blk with CRC error\n");
+               cardp->CRC_OK = 0;
+       }
+
+       kfree_skb(skb);
+
+       /* reschedule timer for 200ms hence */
+       mod_timer(&cardp->fw_timeout, jiffies + (HZ/5));
+
+       if (cardp->fwfinalblk) {
+               cardp->fwdnldover = 1;
+               goto exit;
+       }
+
+       if_usb_send_fw_pkt(cardp);
+
+ exit:
+       if_usb_submit_rx_urb_fwload(cardp);
+
+       kfree(syncfwheader);
+
+       lbtf_deb_leave(LBTF_DEB_USB);
+}
+
+#define MRVDRV_MIN_PKT_LEN     30
+
+static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
+                                      struct if_usb_card *cardp,
+                                      struct lbtf_private *priv)
+{
+       if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
+           || recvlength < MRVDRV_MIN_PKT_LEN) {
+               lbtf_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n");
+               kfree_skb(skb);
+               return;
+       }
+
+       skb_put(skb, recvlength);
+       skb_pull(skb, MESSAGE_HEADER_LEN);
+       lbtf_rx(priv, skb);
+}
+
+static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
+                                     struct sk_buff *skb,
+                                     struct if_usb_card *cardp,
+                                     struct lbtf_private *priv)
+{
+       if (recvlength > LBS_CMD_BUFFER_SIZE) {
+               lbtf_deb_usbd(&cardp->udev->dev,
+                            "The receive buffer is too large\n");
+               kfree_skb(skb);
+               return;
+       }
+
+       BUG_ON(!in_interrupt());
+
+       spin_lock(&priv->driver_lock);
+       memcpy(priv->cmd_resp_buff, recvbuff + MESSAGE_HEADER_LEN,
+              recvlength - MESSAGE_HEADER_LEN);
+       kfree_skb(skb);
+       lbtf_cmd_response_rx(priv);
+       spin_unlock(&priv->driver_lock);
+}
+
+/**
+ *  if_usb_receive - read data received from the device.
+ *
+ *  @urb               pointer to struct urb
+ */
+static void if_usb_receive(struct urb *urb)
+{
+       struct if_usb_card *cardp = urb->context;
+       struct sk_buff *skb = cardp->rx_skb;
+       struct lbtf_private *priv = cardp->priv;
+       int recvlength = urb->actual_length;
+       uint8_t *recvbuff = NULL;
+       uint32_t recvtype = 0;
+       __le32 *pkt = (__le32 *) skb->data;
+
+       lbtf_deb_enter(LBTF_DEB_USB);
+
+       if (recvlength) {
+               if (urb->status) {
+                       lbtf_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
+                                    urb->status);
+                       kfree_skb(skb);
+                       goto setup_for_next;
+               }
+
+               recvbuff = skb->data;
+               recvtype = le32_to_cpu(pkt[0]);
+               lbtf_deb_usbd(&cardp->udev->dev,
+                           "Recv length = 0x%x, Recv type = 0x%X\n",
+                           recvlength, recvtype);
+       } else if (urb->status) {
+               kfree_skb(skb);
+               lbtf_deb_leave(LBTF_DEB_USB);
+               return;
+       }
+
+       switch (recvtype) {
+       case CMD_TYPE_DATA:
+               process_cmdtypedata(recvlength, skb, cardp, priv);
+               break;
+
+       case CMD_TYPE_REQUEST:
+               process_cmdrequest(recvlength, recvbuff, skb, cardp, priv);
+               break;
+
+       case CMD_TYPE_INDICATION:
+       {
+               /* Event cause handling */
+               u32 event_cause = le32_to_cpu(pkt[1]);
+               lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n",
+                       event_cause);
+
+               /* Icky undocumented magic special case */
+               if (event_cause & 0xffff0000) {
+                       u16 tmp;
+                       u8 retrycnt;
+                       u8 failure;
+
+                       tmp = event_cause >> 16;
+                       retrycnt = tmp & 0x00ff;
+                       failure = (tmp & 0xff00) >> 8;
+                       lbtf_send_tx_feedback(priv, retrycnt, failure);
+               } else if (event_cause == LBTF_EVENT_BCN_SENT)
+                       lbtf_bcn_sent(priv);
+               else
+                       lbtf_deb_usbd(&cardp->udev->dev,
+                              "Unsupported notification %d received\n",
+                              event_cause);
+               kfree_skb(skb);
+               break;
+       }
+       default:
+               lbtf_deb_usbd(&cardp->udev->dev,
+                       "libertastf: unknown command type 0x%X\n", recvtype);
+               kfree_skb(skb);
+               break;
+       }
+
+setup_for_next:
+       if_usb_submit_rx_urb(cardp);
+       lbtf_deb_leave(LBTF_DEB_USB);
+}
+
+/**
+ *  if_usb_host_to_card -  Download data to the device
+ *
+ *  @priv              pointer to struct lbtf_private structure
+ *  @type              type of data
+ *  @buf               pointer to data buffer
+ *  @len               number of bytes
+ *
+ *  Returns: 0 on success, nonzero otherwise
+ */
+static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
+                              uint8_t *payload, uint16_t nb)
+{
+       struct if_usb_card *cardp = priv->card;
+       u8 data = 0;
+
+       lbtf_deb_usbd(&cardp->udev->dev, "*** type = %u\n", type);
+       lbtf_deb_usbd(&cardp->udev->dev, "size after = %d\n", nb);
+
+       if (type == MVMS_CMD) {
+               *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
+       } else {
+               *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_DATA);
+               data = 1;
+       }
+
+       memcpy((cardp->ep_out_buf + MESSAGE_HEADER_LEN), payload, nb);
+
+       return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN,
+                           data);
+}
+
+/**
+ *  if_usb_issue_boot_command - Issue boot command to Boot2.
+ *
+ *  @ivalue   1 boots from FW by USB-Download, 2 boots from FW in EEPROM.
+ *
+ *  Returns: 0
+ */
+static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue)
+{
+       struct bootcmd *bootcmd = cardp->ep_out_buf;
+
+       /* Prepare command */
+       bootcmd->magic = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
+       bootcmd->cmd = ivalue;
+       memset(bootcmd->pad, 0, sizeof(bootcmd->pad));
+
+       /* Issue command */
+       usb_tx_block(cardp, cardp->ep_out_buf, sizeof(*bootcmd), 0);
+
+       return 0;
+}
+
+
+/**
+ *  check_fwfile_format - Check the validity of Boot2/FW image.
+ *
+ *  @data      pointer to image
+ *  @totlen    image length
+ *
+ *  Returns: 0 if the image is valid, nonzero otherwise.
+ */
+static int check_fwfile_format(const u8 *data, u32 totlen)
+{
+       u32 bincmd, exit;
+       u32 blksize, offset, len;
+       int ret;
+
+       ret = 1;
+       exit = len = 0;
+
+       do {
+               struct fwheader *fwh = (void *) data;
+
+               bincmd = le32_to_cpu(fwh->dnldcmd);
+               blksize = le32_to_cpu(fwh->datalength);
+               switch (bincmd) {
+               case FW_HAS_DATA_TO_RECV:
+                       offset = sizeof(struct fwheader) + blksize;
+                       data += offset;
+                       len += offset;
+                       if (len >= totlen)
+                               exit = 1;
+                       break;
+               case FW_HAS_LAST_BLOCK:
+                       exit = 1;
+                       ret = 0;
+                       break;
+               default:
+                       exit = 1;
+                       break;
+               }
+       } while (!exit);
+
+       if (ret)
+               pr_err("firmware file format check FAIL\n");
+       else
+               lbtf_deb_fw("firmware file format check PASS\n");
+
+       return ret;
+}
+
+
+static int if_usb_prog_firmware(struct if_usb_card *cardp)
+{
+       int i = 0;
+       static int reset_count = 10;
+       int ret = 0;
+
+       lbtf_deb_enter(LBTF_DEB_USB);
+
+       kernel_param_lock(THIS_MODULE);
+       ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
+       if (ret < 0) {
+               pr_err("request_firmware() failed with %#x\n", ret);
+               pr_err("firmware %s not found\n", lbtf_fw_name);
+               kernel_param_unlock(THIS_MODULE);
+               goto done;
+       }
+       kernel_param_unlock(THIS_MODULE);
+
+       if (check_fwfile_format(cardp->fw->data, cardp->fw->size))
+               goto release_fw;
+
+restart:
+       if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
+               lbtf_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
+               ret = -1;
+               goto release_fw;
+       }
+
+       cardp->bootcmdresp = 0;
+       do {
+               int j = 0;
+               i++;
+               /* Issue Boot command = 1, Boot from Download-FW */
+               if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
+               /* wait for command response */
+               do {
+                       j++;
+                       msleep_interruptible(100);
+               } while (cardp->bootcmdresp == 0 && j < 10);
+       } while (cardp->bootcmdresp == 0 && i < 5);
+
+       if (cardp->bootcmdresp <= 0) {
+               if (--reset_count >= 0) {
+                       if_usb_reset_device(cardp);
+                       goto restart;
+               }
+               return -1;
+       }
+
+       i = 0;
+
+       cardp->totalbytes = 0;
+       cardp->fwlastblksent = 0;
+       cardp->CRC_OK = 1;
+       cardp->fwdnldover = 0;
+       cardp->fwseqnum = -1;
+       cardp->totalbytes = 0;
+       cardp->fwfinalblk = 0;
+
+       /* Send the first firmware packet... */
+       if_usb_send_fw_pkt(cardp);
+
+       /* ... and wait for the process to complete */
+       wait_event_interruptible(cardp->fw_wq, cardp->priv->surpriseremoved ||
+                                              cardp->fwdnldover);
+
+       del_timer_sync(&cardp->fw_timeout);
+       usb_kill_urb(cardp->rx_urb);
+
+       if (!cardp->fwdnldover) {
+               pr_info("failed to load fw, resetting device!\n");
+               if (--reset_count >= 0) {
+                       if_usb_reset_device(cardp);
+                       goto restart;
+               }
+
+               pr_info("FW download failure, time = %d ms\n", i * 100);
+               ret = -1;
+               goto release_fw;
+       }
+
+       cardp->priv->fw_ready = 1;
+
+ release_fw:
+       release_firmware(cardp->fw);
+       cardp->fw = NULL;
+
+       if_usb_setup_firmware(cardp->priv);
+
+ done:
+       lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret);
+       return ret;
+}
+
+
+#define if_usb_suspend NULL
+#define if_usb_resume NULL
+
+static struct usb_driver if_usb_driver = {
+       .name = DRV_NAME,
+       .probe = if_usb_probe,
+       .disconnect = if_usb_disconnect,
+       .id_table = if_usb_table,
+       .suspend = if_usb_suspend,
+       .resume = if_usb_resume,
+       .disable_hub_initiated_lpm = 1,
+};
+
+module_usb_driver(if_usb_driver);
+
+MODULE_DESCRIPTION("8388 USB WLAN Thinfirm Driver");
+MODULE_AUTHOR("Cozybit Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.h b/drivers/net/wireless/marvell/libertas_tf/if_usb.h
new file mode 100644 (file)
index 0000000..6fa5b3f
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  Copyright (C) 2008, cozybit Inc.
+ *  Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ */
+#include <linux/wait.h>
+#include <linux/timer.h>
+
+struct lbtf_private;
+
+/**
+  * This file contains definition for USB interface.
+  */
+#define CMD_TYPE_REQUEST               0xF00DFACE
+#define CMD_TYPE_DATA                  0xBEADC0DE
+#define CMD_TYPE_INDICATION            0xBEEFFACE
+
+#define BOOT_CMD_FW_BY_USB             0x01
+#define BOOT_CMD_FW_IN_EEPROM          0x02
+#define BOOT_CMD_UPDATE_BOOT2          0x03
+#define BOOT_CMD_UPDATE_FW             0x04
+#define BOOT_CMD_MAGIC_NUMBER          0x4C56524D   /* LVRM */
+
+struct bootcmd {
+       __le32  magic;
+       uint8_t cmd;
+       uint8_t pad[11];
+};
+
+#define BOOT_CMD_RESP_OK               0x0001
+#define BOOT_CMD_RESP_FAIL             0x0000
+
+struct bootcmdresp {
+       __le32  magic;
+       uint8_t cmd;
+       uint8_t result;
+       uint8_t pad[2];
+};
+
+/** USB card description structure*/
+struct if_usb_card {
+       struct usb_device *udev;
+       struct urb *rx_urb, *tx_urb, *cmd_urb;
+       struct lbtf_private *priv;
+
+       struct sk_buff *rx_skb;
+
+       uint8_t ep_in;
+       uint8_t ep_out;
+
+       int8_t bootcmdresp;
+
+       int ep_in_size;
+
+       void *ep_out_buf;
+       int ep_out_size;
+
+       const struct firmware *fw;
+       struct timer_list fw_timeout;
+       wait_queue_head_t fw_wq;
+       uint32_t fwseqnum;
+       uint32_t totalbytes;
+       uint32_t fwlastblksent;
+       uint8_t CRC_OK;
+       uint8_t fwdnldover;
+       uint8_t fwfinalblk;
+
+       __le16 boot2_version;
+};
+
+/** fwheader */
+struct fwheader {
+       __le32 dnldcmd;
+       __le32 baseaddr;
+       __le32 datalength;
+       __le32 CRC;
+};
+
+#define FW_MAX_DATA_BLK_SIZE   600
+/** FWData */
+struct fwdata {
+       struct fwheader hdr;
+       __le32 seqnum;
+       uint8_t data[0];
+};
+
+/** fwsyncheader */
+struct fwsyncheader {
+       __le32 cmd;
+       __le32 seqnum;
+};
+
+#define FW_HAS_DATA_TO_RECV            0x00000001
+#define FW_HAS_LAST_BLOCK              0x00000004
diff --git a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
new file mode 100644 (file)
index 0000000..ad77b92
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ *  Copyright (C) 2008, cozybit Inc.
+ *  Copyright (C) 2007, Red Hat, Inc.
+ *  Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/kthread.h>
+#include <net/mac80211.h>
+
+#include "deb_defs.h"
+
+#ifndef DRV_NAME
+#define DRV_NAME "libertas_tf"
+#endif
+
+#define        MRVL_DEFAULT_RETRIES                    9
+#define MRVL_PER_PACKET_RATE                   0x10
+#define MRVL_MAX_BCN_SIZE                      440
+#define CMD_OPTION_WAITFORRSP                  0x0002
+
+/* Return command are almost always the same as the host command, but with
+ * bit 15 set high.  There are a few exceptions, though...
+ */
+#define CMD_RET(cmd)                   (0x8000 | cmd)
+
+/* Command codes */
+#define CMD_GET_HW_SPEC                                0x0003
+#define CMD_802_11_RESET                       0x0005
+#define CMD_MAC_MULTICAST_ADR                  0x0010
+#define CMD_802_11_RADIO_CONTROL               0x001c
+#define CMD_802_11_RF_CHANNEL                  0x001d
+#define CMD_802_11_RF_TX_POWER                 0x001e
+#define CMD_MAC_CONTROL                                0x0028
+#define CMD_802_11_MAC_ADDRESS                 0x004d
+#define        CMD_SET_BOOT2_VER                       0x00a5
+#define CMD_802_11_BEACON_CTRL                 0x00b0
+#define CMD_802_11_BEACON_SET                  0x00cb
+#define CMD_802_11_SET_MODE                    0x00cc
+#define CMD_802_11_SET_BSSID                   0x00cd
+
+#define CMD_ACT_GET                    0x0000
+#define CMD_ACT_SET                    0x0001
+
+/* Define action or option for CMD_802_11_RESET */
+#define CMD_ACT_HALT                   0x0003
+
+/* Define action or option for CMD_MAC_CONTROL */
+#define CMD_ACT_MAC_RX_ON                      0x0001
+#define CMD_ACT_MAC_TX_ON                      0x0002
+#define CMD_ACT_MAC_MULTICAST_ENABLE           0x0020
+#define CMD_ACT_MAC_BROADCAST_ENABLE           0x0040
+#define CMD_ACT_MAC_PROMISCUOUS_ENABLE         0x0080
+#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE       0x0100
+
+/* Define action or option for CMD_802_11_RADIO_CONTROL */
+#define CMD_TYPE_AUTO_PREAMBLE         0x0001
+#define CMD_TYPE_SHORT_PREAMBLE                0x0002
+#define CMD_TYPE_LONG_PREAMBLE         0x0003
+
+#define TURN_ON_RF                     0x01
+#define RADIO_ON                       0x01
+#define RADIO_OFF                      0x00
+
+#define SET_AUTO_PREAMBLE              0x05
+#define SET_SHORT_PREAMBLE             0x03
+#define SET_LONG_PREAMBLE              0x01
+
+/* Define action or option for CMD_802_11_RF_CHANNEL */
+#define CMD_OPT_802_11_RF_CHANNEL_GET  0x00
+#define CMD_OPT_802_11_RF_CHANNEL_SET  0x01
+
+/* Codes for CMD_802_11_SET_MODE */
+enum lbtf_mode {
+       LBTF_PASSIVE_MODE,
+       LBTF_STA_MODE,
+       LBTF_AP_MODE,
+};
+
+/** Card Event definition */
+#define MACREG_INT_CODE_FIRMWARE_READY         48
+/** Buffer Constants */
+
+/*     The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical
+*      addresses of TxPD buffers. Station has only 8 TxPD available, Whereas
+*      driver has more local TxPDs. Each TxPD on the host memory is associated
+*      with a Tx control node. The driver maintains 8 RxPD descriptors for
+*      station firmware to store Rx packet information.
+*
+*      Current version of MAC has a 32x6 multicast address buffer.
+*
+*      802.11b can have up to  14 channels, the driver keeps the
+*      BSSID(MAC address) of each APs or Ad hoc stations it has sensed.
+*/
+
+#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
+#define LBS_NUM_CMD_BUFFERS             10
+#define LBS_CMD_BUFFER_SIZE             (2 * 1024)
+#define MRVDRV_MAX_CHANNEL_SIZE                14
+#define MRVDRV_SNAP_HEADER_LEN          8
+
+#define        LBS_UPLD_SIZE                   2312
+#define DEV_NAME_LEN                   32
+
+/** Misc constants */
+/* This section defines 802.11 specific contants */
+
+#define MRVDRV_MAX_REGION_CODE                 6
+/**
+ * the table to keep region code
+ */
+#define LBTF_REGDOMAIN_US      0x10
+#define LBTF_REGDOMAIN_CA      0x20
+#define LBTF_REGDOMAIN_EU      0x30
+#define LBTF_REGDOMAIN_SP      0x31
+#define LBTF_REGDOMAIN_FR      0x32
+#define LBTF_REGDOMAIN_JP      0x40
+
+#define SBI_EVENT_CAUSE_SHIFT          3
+
+/** RxPD status */
+
+#define MRVDRV_RXPD_STATUS_OK                0x0001
+
+
+/* This is for firmware specific length */
+#define EXTRA_LEN      36
+
+#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
+       (ETH_FRAME_LEN + sizeof(struct txpd) + EXTRA_LEN)
+
+#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
+       (ETH_FRAME_LEN + sizeof(struct rxpd) \
+        + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
+
+#define        CMD_F_HOSTCMD           (1 << 0)
+#define FW_CAPINFO_WPA         (1 << 0)
+
+#define RF_ANTENNA_1           0x1
+#define RF_ANTENNA_2           0x2
+#define RF_ANTENNA_AUTO                0xFFFF
+
+#define LBTF_EVENT_BCN_SENT    55
+
+/** Global Variable Declaration */
+/** mv_ms_type */
+enum mv_ms_type {
+       MVMS_DAT = 0,
+       MVMS_CMD = 1,
+       MVMS_TXDONE = 2,
+       MVMS_EVENT
+};
+
+extern struct workqueue_struct *lbtf_wq;
+
+struct lbtf_private;
+
+struct lbtf_offset_value {
+       u32 offset;
+       u32 value;
+};
+
+struct channel_range {
+       u8 regdomain;
+       u8 start;
+       u8 end; /* exclusive (channel must be less than end) */
+};
+
+struct if_usb_card;
+
+/** Private structure for the MV device */
+struct lbtf_private {
+       void *card;
+       struct ieee80211_hw *hw;
+
+       /* Command response buffer */
+       u8 cmd_resp_buff[LBS_UPLD_SIZE];
+       /* Download sent:
+          bit0 1/0=data_sent/data_tx_done,
+          bit1 1/0=cmd_sent/cmd_tx_done,
+          all other bits reserved 0 */
+       struct ieee80211_vif *vif;
+
+       struct work_struct cmd_work;
+       struct work_struct tx_work;
+       /** Hardware access */
+       int (*hw_host_to_card) (struct lbtf_private *priv, u8 type, u8 *payload, u16 nb);
+       int (*hw_prog_firmware) (struct if_usb_card *cardp);
+       int (*hw_reset_device) (struct if_usb_card *cardp);
+
+
+       /** Wlan adapter data structure*/
+       /** STATUS variables */
+       u32 fwrelease;
+       u32 fwcapinfo;
+       /* protected with big lock */
+
+       struct mutex lock;
+
+       /** command-related variables */
+       u16 seqnum;
+       /* protected by big lock */
+
+       struct cmd_ctrl_node *cmd_array;
+       /** Current command */
+       struct cmd_ctrl_node *cur_cmd;
+       /** command Queues */
+       /** Free command buffers */
+       struct list_head cmdfreeq;
+       /** Pending command buffers */
+       struct list_head cmdpendingq;
+
+       /** spin locks */
+       spinlock_t driver_lock;
+
+       /** Timers */
+       struct timer_list command_timer;
+       int nr_retries;
+       int cmd_timed_out;
+
+       u8 cmd_response_rxed;
+
+       /** capability Info used in Association, start, join */
+       u16 capability;
+
+       /** MAC address information */
+       u8 current_addr[ETH_ALEN];
+       u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
+       u32 nr_of_multicastmacaddr;
+       int cur_freq;
+
+       struct sk_buff *skb_to_tx;
+       struct sk_buff *tx_skb;
+
+       /** NIC Operation characteristics */
+       u16 mac_control;
+       u16 regioncode;
+       struct channel_range range;
+
+       u8 radioon;
+       u32 preamble;
+
+       struct ieee80211_channel channels[14];
+       struct ieee80211_rate rates[12];
+       struct ieee80211_supported_band band;
+       struct lbtf_offset_value offsetvalue;
+
+       u8 fw_ready;
+       u8 surpriseremoved;
+       struct sk_buff_head bc_ps_buf;
+
+       /* Most recently reported noise in dBm */
+       s8 noise;
+};
+
+/* 802.11-related definitions */
+
+/* TxPD descriptor */
+struct txpd {
+       /* Current Tx packet status */
+       __le32 tx_status;
+       /* Tx control */
+       __le32 tx_control;
+       __le32 tx_packet_location;
+       /* Tx packet length */
+       __le16 tx_packet_length;
+       /* First 2 byte of destination MAC address */
+       u8 tx_dest_addr_high[2];
+       /* Last 4 byte of destination MAC address */
+       u8 tx_dest_addr_low[4];
+       /* Pkt Priority */
+       u8 priority;
+       /* Pkt Trasnit Power control */
+       u8 powermgmt;
+       /* Time the packet has been queued in the driver (units = 2ms) */
+       u8 pktdelay_2ms;
+       /* reserved */
+       u8 reserved1;
+};
+
+/* RxPD Descriptor */
+struct rxpd {
+       /* Current Rx packet status */
+       __le16 status;
+
+       /* SNR */
+       u8 snr;
+
+       /* Tx control */
+       u8 rx_control;
+
+       /* Pkt length */
+       __le16 pkt_len;
+
+       /* Noise Floor */
+       u8 nf;
+
+       /* Rx Packet Rate */
+       u8 rx_rate;
+
+       /* Pkt addr */
+       __le32 pkt_ptr;
+
+       /* Next Rx RxPD addr */
+       __le32 next_rxpd_ptr;
+
+       /* Pkt Priority */
+       u8 priority;
+       u8 reserved[3];
+};
+
+struct cmd_header {
+       __le16 command;
+       __le16 size;
+       __le16 seqnum;
+       __le16 result;
+} __packed;
+
+struct cmd_ctrl_node {
+       struct list_head list;
+       int result;
+       /* command response */
+       int (*callback)(struct lbtf_private *,
+                       unsigned long, struct cmd_header *);
+       unsigned long callback_arg;
+       /* command data */
+       struct cmd_header *cmdbuf;
+       /* wait queue */
+       u16 cmdwaitqwoken;
+       wait_queue_head_t cmdwait_q;
+};
+
+/*
+ * Define data structure for CMD_GET_HW_SPEC
+ * This structure defines the response for the GET_HW_SPEC command
+ */
+struct cmd_ds_get_hw_spec {
+       struct cmd_header hdr;
+
+       /* HW Interface version number */
+       __le16 hwifversion;
+       /* HW version number */
+       __le16 version;
+       /* Max number of TxPD FW can handle */
+       __le16 nr_txpd;
+       /* Max no of Multicast address */
+       __le16 nr_mcast_adr;
+       /* MAC address */
+       u8 permanentaddr[6];
+
+       /* region Code */
+       __le16 regioncode;
+
+       /* Number of antenna used */
+       __le16 nr_antenna;
+
+       /* FW release number, example 0x01030304 = 2.3.4p1 */
+       __le32 fwrelease;
+
+       /* Base Address of TxPD queue */
+       __le32 wcb_base;
+       /* Read Pointer of RxPd queue */
+       __le32 rxpd_rdptr;
+
+       /* Write Pointer of RxPd queue */
+       __le32 rxpd_wrptr;
+
+       /*FW/HW capability */
+       __le32 fwcapinfo;
+} __packed;
+
+struct cmd_ds_mac_control {
+       struct cmd_header hdr;
+       __le16 action;
+       u16 reserved;
+};
+
+struct cmd_ds_802_11_mac_address {
+       struct cmd_header hdr;
+
+       __le16 action;
+       uint8_t macadd[ETH_ALEN];
+};
+
+struct cmd_ds_mac_multicast_addr {
+       struct cmd_header hdr;
+
+       __le16 action;
+       __le16 nr_of_adrs;
+       u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
+};
+
+struct cmd_ds_set_mode {
+       struct cmd_header hdr;
+
+       __le16 mode;
+};
+
+struct cmd_ds_set_bssid {
+       struct cmd_header hdr;
+
+       u8 bssid[6];
+       u8 activate;
+};
+
+struct cmd_ds_802_11_radio_control {
+       struct cmd_header hdr;
+
+       __le16 action;
+       __le16 control;
+};
+
+
+struct cmd_ds_802_11_rf_channel {
+       struct cmd_header hdr;
+
+       __le16 action;
+       __le16 channel;
+       __le16 rftype;      /* unused */
+       __le16 reserved;    /* unused */
+       u8 channellist[32]; /* unused */
+};
+
+struct cmd_ds_set_boot2_ver {
+       struct cmd_header hdr;
+
+       __le16 action;
+       __le16 version;
+};
+
+struct cmd_ds_802_11_reset {
+       struct cmd_header hdr;
+
+       __le16 action;
+};
+
+struct cmd_ds_802_11_beacon_control {
+       struct cmd_header hdr;
+
+       __le16 action;
+       __le16 beacon_enable;
+       __le16 beacon_period;
+};
+
+struct cmd_ds_802_11_beacon_set {
+       struct cmd_header hdr;
+
+       __le16 len;
+       u8 beacon[MRVL_MAX_BCN_SIZE];
+};
+
+struct lbtf_private;
+struct cmd_ctrl_node;
+
+/** Function Prototype Declaration */
+void lbtf_set_mac_control(struct lbtf_private *priv);
+
+int lbtf_free_cmd_buffer(struct lbtf_private *priv);
+
+int lbtf_allocate_cmd_buffer(struct lbtf_private *priv);
+int lbtf_execute_next_command(struct lbtf_private *priv);
+int lbtf_set_radio_control(struct lbtf_private *priv);
+int lbtf_update_hw_spec(struct lbtf_private *priv);
+int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv);
+void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode);
+void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid);
+int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr);
+
+int lbtf_set_channel(struct lbtf_private *priv, u8 channel);
+
+int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon);
+int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
+                    int beacon_int);
+
+
+int lbtf_process_rx_command(struct lbtf_private *priv);
+void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd,
+                         int result);
+void lbtf_cmd_response_rx(struct lbtf_private *priv);
+
+/* main.c */
+struct chan_freq_power *lbtf_get_region_cfp_table(u8 region,
+       int *cfp_no);
+struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev);
+int lbtf_remove_card(struct lbtf_private *priv);
+int lbtf_start_card(struct lbtf_private *priv);
+int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb);
+void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail);
+void lbtf_bcn_sent(struct lbtf_private *priv);
+
+/* support functions for cmd.c */
+/* lbtf_cmd() infers the size of the buffer to copy data back into, from
+   the size of the target of the pointer. Since the command to be sent
+   may often be smaller, that size is set in cmd->size by the caller.*/
+#define lbtf_cmd(priv, cmdnr, cmd, cb, cb_arg) ({              \
+       uint16_t __sz = le16_to_cpu((cmd)->hdr.size);           \
+       (cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd)));          \
+       __lbtf_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \
+})
+
+#define lbtf_cmd_with_response(priv, cmdnr, cmd)       \
+       lbtf_cmd(priv, cmdnr, cmd, lbtf_cmd_copyback, (unsigned long) (cmd))
+
+void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
+       struct cmd_header *in_cmd, int in_cmd_size);
+
+int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
+             struct cmd_header *in_cmd, int in_cmd_size,
+             int (*callback)(struct lbtf_private *, unsigned long,
+                             struct cmd_header *),
+             unsigned long callback_arg);
+
+int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra,
+                    struct cmd_header *resp);
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
new file mode 100644 (file)
index 0000000..a47f0ac
--- /dev/null
@@ -0,0 +1,766 @@
+/*
+ *  Copyright (C) 2008, cozybit Inc.
+ *  Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/hardirq.h>
+#include <linux/slab.h>
+
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include "libertas_tf.h"
+
+#define DRIVER_RELEASE_VERSION "004.p0"
+/* thinfirm version: 5.132.X.pX */
+#define LBTF_FW_VER_MIN                0x05840300
+#define LBTF_FW_VER_MAX                0x0584ffff
+#define QOS_CONTROL_LEN                2
+
+/* Module parameters */
+unsigned int lbtf_debug;
+EXPORT_SYMBOL_GPL(lbtf_debug);
+module_param_named(libertas_tf_debug, lbtf_debug, int, 0644);
+
+static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION
+#ifdef DEBUG
+       "-dbg"
+#endif
+       "";
+
+struct workqueue_struct *lbtf_wq;
+
+static const struct ieee80211_channel lbtf_channels[] = {
+       { .center_freq = 2412, .hw_value = 1 },
+       { .center_freq = 2417, .hw_value = 2 },
+       { .center_freq = 2422, .hw_value = 3 },
+       { .center_freq = 2427, .hw_value = 4 },
+       { .center_freq = 2432, .hw_value = 5 },
+       { .center_freq = 2437, .hw_value = 6 },
+       { .center_freq = 2442, .hw_value = 7 },
+       { .center_freq = 2447, .hw_value = 8 },
+       { .center_freq = 2452, .hw_value = 9 },
+       { .center_freq = 2457, .hw_value = 10 },
+       { .center_freq = 2462, .hw_value = 11 },
+       { .center_freq = 2467, .hw_value = 12 },
+       { .center_freq = 2472, .hw_value = 13 },
+       { .center_freq = 2484, .hw_value = 14 },
+};
+
+/* This table contains the hardware specific values for the modulation rates. */
+static const struct ieee80211_rate lbtf_rates[] = {
+       { .bitrate = 10,
+         .hw_value = 0, },
+       { .bitrate = 20,
+         .hw_value = 1,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 55,
+         .hw_value = 2,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 110,
+         .hw_value = 3,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 60,
+         .hw_value = 5,
+         .flags = 0 },
+       { .bitrate = 90,
+         .hw_value = 6,
+         .flags = 0 },
+       { .bitrate = 120,
+         .hw_value = 7,
+         .flags = 0 },
+       { .bitrate = 180,
+         .hw_value = 8,
+         .flags = 0 },
+       { .bitrate = 240,
+         .hw_value = 9,
+         .flags = 0 },
+       { .bitrate = 360,
+         .hw_value = 10,
+         .flags = 0 },
+       { .bitrate = 480,
+         .hw_value = 11,
+         .flags = 0 },
+       { .bitrate = 540,
+         .hw_value = 12,
+         .flags = 0 },
+};
+
+static void lbtf_cmd_work(struct work_struct *work)
+{
+       struct lbtf_private *priv = container_of(work, struct lbtf_private,
+                                        cmd_work);
+
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       spin_lock_irq(&priv->driver_lock);
+       /* command response? */
+       if (priv->cmd_response_rxed) {
+               priv->cmd_response_rxed = 0;
+               spin_unlock_irq(&priv->driver_lock);
+               lbtf_process_rx_command(priv);
+               spin_lock_irq(&priv->driver_lock);
+       }
+
+       if (priv->cmd_timed_out && priv->cur_cmd) {
+               struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
+
+               if (++priv->nr_retries > 10) {
+                       lbtf_complete_command(priv, cmdnode,
+                                             -ETIMEDOUT);
+                       priv->nr_retries = 0;
+               } else {
+                       priv->cur_cmd = NULL;
+
+                       /* Stick it back at the _top_ of the pending
+                        * queue for immediate resubmission */
+                       list_add(&cmdnode->list, &priv->cmdpendingq);
+               }
+       }
+       priv->cmd_timed_out = 0;
+       spin_unlock_irq(&priv->driver_lock);
+
+       if (!priv->fw_ready) {
+               lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready");
+               return;
+       }
+
+       /* Execute the next command */
+       if (!priv->cur_cmd)
+               lbtf_execute_next_command(priv);
+
+       lbtf_deb_leave(LBTF_DEB_CMD);
+}
+
+/**
+ *  lbtf_setup_firmware: initialize firmware.
+ *
+ *  @priv    A pointer to struct lbtf_private structure
+ *
+ *  Returns: 0 on success.
+ */
+static int lbtf_setup_firmware(struct lbtf_private *priv)
+{
+       int ret = -1;
+
+       lbtf_deb_enter(LBTF_DEB_FW);
+       /*
+        * Read priv address from HW
+        */
+       eth_broadcast_addr(priv->current_addr);
+       ret = lbtf_update_hw_spec(priv);
+       if (ret) {
+               ret = -1;
+               goto done;
+       }
+
+       lbtf_set_mac_control(priv);
+       lbtf_set_radio_control(priv);
+
+       ret = 0;
+done:
+       lbtf_deb_leave_args(LBTF_DEB_FW, "ret: %d", ret);
+       return ret;
+}
+
+/**
+ *  This function handles the timeout of command sending.
+ *  It will re-send the same command again.
+ */
+static void command_timer_fn(unsigned long data)
+{
+       struct lbtf_private *priv = (struct lbtf_private *)data;
+       unsigned long flags;
+       lbtf_deb_enter(LBTF_DEB_CMD);
+
+       spin_lock_irqsave(&priv->driver_lock, flags);
+
+       if (!priv->cur_cmd) {
+               printk(KERN_DEBUG "libertastf: command timer expired; "
+                                 "no pending command\n");
+               goto out;
+       }
+
+       printk(KERN_DEBUG "libertas: command %x timed out\n",
+               le16_to_cpu(priv->cur_cmd->cmdbuf->command));
+
+       priv->cmd_timed_out = 1;
+       queue_work(lbtf_wq, &priv->cmd_work);
+out:
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+       lbtf_deb_leave(LBTF_DEB_CMD);
+}
+
+static int lbtf_init_adapter(struct lbtf_private *priv)
+{
+       lbtf_deb_enter(LBTF_DEB_MAIN);
+       eth_broadcast_addr(priv->current_addr);
+       mutex_init(&priv->lock);
+
+       priv->vif = NULL;
+       setup_timer(&priv->command_timer, command_timer_fn,
+               (unsigned long)priv);
+
+       INIT_LIST_HEAD(&priv->cmdfreeq);
+       INIT_LIST_HEAD(&priv->cmdpendingq);
+
+       spin_lock_init(&priv->driver_lock);
+
+       /* Allocate the command buffers */
+       if (lbtf_allocate_cmd_buffer(priv))
+               return -1;
+
+       lbtf_deb_leave(LBTF_DEB_MAIN);
+       return 0;
+}
+
+static void lbtf_free_adapter(struct lbtf_private *priv)
+{
+       lbtf_deb_enter(LBTF_DEB_MAIN);
+       lbtf_free_cmd_buffer(priv);
+       del_timer(&priv->command_timer);
+       lbtf_deb_leave(LBTF_DEB_MAIN);
+}
+
+static void lbtf_op_tx(struct ieee80211_hw *hw,
+                      struct ieee80211_tx_control *control,
+                      struct sk_buff *skb)
+{
+       struct lbtf_private *priv = hw->priv;
+
+       priv->skb_to_tx = skb;
+       queue_work(lbtf_wq, &priv->tx_work);
+       /*
+        * queue will be restarted when we receive transmission feedback if
+        * there are no buffered multicast frames to send
+        */
+       ieee80211_stop_queues(priv->hw);
+}
+
+static void lbtf_tx_work(struct work_struct *work)
+{
+       struct lbtf_private *priv = container_of(work, struct lbtf_private,
+                                        tx_work);
+       unsigned int len;
+       struct ieee80211_tx_info *info;
+       struct txpd *txpd;
+       struct sk_buff *skb = NULL;
+       int err;
+
+       lbtf_deb_enter(LBTF_DEB_MACOPS | LBTF_DEB_TX);
+
+       if ((priv->vif->type == NL80211_IFTYPE_AP) &&
+           (!skb_queue_empty(&priv->bc_ps_buf)))
+               skb = skb_dequeue(&priv->bc_ps_buf);
+       else if (priv->skb_to_tx) {
+               skb = priv->skb_to_tx;
+               priv->skb_to_tx = NULL;
+       } else {
+               lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
+               return;
+       }
+
+       len = skb->len;
+       info  = IEEE80211_SKB_CB(skb);
+       txpd = (struct txpd *)  skb_push(skb, sizeof(struct txpd));
+
+       if (priv->surpriseremoved) {
+               dev_kfree_skb_any(skb);
+               lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
+               return;
+       }
+
+       memset(txpd, 0, sizeof(struct txpd));
+       /* Activate per-packet rate selection */
+       txpd->tx_control |= cpu_to_le32(MRVL_PER_PACKET_RATE |
+                            ieee80211_get_tx_rate(priv->hw, info)->hw_value);
+
+       /* copy destination address from 802.11 header */
+       memcpy(txpd->tx_dest_addr_high, skb->data + sizeof(struct txpd) + 4,
+               ETH_ALEN);
+       txpd->tx_packet_length = cpu_to_le16(len);
+       txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
+       lbtf_deb_hex(LBTF_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
+       BUG_ON(priv->tx_skb);
+       spin_lock_irq(&priv->driver_lock);
+       priv->tx_skb = skb;
+       err = priv->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len);
+       spin_unlock_irq(&priv->driver_lock);
+       if (err) {
+               dev_kfree_skb_any(skb);
+               priv->tx_skb = NULL;
+               pr_err("TX error: %d", err);
+       }
+       lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
+}
+
+static int lbtf_op_start(struct ieee80211_hw *hw)
+{
+       struct lbtf_private *priv = hw->priv;
+       void *card = priv->card;
+       int ret = -1;
+
+       lbtf_deb_enter(LBTF_DEB_MACOPS);
+
+       if (!priv->fw_ready)
+               /* Upload firmware */
+               if (priv->hw_prog_firmware(card))
+                       goto err_prog_firmware;
+
+       /* poke the firmware */
+       priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
+       priv->radioon = RADIO_ON;
+       priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
+       ret = lbtf_setup_firmware(priv);
+       if (ret)
+               goto err_prog_firmware;
+
+       if ((priv->fwrelease < LBTF_FW_VER_MIN) ||
+           (priv->fwrelease > LBTF_FW_VER_MAX)) {
+               ret = -1;
+               goto err_prog_firmware;
+       }
+
+       printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
+       lbtf_deb_leave(LBTF_DEB_MACOPS);
+       return 0;
+
+err_prog_firmware:
+       priv->hw_reset_device(card);
+       lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret);
+       return ret;
+}
+
+static void lbtf_op_stop(struct ieee80211_hw *hw)
+{
+       struct lbtf_private *priv = hw->priv;
+       unsigned long flags;
+       struct sk_buff *skb;
+
+       struct cmd_ctrl_node *cmdnode;
+
+       lbtf_deb_enter(LBTF_DEB_MACOPS);
+
+       /* Flush pending command nodes */
+       spin_lock_irqsave(&priv->driver_lock, flags);
+       list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
+               cmdnode->result = -ENOENT;
+               cmdnode->cmdwaitqwoken = 1;
+               wake_up_interruptible(&cmdnode->cmdwait_q);
+       }
+
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+       cancel_work_sync(&priv->cmd_work);
+       cancel_work_sync(&priv->tx_work);
+       while ((skb = skb_dequeue(&priv->bc_ps_buf)))
+               dev_kfree_skb_any(skb);
+       priv->radioon = RADIO_OFF;
+       lbtf_set_radio_control(priv);
+
+       lbtf_deb_leave(LBTF_DEB_MACOPS);
+}
+
+static int lbtf_op_add_interface(struct ieee80211_hw *hw,
+                       struct ieee80211_vif *vif)
+{
+       struct lbtf_private *priv = hw->priv;
+       lbtf_deb_enter(LBTF_DEB_MACOPS);
+       if (priv->vif != NULL)
+               return -EOPNOTSUPP;
+
+       priv->vif = vif;
+       switch (vif->type) {
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_AP:
+               lbtf_set_mode(priv, LBTF_AP_MODE);
+               break;
+       case NL80211_IFTYPE_STATION:
+               lbtf_set_mode(priv, LBTF_STA_MODE);
+               break;
+       default:
+               priv->vif = NULL;
+               return -EOPNOTSUPP;
+       }
+       lbtf_set_mac_address(priv, (u8 *) vif->addr);
+       lbtf_deb_leave(LBTF_DEB_MACOPS);
+       return 0;
+}
+
+static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
+                       struct ieee80211_vif *vif)
+{
+       struct lbtf_private *priv = hw->priv;
+       lbtf_deb_enter(LBTF_DEB_MACOPS);
+
+       if (priv->vif->type == NL80211_IFTYPE_AP ||
+           priv->vif->type == NL80211_IFTYPE_MESH_POINT)
+               lbtf_beacon_ctrl(priv, 0, 0);
+       lbtf_set_mode(priv, LBTF_PASSIVE_MODE);
+       lbtf_set_bssid(priv, 0, NULL);
+       priv->vif = NULL;
+       lbtf_deb_leave(LBTF_DEB_MACOPS);
+}
+
+static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
+{
+       struct lbtf_private *priv = hw->priv;
+       struct ieee80211_conf *conf = &hw->conf;
+       lbtf_deb_enter(LBTF_DEB_MACOPS);
+
+       if (conf->chandef.chan->center_freq != priv->cur_freq) {
+               priv->cur_freq = conf->chandef.chan->center_freq;
+               lbtf_set_channel(priv, conf->chandef.chan->hw_value);
+       }
+       lbtf_deb_leave(LBTF_DEB_MACOPS);
+       return 0;
+}
+
+static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw,
+                                    struct netdev_hw_addr_list *mc_list)
+{
+       struct lbtf_private *priv = hw->priv;
+       int i;
+       struct netdev_hw_addr *ha;
+       int mc_count = netdev_hw_addr_list_count(mc_list);
+
+       if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE)
+               return mc_count;
+
+       priv->nr_of_multicastmacaddr = mc_count;
+       i = 0;
+       netdev_hw_addr_list_for_each(ha, mc_list)
+               memcpy(&priv->multicastlist[i++], ha->addr, ETH_ALEN);
+
+       return mc_count;
+}
+
+#define SUPPORTED_FIF_FLAGS  FIF_ALLMULTI
+static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
+                       unsigned int changed_flags,
+                       unsigned int *new_flags,
+                       u64 multicast)
+{
+       struct lbtf_private *priv = hw->priv;
+       int old_mac_control = priv->mac_control;
+
+       lbtf_deb_enter(LBTF_DEB_MACOPS);
+
+       changed_flags &= SUPPORTED_FIF_FLAGS;
+       *new_flags &= SUPPORTED_FIF_FLAGS;
+
+       if (!changed_flags) {
+               lbtf_deb_leave(LBTF_DEB_MACOPS);
+               return;
+       }
+
+       priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
+       if (*new_flags & (FIF_ALLMULTI) ||
+           multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
+               priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
+               priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE;
+       } else if (multicast) {
+               priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE;
+               priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
+               lbtf_cmd_set_mac_multicast_addr(priv);
+       } else {
+               priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE |
+                                      CMD_ACT_MAC_ALL_MULTICAST_ENABLE);
+               if (priv->nr_of_multicastmacaddr) {
+                       priv->nr_of_multicastmacaddr = 0;
+                       lbtf_cmd_set_mac_multicast_addr(priv);
+               }
+       }
+
+
+       if (priv->mac_control != old_mac_control)
+               lbtf_set_mac_control(priv);
+
+       lbtf_deb_leave(LBTF_DEB_MACOPS);
+}
+
+static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
+                       struct ieee80211_vif *vif,
+                       struct ieee80211_bss_conf *bss_conf,
+                       u32 changes)
+{
+       struct lbtf_private *priv = hw->priv;
+       struct sk_buff *beacon;
+       lbtf_deb_enter(LBTF_DEB_MACOPS);
+
+       if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) {
+               switch (priv->vif->type) {
+               case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_MESH_POINT:
+                       beacon = ieee80211_beacon_get(hw, vif);
+                       if (beacon) {
+                               lbtf_beacon_set(priv, beacon);
+                               kfree_skb(beacon);
+                               lbtf_beacon_ctrl(priv, 1,
+                                                bss_conf->beacon_int);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (changes & BSS_CHANGED_BSSID) {
+               bool activate = !is_zero_ether_addr(bss_conf->bssid);
+               lbtf_set_bssid(priv, activate, bss_conf->bssid);
+       }
+
+       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+               if (bss_conf->use_short_preamble)
+                       priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
+               else
+                       priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+               lbtf_set_radio_control(priv);
+       }
+
+       lbtf_deb_leave(LBTF_DEB_MACOPS);
+}
+
+static int lbtf_op_get_survey(struct ieee80211_hw *hw, int idx,
+                               struct survey_info *survey)
+{
+       struct lbtf_private *priv = hw->priv;
+       struct ieee80211_conf *conf = &hw->conf;
+
+       if (idx != 0)
+               return -ENOENT;
+
+       survey->channel = conf->chandef.chan;
+       survey->filled = SURVEY_INFO_NOISE_DBM;
+       survey->noise = priv->noise;
+
+       return 0;
+}
+
+static const struct ieee80211_ops lbtf_ops = {
+       .tx                     = lbtf_op_tx,
+       .start                  = lbtf_op_start,
+       .stop                   = lbtf_op_stop,
+       .add_interface          = lbtf_op_add_interface,
+       .remove_interface       = lbtf_op_remove_interface,
+       .config                 = lbtf_op_config,
+       .prepare_multicast      = lbtf_op_prepare_multicast,
+       .configure_filter       = lbtf_op_configure_filter,
+       .bss_info_changed       = lbtf_op_bss_info_changed,
+       .get_survey             = lbtf_op_get_survey,
+};
+
+int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
+{
+       struct ieee80211_rx_status stats;
+       struct rxpd *prxpd;
+       int need_padding;
+       unsigned int flags;
+       struct ieee80211_hdr *hdr;
+
+       lbtf_deb_enter(LBTF_DEB_RX);
+
+       prxpd = (struct rxpd *) skb->data;
+
+       memset(&stats, 0, sizeof(stats));
+       if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
+               stats.flag |= RX_FLAG_FAILED_FCS_CRC;
+       stats.freq = priv->cur_freq;
+       stats.band = IEEE80211_BAND_2GHZ;
+       stats.signal = prxpd->snr;
+       priv->noise = prxpd->nf;
+       /* Marvell rate index has a hole at value 4 */
+       if (prxpd->rx_rate > 4)
+               --prxpd->rx_rate;
+       stats.rate_idx = prxpd->rx_rate;
+       skb_pull(skb, sizeof(struct rxpd));
+
+       hdr = (struct ieee80211_hdr *)skb->data;
+       flags = le32_to_cpu(*(__le32 *)(skb->data + 4));
+
+       need_padding = ieee80211_is_data_qos(hdr->frame_control);
+       need_padding ^= ieee80211_has_a4(hdr->frame_control);
+       need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
+                       (*ieee80211_get_qos_ctl(hdr) &
+                        IEEE80211_QOS_CTL_A_MSDU_PRESENT);
+
+       if (need_padding) {
+               memmove(skb->data + 2, skb->data, skb->len);
+               skb_reserve(skb, 2);
+       }
+
+       memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
+
+       lbtf_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
+              skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
+       lbtf_deb_hex(LBTF_DEB_RX, "RX Data", skb->data,
+                    min_t(unsigned int, skb->len, 100));
+
+       ieee80211_rx_irqsafe(priv->hw, skb);
+
+       lbtf_deb_leave(LBTF_DEB_RX);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lbtf_rx);
+
+/**
+ * lbtf_add_card: Add and initialize the card, no fw upload yet.
+ *
+ *  @card    A pointer to card
+ *
+ *  Returns: pointer to struct lbtf_priv.
+ */
+struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
+{
+       struct ieee80211_hw *hw;
+       struct lbtf_private *priv = NULL;
+
+       lbtf_deb_enter(LBTF_DEB_MAIN);
+
+       hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops);
+       if (!hw)
+               goto done;
+
+       priv = hw->priv;
+       if (lbtf_init_adapter(priv))
+               goto err_init_adapter;
+
+       priv->hw = hw;
+       priv->card = card;
+       priv->tx_skb = NULL;
+
+       hw->queues = 1;
+       ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
+       hw->extra_tx_headroom = sizeof(struct txpd);
+       memcpy(priv->channels, lbtf_channels, sizeof(lbtf_channels));
+       memcpy(priv->rates, lbtf_rates, sizeof(lbtf_rates));
+       priv->band.n_bitrates = ARRAY_SIZE(lbtf_rates);
+       priv->band.bitrates = priv->rates;
+       priv->band.n_channels = ARRAY_SIZE(lbtf_channels);
+       priv->band.channels = priv->channels;
+       hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+       hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_STATION) |
+               BIT(NL80211_IFTYPE_ADHOC);
+       skb_queue_head_init(&priv->bc_ps_buf);
+
+       SET_IEEE80211_DEV(hw, dmdev);
+
+       INIT_WORK(&priv->cmd_work, lbtf_cmd_work);
+       INIT_WORK(&priv->tx_work, lbtf_tx_work);
+       if (ieee80211_register_hw(hw))
+               goto err_init_adapter;
+
+       goto done;
+
+err_init_adapter:
+       lbtf_free_adapter(priv);
+       ieee80211_free_hw(hw);
+       priv = NULL;
+
+done:
+       lbtf_deb_leave_args(LBTF_DEB_MAIN, "priv %p", priv);
+       return priv;
+}
+EXPORT_SYMBOL_GPL(lbtf_add_card);
+
+
+int lbtf_remove_card(struct lbtf_private *priv)
+{
+       struct ieee80211_hw *hw = priv->hw;
+
+       lbtf_deb_enter(LBTF_DEB_MAIN);
+
+       priv->surpriseremoved = 1;
+       del_timer(&priv->command_timer);
+       lbtf_free_adapter(priv);
+       priv->hw = NULL;
+       ieee80211_unregister_hw(hw);
+       ieee80211_free_hw(hw);
+
+    lbtf_deb_leave(LBTF_DEB_MAIN);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lbtf_remove_card);
+
+void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb);
+
+       ieee80211_tx_info_clear_status(info);
+       /*
+        * Commented out, otherwise we never go beyond 1Mbit/s using mac80211
+        * default pid rc algorithm.
+        *
+        * info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt;
+        */
+       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail)
+               info->flags |= IEEE80211_TX_STAT_ACK;
+       skb_pull(priv->tx_skb, sizeof(struct txpd));
+       ieee80211_tx_status_irqsafe(priv->hw, priv->tx_skb);
+       priv->tx_skb = NULL;
+       if (!priv->skb_to_tx && skb_queue_empty(&priv->bc_ps_buf))
+               ieee80211_wake_queues(priv->hw);
+       else
+               queue_work(lbtf_wq, &priv->tx_work);
+}
+EXPORT_SYMBOL_GPL(lbtf_send_tx_feedback);
+
+void lbtf_bcn_sent(struct lbtf_private *priv)
+{
+       struct sk_buff *skb = NULL;
+
+       if (priv->vif->type != NL80211_IFTYPE_AP)
+               return;
+
+       if (skb_queue_empty(&priv->bc_ps_buf)) {
+               bool tx_buff_bc = false;
+
+               while ((skb = ieee80211_get_buffered_bc(priv->hw, priv->vif))) {
+                       skb_queue_tail(&priv->bc_ps_buf, skb);
+                       tx_buff_bc = true;
+               }
+               if (tx_buff_bc) {
+                       ieee80211_stop_queues(priv->hw);
+                       queue_work(lbtf_wq, &priv->tx_work);
+               }
+       }
+
+       skb = ieee80211_beacon_get(priv->hw, priv->vif);
+
+       if (skb) {
+               lbtf_beacon_set(priv, skb);
+               kfree_skb(skb);
+       }
+}
+EXPORT_SYMBOL_GPL(lbtf_bcn_sent);
+
+static int __init lbtf_init_module(void)
+{
+       lbtf_deb_enter(LBTF_DEB_MAIN);
+       lbtf_wq = create_workqueue("libertastf");
+       if (lbtf_wq == NULL) {
+               printk(KERN_ERR "libertastf: couldn't create workqueue\n");
+               return -ENOMEM;
+       }
+       lbtf_deb_leave(LBTF_DEB_MAIN);
+       return 0;
+}
+
+static void __exit lbtf_exit_module(void)
+{
+       lbtf_deb_enter(LBTF_DEB_MAIN);
+       destroy_workqueue(lbtf_wq);
+       lbtf_deb_leave(LBTF_DEB_MAIN);
+}
+
+module_init(lbtf_init_module);
+module_exit(lbtf_exit_module);
+
+MODULE_DESCRIPTION("Libertas WLAN Thinfirm Driver Library");
+MODULE_AUTHOR("Cozybit Inc.");
+MODULE_LICENSE("GPL");