[PATCH] Libertas 5.110.5 -> 5.110.7 upgrade

Marcelo Tosatti marcelo at kvack.org
Tue Jun 6 17:13:26 EDT 2006


So, here they are, the changes from Marvell relative to the GIT tree.

Next step is to get rid of the thread buffering commands from the net
driver API to the hardware. This is a pretty large task (since most of
the driver is structured based on it), but will greatly simplify the
driver getting rid of a _large_ amount of deadly bugs.

-------------------------------------

Merge Libertas 5.110.7 changes.

- You can configure forwarding tables

- You can configure blinding nodes

- You can use the standalone USB 8388 device (i.e. not using click
router) and put it in power save mode while associated to an AP or
joined to an adhoc network.

Signed-off-by: Marcelo Tosatti <marcelo at kvack.org>

diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index b253305..164f8f3 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -187,7 +187,8 @@ #define HostCmd_CMD_GET_TSF             
 
 
 
-
+#define HostCmd_CMD_DFT_ACCESS                   0x0087
+#define HostCmd_RET_DFT_ACCESS                   0x8087
 
 /* For the IEEE Power Save */
 #define HostCmd_SubCmd_Enter_PS               0x0030
@@ -451,6 +452,18 @@ #define HostCmd_TYPE_CAM                
 #define HostCmd_TYPE_MAX_PSP                    0x0001
 #define HostCmd_TYPE_FAST_PSP                   0x0002
 
+/* Define action or option for HostCmd_CMD_DFT_ACCESS */
+enum HostCmd_CMD_DFT_ACCESS_OPTS {
+	HostCmd_ACT_DFT_ACCESS_ADD = 1,
+	HostCmd_ACT_DFT_ACCESS_DEL,
+	HostCmd_ACT_DFT_ACCESS_LIST,
+	HostCmd_ACT_DFT_ACCESS_RESET,
+	HostCmd_ACT_BT_ACCESS_ADD,
+	HostCmd_ACT_BT_ACCESS_DEL,
+	HostCmd_ACT_BT_ACCESS_LIST,
+	HostCmd_ACT_BT_ACCESS_RESET 
+};
+
 /** Card Event definition */
 #define MACREG_INT_CODE_TX_PPA_FREE             0x00000000
 #define MACREG_INT_CODE_TX_DMA_DONE             0x00000001
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index b89697e..2e79e11 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -883,6 +883,15 @@ struct HostCmd_DS_GET_TSF {
 	u64 TsfValue;
 } __attribute__ ((packed));
 
+/** HostCmd_CMD_DFT_ACCESS */
+struct HostCmd_DS_DFT_ACCESS
+{
+	u16	Action;
+	u32	id;
+	u8	addr1[ETH_ALEN];
+	u8	addr2[ETH_ALEN];
+} __attribute__ ((packed));
+
 /* HostCmd_DS_COMMAND*/
 struct HostCmd_DS_COMMAND {
 	/* Command Header */
@@ -944,6 +953,7 @@ struct HostCmd_DS_COMMAND {
 		struct HostCmd_DS_802_11_LED_CTRL ledgpio;
 
 		struct HostCmd_TX_RATE_QUERY txrate;
+		struct HostCmd_DS_DFT_ACCESS dft;
 		struct HostCmd_DS_GET_TSF gettsf;
 	} params;
 } __attribute__ ((packed));
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 80c03f9..6b61be4 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -74,6 +74,8 @@ static void if_usb_receive(struct urb *u
 static int if_usb_probe(struct usb_interface *intf,  
 			const struct usb_device_id *id);
 static void if_usb_disconnect(struct usb_interface *intf);
+static int if_usb_suspend(struct usb_interface *intf, pm_message_t message);
+static int if_usb_resume(struct usb_interface *intf);
 
 /** if_usb_driver */
 static struct usb_driver if_usb_driver = {
@@ -89,6 +91,9 @@ static struct usb_driver if_usb_driver =
 		/* device signature table */
 	.id_table = if_usb_table,
 
+	.suspend = if_usb_suspend,
+  
+	.resume = if_usb_resume,
 };
 
 MODULE_DEVICE_TABLE(usb, if_usb_table);
@@ -142,9 +147,11 @@ static void if_usb_write_bulk_callback(s
 		PRINTM(INFO, "Actual length transmitted %d\n", urb->actual_length);
 		priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
 	}
+
 	if (!cardp->IsFWDnld) {
 		usb_int_cause |= HIS_TxDnLdRdy;
-		if_usb_interrupt(priv, HIS_TxDnLdRdy, TX_SUCCESS);
+		if (priv->adapter->PSState != PS_STATE_SLEEP)
+			if_usb_interrupt(priv, HIS_TxDnLdRdy, TX_SUCCESS);
 	}
 
 tx_exit:		
@@ -1010,4 +1017,36 @@ inline int sbi_resume(wlan_private * pri
 }
 #endif
 
+static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usb_card_rec	*cardp = usb_get_intfdata(intf);
+	wlan_private	*priv = cardp->priv;
+
+	ENTER();
+
+	if (priv->adapter->PSState != PS_STATE_FULL_POWER)
+		return -1;
+	netif_device_detach(cardp->eth_dev); 	
+
+	cardp->rx_urb_recall = TRUE;
+
+	LEAVE();
+	return 0;	
+}
 
+static int if_usb_resume(struct usb_interface *intf)
+{
+	struct usb_card_rec	*cardp = usb_get_intfdata(intf);
+
+	ENTER();
+
+	cardp->rx_urb_recall = FALSE;
+	if (!cardp->rx_urb_pending) {
+		if_usb_submit_rx_urb(cardp->priv);
+	}
+
+	netif_device_attach(cardp->eth_dev);
+    
+	LEAVE();
+	return 0;	
+}
diff --git a/drivers/net/wireless/libertas/include.h b/drivers/net/wireless/libertas/include.h
index c4b4d2a..bdc52b4 100644
--- a/drivers/net/wireless/libertas/include.h
+++ b/drivers/net/wireless/libertas/include.h
@@ -35,6 +35,8 @@ #define _INCLUDE_H_
 #include    "os_headers.h"
 #include    "wlan_defs.h"
 #include    "wlan_thread.h"
+#include    "radiotap.h"
+#include    <linux/kernel.h>
 #include    "wlan_types.h"
 
 #include    "wlan_11d.h"
@@ -55,5 +57,4 @@ #include    "sbi.h"
 #include    "wlan_fw.h"
 #include    "wlan_wext.h"
 #include    "wlan_decl.h"
-#include    "radiotap.h"
 #endif /* _INCLUDE_H_ */
diff --git a/drivers/net/wireless/libertas/radiotap.h b/drivers/net/wireless/libertas/radiotap.h
index 19b115e..6fd796a 100644
--- a/drivers/net/wireless/libertas/radiotap.h
+++ b/drivers/net/wireless/libertas/radiotap.h
@@ -226,5 +226,68 @@ #define	IEEE80211_RADIOTAP_F_TX_FAIL	0x0
 #define	IEEE80211_RADIOTAP_F_TX_CTS	0x0002	/* used cts 'protection' */
 #define	IEEE80211_RADIOTAP_F_TX_RTS	0x0004	/* used rts/cts handshake */
 
+struct IEEE80211_Hdr
+{
+    u16  FrameControl;
+    u16  DurationID;
+    u8  address1[6];
+    u8  address2[6];
+    u8  address3[6];
+    u16  SeqControl;
+    u8  address4[6];
+} __attribute__ ((packed));
+
+struct TxRadiotapHdr
+{
+    struct ieee80211_radiotap_header hdr;
+    u8           rate;
+    u8           txpower;
+    u8           rts_retries;
+    u8           data_retries;
+    //u8           pad[IEEE80211_RADIOTAP_HDRLEN - 12];
+} __attribute__ ((packed));
+
+#define TX_RADIOTAP_PRESENT (   \
+		(1 << IEEE80211_RADIOTAP_RATE)    | \
+		(1 << IEEE80211_RADIOTAP_DBM_TX_POWER)  | \
+		(1 << IEEE80211_RADIOTAP_RTS_RETRIES) | \
+		(1 << IEEE80211_RADIOTAP_DATA_RETRIES)  | \
+		0)
+
+#define IEEE80211_FC_VERSION_MASK    0x0003
+#define IEEE80211_FC_TYPE_MASK       0x000c
+#define IEEE80211_FC_TYPE_MGT        0x0000
+#define IEEE80211_FC_TYPE_CTL        0x0004
+#define IEEE80211_FC_TYPE_DATA       0x0008
+#define IEEE80211_FC_SUBTYPE_MASK    0x00f0
+#define IEEE80211_FC_TOFROMDS_MASK   0x0300
+#define IEEE80211_FC_TODS_MASK       0x0100
+#define IEEE80211_FC_FROMDS_MASK     0x0200
+#define IEEE80211_FC_NODS            0x0000
+#define IEEE80211_FC_TODS            0x0100
+#define IEEE80211_FC_FROMDS          0x0200
+#define IEEE80211_FC_DSTODS          0x0300
+
+struct RxRadiotapHdr
+{
+    struct ieee80211_radiotap_header hdr;
+    u8           flags;
+    u8           rate;
+    u16          chan_freq;
+    u16          chan_flags;
+    u8           antenna;
+    u8           antsignal;
+    u16          rx_flags;
+    //u8           pad[IEEE80211_RADIOTAP_HDRLEN - 18];
+} __attribute__ ((packed));
+
+#define RX_RADIOTAP_PRESENT (   \
+		(1 << IEEE80211_RADIOTAP_FLAGS)   | \
+		(1 << IEEE80211_RADIOTAP_RATE)    | \
+		(1 << IEEE80211_RADIOTAP_CHANNEL) | \
+		(1 << IEEE80211_RADIOTAP_ANTENNA) | \
+		(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)  | \
+		(1 << IEEE80211_RADIOTAP_RX_FLAGS)  | \
+		0)
 
 #endif /* _NET_IF_IEEE80211RADIOTAP_H_ */
diff --git a/drivers/net/wireless/libertas/wlan_11d.c b/drivers/net/wireless/libertas/wlan_11d.c
index 41a0a11..236d6d0 100644
--- a/drivers/net/wireless/libertas/wlan_11d.c
+++ b/drivers/net/wireless/libertas/wlan_11d.c
@@ -422,8 +422,9 @@ int wlan_parse_domain_info_11d(
 		parsed_region_chan_11d_t * parsed_region_chan ) 
 {
 	u8 	NoOfSubband, NoOfChan;
-	u8 	lastChan, firstChan, curChan;
+	u8 	lastChan, firstChan;
 	u8	region;
+	u8	curChan = 0;
 
 	u8 	idx =0;		/*chan index in parsed_region_chan*/
 	
diff --git a/drivers/net/wireless/libertas/wlan_cmd.c b/drivers/net/wireless/libertas/wlan_cmd.c
index b05ce0d..24b1d37 100644
--- a/drivers/net/wireless/libertas/wlan_cmd.c
+++ b/drivers/net/wireless/libertas/wlan_cmd.c
@@ -1067,6 +1067,68 @@ static int wlan_cmd_802_11_eeprom_access
 
 
 
+/** 
+ *  @brief This function prepares command of DFT access.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: ADD, DEL, RESET, or LIST
+ *  @param pdata_buf	A pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_dft_access(wlan_private * priv,
+			   struct HostCmd_DS_COMMAND * cmd,
+			   u16 cmd_action,
+			   void *pdata_buf)
+{
+	struct HostCmd_DS_DFT_ACCESS *dft_access = &cmd->params.dft;
+	PRINTM(INFO, "DFT CMD(%d)\n", cmd_action);
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_DFT_ACCESS);
+	cmd->Size = wlan_cpu_to_le16(sizeof(struct HostCmd_DS_DFT_ACCESS)
+                                 + S_DS_GEN);
+	cmd->Result 	= 0;
+	dft_access->Action = wlan_cpu_to_le16(cmd_action);
+
+	switch (cmd_action) {
+		case HostCmd_ACT_DFT_ACCESS_ADD:
+			memcpy(dft_access->addr1, pdata_buf, 2*ETH_ALEN);
+			HEXDUMP("DFT_ADD: index mac address-", 
+				dft_access->addr1, 6);
+			HEXDUMP("DFT_ADD: yield mac address-", 
+				dft_access->addr2, 6);
+			break;
+		case HostCmd_ACT_DFT_ACCESS_DEL:
+			memcpy(dft_access->addr1, pdata_buf, 1*ETH_ALEN);
+			HEXDUMP("DFT_DEL: index mac address-", 
+				dft_access->addr1, 6);
+			break;
+		case HostCmd_ACT_DFT_ACCESS_LIST:
+			dft_access->id = wlan_cpu_to_le32(*(u32 *)pdata_buf);
+			break;
+		case HostCmd_ACT_DFT_ACCESS_RESET:
+			break;
+		case HostCmd_ACT_BT_ACCESS_ADD:
+			memcpy(dft_access->addr1, pdata_buf, 2*ETH_ALEN);
+			HEXDUMP("BT_ADD: blinded mac address-", 
+				dft_access->addr1, 6);
+			break;
+		case HostCmd_ACT_BT_ACCESS_DEL:
+			memcpy(dft_access->addr1, pdata_buf, 1*ETH_ALEN);
+			HEXDUMP("BT_DEL: blinded mac address-", 
+				dft_access->addr1, 6);
+			break;
+		case HostCmd_ACT_BT_ACCESS_LIST:
+			dft_access->id = wlan_cpu_to_le32(*(u32 *)pdata_buf);
+			break;
+		case HostCmd_ACT_BT_ACCESS_RESET:
+			break;
+		default:
+			break;
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
 
 /** 
  *  @brief This function queues the command to cmd list.
@@ -1611,6 +1673,10 @@ #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS
 							cmd_action, pdata_buf);
 			break;
 
+		case HostCmd_CMD_DFT_ACCESS:
+			ret = wlan_cmd_dft_access(priv, CmdPtr,
+					cmd_action, pdata_buf);
+			break;
 
 		case HostCmd_CMD_GET_TSF:
             CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_GET_TSF);
diff --git a/drivers/net/wireless/libertas/wlan_cmdresp.c b/drivers/net/wireless/libertas/wlan_cmdresp.c
index b68e158..94711ac 100644
--- a/drivers/net/wireless/libertas/wlan_cmdresp.c
+++ b/drivers/net/wireless/libertas/wlan_cmdresp.c
@@ -33,6 +33,7 @@ Change log:
 	04/10/06: Add hostcmd generic API
 	04/18/06: Remove old Subscrive Event and add new Subscribe Event
 		  implementation through generic hostcmd API
+	05/08/06: Remove Adapter->PermanentAddr memcpy
 ********************************************************/
 
 #include	"include.h"
@@ -281,15 +282,6 @@ static int wlan_ret_get_hw_spec(wlan_pri
 	Adapter->fwCapInfo = wlan_le32_to_cpu(hwspec->fwCapInfo);
 
 
-	/* permanent address should only be set once at start up */
-	if (Adapter->PermanentAddr[0] == 0xff) {
-		/* permanent address has not been set yet, set it */
-		memcpy(Adapter->PermanentAddr, hwspec->PermanentAddr,
-							MRVDRV_ETH_ADDR_LEN);
-	}
-
-	memcpy(priv->wlan_dev.netdev->dev_addr, hwspec->PermanentAddr,
-								ETH_ALEN);
 	Adapter->FWReleaseNumber = hwspec->FWReleaseNumber;
 
 	PRINTM(INFO, "GET_HW_SPEC: FWReleaseVersion- 0x%X\n", Adapter->FWReleaseNumber);
@@ -321,6 +313,7 @@ static int wlan_ret_get_hw_spec(wlan_pri
 		memmove(Adapter->CurrentAddr, hwspec->PermanentAddr,
 				MRVDRV_ETH_ADDR_LEN);
 	}
+	memcpy(priv->wlan_dev.netdev->dev_addr, Adapter->CurrentAddr, ETH_ALEN);
 
 	if (wlan_set_regiontable(priv, Adapter->RegionCode, 0)) {
 			ret = WLAN_STATUS_FAILURE;
@@ -1100,6 +1093,11 @@ int wlan_process_rx_command(wlan_private
                &resp->params.gettsf.TsfValue,
                sizeof(u64));
 	    break;
+	case HostCmd_RET_DFT_ACCESS:
+	    if (Adapter->CurCmd->pdata_buf) 
+		    memcpy(Adapter->CurCmd->pdata_buf, &resp->params.dft.addr1, 
+                   	   2*ETH_ALEN);
+	    break;
 	case  HostCmd_RTE_802_11_TX_RATE_QUERY:
 	    priv->adapter->TxRate = resp->params.txrate.TxRate;
 	    break;
diff --git a/drivers/net/wireless/libertas/wlan_defs.h b/drivers/net/wireless/libertas/wlan_defs.h
index 2b4c5ed..0c1eb7e 100644
--- a/drivers/net/wireless/libertas/wlan_defs.h
+++ b/drivers/net/wireless/libertas/wlan_defs.h
@@ -223,7 +223,6 @@ #define MRVDRV_DEFAULT_MULTIPLE_DTIM		1
 
 #define MRVDRV_DEFAULT_LISTEN_INTERVAL		10
 #define MRVDRV_DEFAULT_LOCAL_LISTEN_INTERVAL		0
-#define MRVDRV_MAX_TX_POWER		      	15
 
 #define	MRVDRV_CHANNELS_PER_SCAN		4
 #define	MRVDRV_MAX_CHANNELS_PER_SCAN		14
@@ -287,7 +286,7 @@ #define MRVL_FIXED_IE_SIZE      12
 
 /* This is for firmware specific length */
 #define EXTRA_LEN	36 
-#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE	1550
+#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE	1514
 
 #define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
 	(MRVDRV_MAXIMUM_ETH_PACKET_SIZE + sizeof(struct TxPD) + EXTRA_LEN)
diff --git a/drivers/net/wireless/libertas/wlan_dev.h b/drivers/net/wireless/libertas/wlan_dev.h
index a7afce9..0f8d124 100644
--- a/drivers/net/wireless/libertas/wlan_dev.h
+++ b/drivers/net/wireless/libertas/wlan_dev.h
@@ -26,6 +26,7 @@ Change log:
 	01/11/06: Conditionalize new scan/join structures.
 	04/18/06: Remove old Subscrive Event and add new Subscribe Event
 		  implementation through generic hostcmd API
+	05/08/06: Remove PermanentAddr from Adapter
 
  ************************************************************/
 
@@ -266,7 +267,6 @@ #endif /* REASSOCIATION */
 	u8			ATIMEnabled;
 
 	/** MAC address information */
-	u8 			PermanentAddr[MRVDRV_ETH_ADDR_LEN];
 	u8 			CurrentAddr[MRVDRV_ETH_ADDR_LEN];
 	u8 			MulticastList[MRVDRV_MAX_MULTICAST_LIST_SIZE]
 						[MRVDRV_ETH_ADDR_LEN];
diff --git a/drivers/net/wireless/libertas/wlan_fw.c b/drivers/net/wireless/libertas/wlan_fw.c
index da872b9..53e4794 100644
--- a/drivers/net/wireless/libertas/wlan_fw.c
+++ b/drivers/net/wireless/libertas/wlan_fw.c
@@ -25,6 +25,7 @@ Change log:
 	01/11/06: Conditionalize new scan/join functions.
 	          Cleanup association response handler initialization.
 	01/06/05: Add FW file read
+	05/08/06: Remove the 2nd GET_HW_SPEC command and TempAddr/PermanentAddr
 
 ********************************************************/
 
@@ -68,17 +69,16 @@ static int wlan_setup_station_hw(wlan_pr
 {
 	int 		ret = WLAN_STATUS_SUCCESS;
 	wlan_adapter   *adapter = priv->adapter;
-	u16		dbm = MRVDRV_MAX_TX_POWER;
- 	u8           TempAddr[MRVDRV_ETH_ADDR_LEN];
-	
 
     	ENTER();
     
 	sbi_disable_host_int(priv);
 
 
-	if ((ret=request_firmware(&priv->firmware, fw_name, priv->hotplug_device)) < 0) {
-		PRINTM(FATAL, "request_firmware() failed, error code = %#x\n", ret);
+	if ((ret=request_firmware(&priv->firmware, fw_name,
+					priv->hotplug_device)) < 0) {
+		PRINTM(MSG, "request_firmware() failed, error code = %#x\n", ret);
+		PRINTM(MSG, "%s not found in /lib/firmware\n", fw_name);
 		goto done;
 	}
 
@@ -108,16 +108,8 @@ #define RF_REG_VALUE  0xc8
 
 	/*
 	 * Read MAC address from HW
-	 * permanent address is not read first before it gets set if
-	 * NetworkAddress entry exists in the registry, so need to read it
-	 * first
-	 * 
-	 * use permanentaddr as temp variable to store currentaddr if
-	 * NetworkAddress entry exists
 	 */
-	memmove(TempAddr, adapter->CurrentAddr, MRVDRV_ETH_ADDR_LEN);
 	memset(adapter->CurrentAddr, 0xff, MRVDRV_ETH_ADDR_LEN);
-	memset(adapter->PermanentAddr, 0xff, MRVDRV_ETH_ADDR_LEN);
 
 	ret = PrepareAndSendCommand(priv, HostCmd_CMD_GET_HW_SPEC, 
 			0, HostCmd_OPTION_WAITFORRSP,
@@ -128,38 +120,9 @@ #define RF_REG_VALUE  0xc8
 		goto done;
 	}
 
-	if (TempAddr[0] != 0xff) {
-		/*
-		 * an address was read, so need to send GET_HW_SPEC again to
-		 * set the soft mac
-		 */
-
-		memmove(adapter->CurrentAddr, TempAddr, MRVDRV_ETH_ADDR_LEN);
-
-		ret = PrepareAndSendCommand(priv, HostCmd_CMD_GET_HW_SPEC,
-			0, HostCmd_OPTION_WAITFORRSP,
-			0, NULL);
-
-		if (ret) {
-			ret = WLAN_STATUS_FAILURE;
-			goto done;
-		}
-	}
-
 	SetMacPacketFilter(priv);
 
 
-	/* set the max tx power */
-	ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RF_TX_POWER,
-		HostCmd_ACT_TX_POWER_OPT_SET_LOW,
-		HostCmd_OPTION_WAITFORRSP, 0,
-		&dbm);
-
-	if (ret) {
-		ret = WLAN_STATUS_FAILURE;
-		goto done;
-	}
-
 
 	/* Get the supported Data Rates */
 	ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_DATA_RATE,
@@ -344,9 +307,6 @@ #define SHORT_PREAMBLE_ALLOWED		1
 
 	Adapter->EncryptionStatus = Wlan802_11WEPDisabled;
 
-	priv->adapter->linkmode = WLAN_LINKMODE_802_11;
-	priv->adapter->radiomode = WLAN_RADIOMODE_RADIOTAP;
-	
 	spin_lock_init(&Adapter->CurrentTxLock);
 
 	Adapter->CurrentTxSkb = NULL;
diff --git a/drivers/net/wireless/libertas/wlan_join.c b/drivers/net/wireless/libertas/wlan_join.c
index 02feb05..f20c8b8 100644
--- a/drivers/net/wireless/libertas/wlan_join.c
+++ b/drivers/net/wireless/libertas/wlan_join.c
@@ -1564,6 +1564,7 @@ int wlan_reassociation_thread(void *data
 
         OS_SET_THREAD_STATE(TASK_RUNNING);
         remove_wait_queue(&thread->waitQ, &wait);
+        try_to_freeze();
 
         if (Adapter->SurpriseRemoved) {
             break;
diff --git a/drivers/net/wireless/libertas/wlan_main.c b/drivers/net/wireless/libertas/wlan_main.c
index fbf7c56..97e0466 100644
--- a/drivers/net/wireless/libertas/wlan_main.c
+++ b/drivers/net/wireless/libertas/wlan_main.c
@@ -254,13 +254,11 @@ static int wlan_open(struct net_device *
 		}
 	}
 	
-	memcpy(dev->dev_addr, adapter->PermanentAddr, ETH_ALEN);
-	
 	MODULE_GET;
 
 	priv->open = TRUE;
 
-	if (priv->adapter->MediaConnectStatus == WlanMediaStateConnected)
+	if (adapter->MediaConnectStatus == WlanMediaStateConnected)
 		os_carrier_on(priv);
 	else
 		os_carrier_off(priv);
@@ -695,6 +693,7 @@ static int wlan_service_main_thread(void
 
 		OS_SET_THREAD_STATE(TASK_RUNNING);
 		remove_wait_queue(&thread->waitQ, &wait);
+		try_to_freeze();
 
 		PRINTM(INFO, "main-thread 333: IntCounter=%d CurrentTxSkb=%p "
 				"dnld_sent=%d\n",
@@ -868,7 +867,6 @@ static wlan_private *wlan_add_card(void 
 
 #define	WLAN_WATCHDOG_TIMEOUT	(2 * HZ)
 
-	dev->mtu = MRVDRV_MAXIMUM_ETH_PACKET_SIZE;	
 	dev->tx_timeout = wlan_tx_timeout;
 	dev->get_stats = wlan_get_stats;
 	dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT;
diff --git a/drivers/net/wireless/libertas/wlan_rx.c b/drivers/net/wireless/libertas/wlan_rx.c
index 9878c7e..5238c0d 100644
--- a/drivers/net/wireless/libertas/wlan_rx.c
+++ b/drivers/net/wireless/libertas/wlan_rx.c
@@ -59,41 +59,11 @@ typedef struct
 
 typedef struct
 {
-    u8  dest_addr[6];
-    u8  src_addr[6];
-    u16 ethertype;
-
-} __attribute__ ((packed)) EthII_Hdr_t; 
-
-typedef struct
-{
     struct RxPD         rx_pd;
     void*        eth80211_hdr;
 
 } __attribute__ ((packed)) Rx80211PacketHdr_t;
 
-typedef struct
-{
-    struct ieee80211_radiotap_header hdr;
-    u8           flags;
-    u8           rate;
-    u16          chan_freq;
-    u16          chan_flags;
-    u8           antenna;
-    u8           antsignal;
-    u16          rx_flags;
-    //u8           pad[IEEE80211_RADIOTAP_HDRLEN - 18];
-} __attribute__ ((packed)) RxRadiotapHdr_t;
-
-#define RX_RADIOTAP_PRESENT (   \
-		(1 << IEEE80211_RADIOTAP_FLAGS)   | \
-		(1 << IEEE80211_RADIOTAP_RATE)    | \
-		(1 << IEEE80211_RADIOTAP_CHANNEL) | \
-		(1 << IEEE80211_RADIOTAP_ANTENNA) | \
-		(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)  | \
-		(1 << IEEE80211_RADIOTAP_RX_FLAGS)  | \
-		0)
-
 /********************************************************
 		Global Variables
 ********************************************************/
@@ -224,7 +194,7 @@ int ProcessRxedPacket(wlan_private *priv
 	struct RxPD*   pRxPD;
 
 	int            hdrChop;
-	EthII_Hdr_t*   pEthHdr;
+	struct EthII_Hdr*   pEthHdr;
 
 	
 	const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
@@ -282,7 +252,7 @@ int ProcessRxedPacket(wlan_private *priv
          *  To create the Ethernet II, just move the src, dst address right
          *    before the snap_type.
          */
-        pEthHdr = (EthII_Hdr_t*)
+        pEthHdr = (struct EthII_Hdr*)
             ((u8*)&pRxPkt->eth803_hdr
              + sizeof(pRxPkt->eth803_hdr) + sizeof(pRxPkt->rfc1042_hdr)
              - sizeof(pRxPkt->eth803_hdr.dest_addr)
@@ -379,8 +349,8 @@ int ProcessRxed_802_11_Packet(wlan_priva
 
 	Rx80211PacketHdr_t* pRxPkt;
 	struct RxPD*          pRxPD;
-	RxRadiotapHdr_t radiotap_hdr;
-	RxRadiotapHdr_t *pradiotap_hdr;
+	struct RxRadiotapHdr radiotap_hdr;
+	struct RxRadiotapHdr *pradiotap_hdr;
 
 	ENTER();
 
@@ -420,7 +390,7 @@ int ProcessRxed_802_11_Packet(wlan_priva
 			radiotap_hdr.hdr.it_version = 0;
 			/* XXX must check this value for pad */
 			radiotap_hdr.hdr.it_pad = 0;
-			radiotap_hdr.hdr.it_len = sizeof(RxRadiotapHdr_t);
+			radiotap_hdr.hdr.it_len = sizeof(struct RxRadiotapHdr);
 			radiotap_hdr.hdr.it_present = RX_RADIOTAP_PRESENT;
 			/* unknown values */
 			radiotap_hdr.flags = 0;
@@ -442,14 +412,14 @@ int ProcessRxed_802_11_Packet(wlan_priva
 			skb_pull(skb, sizeof(struct RxPD));
 
 			/* add space for the new radio header */
-			if ( (skb_headroom(skb) < sizeof(RxRadiotapHdr_t)) &&
-					pskb_expand_head(skb, sizeof(RxRadiotapHdr_t), 0, GFP_ATOMIC)) {
+			if ( (skb_headroom(skb) < sizeof(struct RxRadiotapHdr)) &&
+					pskb_expand_head(skb, sizeof(struct RxRadiotapHdr), 0, GFP_ATOMIC)) {
 				PRINTM(MSG, "%s: couldn't pskb_expand_head\n", __func__);
 			}
 
 
-			pradiotap_hdr = (RxRadiotapHdr_t *) skb_push(skb, sizeof(RxRadiotapHdr_t));
-			memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(RxRadiotapHdr_t));
+			pradiotap_hdr = (struct RxRadiotapHdr *) skb_push(skb, sizeof(struct RxRadiotapHdr));
+			memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct RxRadiotapHdr));
 			//HEXDUMP1("RX radiomode packet AFT: ", skb->data, MIN(skb->len, 100));
 			break;
 
diff --git a/drivers/net/wireless/libertas/wlan_tx.c b/drivers/net/wireless/libertas/wlan_tx.c
index d649933..5423ebe 100644
--- a/drivers/net/wireless/libertas/wlan_tx.c
+++ b/drivers/net/wireless/libertas/wlan_tx.c
@@ -29,65 +29,6 @@ Change log:
 #include	"include.h"
 
 /********************************************************
-		Local Variables
-********************************************************/
-
-typedef struct
-{
-    struct ieee80211_radiotap_header hdr;
-    u8           rate;
-    u8           txpower;
-    u8           rts_retries;
-    u8           data_retries;
-    //u8           pad[IEEE80211_RADIOTAP_HDRLEN - 12];
-} __attribute__ ((packed)) TxRadiotapHdr_t;
-
-#define TX_RADIOTAP_PRESENT (   \
-		(1 << IEEE80211_RADIOTAP_RATE)    | \
-		(1 << IEEE80211_RADIOTAP_DBM_TX_POWER)  | \
-		(1 << IEEE80211_RADIOTAP_RTS_RETRIES) | \
-		(1 << IEEE80211_RADIOTAP_DATA_RETRIES)  | \
-		0)
-
-typedef struct
-{
-    u8  dest_addr[6];
-    u8  src_addr[6];
-    u16 ethertype;
-
-} __attribute__ ((packed)) EthII_Hdr_t;
-
-#define IEEE80211_FC_VERSION_MASK    0x0003
-#define IEEE80211_FC_TYPE_MASK       0x000c
-#define IEEE80211_FC_TYPE_MGT        0x0000
-#define IEEE80211_FC_TYPE_CTL        0x0004
-#define IEEE80211_FC_TYPE_DATA       0x0008
-#define IEEE80211_FC_SUBTYPE_MASK    0x00f0
-#define IEEE80211_FC_TOFROMDS_MASK   0x0300
-#define IEEE80211_FC_TODS_MASK       0x0100
-#define IEEE80211_FC_FROMDS_MASK     0x0200
-#define IEEE80211_FC_NODS            0x0000
-#define IEEE80211_FC_TODS            0x0100
-#define IEEE80211_FC_FROMDS          0x0200
-#define IEEE80211_FC_DSTODS          0x0300
-typedef struct
-{
-    u16  FrameControl;
-    u16  DurationID;
-    u8  address1[6];
-    u8  address2[6];
-    u8  address3[6];
-    u16  SeqControl;
-    u8  address4[6];
-
-} __attribute__ ((packed)) IEEE80211_Hdr_t;
-
-
-/********************************************************
-		Global Variables
-********************************************************/
-
-/********************************************************
 		Local Functions
 ********************************************************/
 
@@ -132,7 +73,7 @@ static int SendSinglePacket(wlan_private
 	struct TxPD	LocalTxPD;
 	struct TxPD	*pLocalTxPD = &LocalTxPD;
 	u8		*p802x_hdr;
-	TxRadiotapHdr_t *pradiotap_hdr;
+	struct TxRadiotapHdr *pradiotap_hdr;
 	u32 new_rate;
 	u8		*ptr = priv->adapter->TmpTxBuf;
 
@@ -170,7 +111,7 @@ static int SendSinglePacket(wlan_private
 		if ( priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP ) {
 
 			/* locate radiotap header */
-			pradiotap_hdr = (TxRadiotapHdr_t*)skb->data;
+			pradiotap_hdr = (struct TxRadiotapHdr*)skb->data;
 		
 			/* set TxPD fields from the radiotap header */
 			new_rate = convert_radiotap_rate_to_mv(
@@ -183,8 +124,8 @@ static int SendSinglePacket(wlan_private
 			}
 
 			/* skip the radiotap header */
-			p802x_hdr += sizeof(TxRadiotapHdr_t);
-			pLocalTxPD->TxPacketLength -= sizeof(TxRadiotapHdr_t);	
+			p802x_hdr += sizeof(struct TxRadiotapHdr);
+			pLocalTxPD->TxPacketLength -= sizeof(struct TxRadiotapHdr);	
 
 		}
 		/* copy destination address from 802.3 or 802.11 header */
@@ -392,7 +333,7 @@ done:	
 void SendTxFeedback(wlan_private *priv)
 {
 	wlan_adapter 	*Adapter = priv->adapter;
-	TxRadiotapHdr_t *radiotap_hdr; 	
+	struct TxRadiotapHdr *radiotap_hdr; 	
 	u32 		status = Adapter->EventCause;
 	int txfail;
 	int try_count;
@@ -402,7 +343,7 @@ void SendTxFeedback(wlan_private *priv)
 	    Adapter->CurrentTxSkb == NULL)
 		return;
 
-	radiotap_hdr = (TxRadiotapHdr_t*) Adapter->CurrentTxSkb->data;
+	radiotap_hdr = (struct TxRadiotapHdr*) Adapter->CurrentTxSkb->data;
 
 	if ((Adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0 )
 		HEXDUMP("TX feedback: ", (u8 *) radiotap_hdr, 
diff --git a/drivers/net/wireless/libertas/wlan_types.h b/drivers/net/wireless/libertas/wlan_types.h
index 17c4206..6410610 100644
--- a/drivers/net/wireless/libertas/wlan_types.h
+++ b/drivers/net/wireless/libertas/wlan_types.h
@@ -347,5 +347,12 @@ typedef struct 	_MrvlIEtypes_LedGpio_t {
 } __attribute__ ((packed)) MrvlIEtypes_LedGpio_t;
 
 
+struct EthII_Hdr
+{
+    u8  dest_addr[6];
+    u8  src_addr[6];
+    u16 ethertype;
+} __attribute__ ((packed));
+
 #endif /* _WLAN_TYPES_ */
 
diff --git a/drivers/net/wireless/libertas/wlan_version.h b/drivers/net/wireless/libertas/wlan_version.h
index 94282f8..8eb8d01 100644
--- a/drivers/net/wireless/libertas/wlan_version.h
+++ b/drivers/net/wireless/libertas/wlan_version.h
@@ -31,9 +31,6 @@ #define FPNUM "14"
 
 const char driver_version[]  = 
 	"COMM-USB8388-%s-" DRIVER_RELEASE_VERSION
-	"-("
-	"FP" FPNUM
-	")"
 #ifdef	DEBUG_LEVEL2
 	"-dbg"
 #endif
diff --git a/drivers/net/wireless/libertas/wlan_wext.c b/drivers/net/wireless/libertas/wlan_wext.c
index 7897045..bd6db30 100644
--- a/drivers/net/wireless/libertas/wlan_wext.c
+++ b/drivers/net/wireless/libertas/wlan_wext.c
@@ -88,6 +88,17 @@ static int wlan_set_txpow(struct net_dev
 static int wlan_get_txpow(struct net_device *dev, struct iw_request_info *info,
                           struct iw_param *vwrq, char *extra);
 
+/* DFT function declaration */
+static int wlan_dft_add_ioctl(wlan_private *priv, struct ifreq *req);
+static int wlan_dft_del_ioctl(wlan_private *priv, struct ifreq *req);
+static int wlan_dft_reset_ioctl(wlan_private *priv);
+static int wlan_dft_list_ioctl(wlan_private *priv, struct ifreq *req);
+
+/* BT function declaration */
+static int wlan_bt_add_ioctl(wlan_private *priv, struct ifreq *req);
+static int wlan_bt_del_ioctl(wlan_private *priv, struct ifreq *req);
+static int wlan_bt_reset_ioctl(wlan_private *priv);
+static int wlan_bt_list_ioctl(wlan_private *priv, struct ifreq *req);
 
 
 /** 
@@ -2203,22 +2214,22 @@ static const struct iw_priv_args wlan_pr
 	"setdataavg"
 	},
 	{
-		WLAN_SET_LINKMODE,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
-		IW_PRIV_TYPE_NONE,
-		"linkmode"
+	WLAN_SET_LINKMODE,
+	IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
+	IW_PRIV_TYPE_NONE,
+	"linkmode"
 	},
 	{
-		WLAN_SET_RADIOMODE,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
-		IW_PRIV_TYPE_NONE,
-		"radiomode"
+	WLAN_SET_RADIOMODE,
+	IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
+	IW_PRIV_TYPE_NONE,
+	"radiomode"
 	},
 	{
-		WLAN_SET_DEBUGMODE,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
-		IW_PRIV_TYPE_NONE,
-		"debugmode"
+	WLAN_SET_DEBUGMODE,
+	IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
+	IW_PRIV_TYPE_NONE,
+	"debugmode"
 	},
 	{ 
 	WLAN_SETNONE_GETONEINT, 
@@ -2257,22 +2268,22 @@ static const struct iw_priv_args wlan_pr
 	"getbcnavg"
 	},
 	{
-		WLAN_GET_LINKMODE,
-		IW_PRIV_TYPE_NONE,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
-		"get_linkmode"
+	WLAN_GET_LINKMODE,
+	IW_PRIV_TYPE_NONE,
+	IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
+	"get_linkmode"
 	},
 	{
-		WLAN_GET_RADIOMODE,
-		IW_PRIV_TYPE_NONE,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
-		"get_radiomode"
+	WLAN_GET_RADIOMODE,
+	IW_PRIV_TYPE_NONE,
+	IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
+	"get_radiomode"
 	},
 	{
-		WLAN_GET_DEBUGMODE,
-		IW_PRIV_TYPE_NONE,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
-		"get_debugmode"
+	WLAN_GET_DEBUGMODE,
+	IW_PRIV_TYPE_NONE,
+	IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 
+	"get_debugmode"
 	},
 	{ 
 	WLAN_SETNONE_GETTWELVE_CHAR,
@@ -2355,6 +2366,18 @@ #endif /* REASSOCIATION */
 	"wlanidle-off"
 	},
 	{
+	WLAN_SUBCMD_DFT_RESET,
+	IW_PRIV_TYPE_NONE,
+	IW_PRIV_TYPE_NONE,
+	"dft_reset"
+	},
+	{
+	WLAN_SUBCMD_BT_RESET,
+	IW_PRIV_TYPE_NONE,
+	IW_PRIV_TYPE_NONE,
+	"bt_reset"
+	},
+	{
 	WLAN_SET64CHAR_GET64CHAR,
 	IW_PRIV_TYPE_CHAR | 64,
 	IW_PRIV_TYPE_CHAR | 64,
@@ -2367,6 +2390,44 @@ #endif /* REASSOCIATION */
 	"sleepparams"
 	},
 
+	/* DFT Management */
+	{
+	WLAN_SUBCMD_DFT_ADD,
+	IW_PRIV_TYPE_CHAR | 64, 
+	IW_PRIV_TYPE_CHAR | 64, 
+	"dft_add"
+	},
+	{
+	WLAN_SUBCMD_DFT_DEL,
+	IW_PRIV_TYPE_CHAR | 64, 
+	IW_PRIV_TYPE_CHAR | 64, 
+	"dft_del"
+	},
+	{
+	WLAN_SUBCMD_DFT_LIST,
+	IW_PRIV_TYPE_CHAR | 64, 
+	IW_PRIV_TYPE_CHAR | 64, 
+	"dft_list"
+	},
+	/* BT Management */
+	{
+	WLAN_SUBCMD_BT_ADD,
+	IW_PRIV_TYPE_CHAR | 64, 
+	IW_PRIV_TYPE_CHAR | 64, 
+	"bt_add"
+	},
+	{
+	WLAN_SUBCMD_BT_DEL,
+	IW_PRIV_TYPE_CHAR | 64, 
+	IW_PRIV_TYPE_CHAR | 64, 
+	"bt_del"
+	},
+	{
+	WLAN_SUBCMD_BT_LIST,
+	IW_PRIV_TYPE_CHAR | 64, 
+	IW_PRIV_TYPE_CHAR | 64, 
+	"bt_list"
+	},
 	{
 	WLANSCAN_MODE,
 	IW_PRIV_TYPE_CHAR | 64,
@@ -2521,7 +2582,6 @@ #endif /* REASSOCIATION */
 		"getscantable"
 	},
 
-
 };
 
 struct iw_handler_def wlan_handler_def = {
@@ -2574,6 +2634,7 @@ static int wlan_hostcmd_ioctl(struct net
 	pCmdPtr = (struct HostCmd_DS_GEN *) pCmdNode->BufVirtualAddr;
 	if (copy_from_user(&gencmd, req->ifr_data, sizeof(gencmd))) {
 		PRINTM(INFO, "Copy from user failed\n");
+		kfree(tempResponseBuffer);
 		return -EFAULT;
 	}
 
@@ -2582,6 +2643,7 @@ static int wlan_hostcmd_ioctl(struct net
 	 */
 	if (copy_from_user(pCmdPtr, req->ifr_data, gencmd->Size)) {
 		PRINTM(INFO, "Copy from user failed\n");
+		kfree(tempResponseBuffer);
 		return -EFAULT;
 	}
 
@@ -3369,6 +3431,21 @@ static int wlan_setencryptionmode_ioctl(
 	return WLAN_STATUS_SUCCESS;
 }
 
+static void adjust_mtu(wlan_private *priv)
+{
+	int mtu_increment = 0;
+
+	if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
+		mtu_increment += sizeof(struct IEEE80211_Hdr);
+
+	if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP)
+		mtu_increment += max(sizeof(struct TxRadiotapHdr),
+				     sizeof(struct RxRadiotapHdr));
+	priv->wlan_dev.netdev->mtu = MRVDRV_MAXIMUM_ETH_PACKET_SIZE 
+			              - sizeof(struct EthII_Hdr)
+	 			      + mtu_increment; 
+}
+
 /** 
  *  @brief Set Link-Layer Layer mode
  *  @param priv                 A pointer to wlan_private structure
@@ -3384,20 +3461,20 @@ static int wlan_set_linkmode_ioctl(wlan_
 	mode = (int) ((struct ifreq *)((u8 *)req + 4))->ifr_data;
 
 	switch (mode) {
-		case 0:
-			// mode: normal (802.3)
+		case WLAN_LINKMODE_802_3:
 			priv->adapter->linkmode = mode;
 			break;
-		case 2:
-			// mode: monitor (802.11)
+		case WLAN_LINKMODE_802_11:
 			priv->adapter->linkmode = mode;
 			break;
 		default:
-			printk(KERN_ALERT "usb8388-5: invalid link-layer mode (%#x)\n", mode);
+			PRINTM(FATAL, "usb8388-5: invalid link-layer mode (%#x)\n", mode);
 			return WLAN_STATUS_NOT_ACCEPTED;
 			break;
 	}
-	printk(KERN_ALERT "usb8388-5: link-layer mode is %#x\n", mode);
+	PRINTM(INFO, "usb8388-5: link-layer mode is %#x\n", mode);
+
+	adjust_mtu(priv);
 
 	LEAVE();
 	return WLAN_STATUS_SUCCESS;
@@ -3418,24 +3495,20 @@ static int wlan_set_radiomode_ioctl(wlan
 	mode = (int) ((struct ifreq *)((u8 *)req + 4))->ifr_data;
 
 	switch (mode) {
-		case 0:
-			// mode: no radioheader
+		case WLAN_RADIOMODE_NONE:
 			priv->adapter->radiomode = mode;
 			break;
-		case 1:
-			// mode: prism
-			printk(KERN_ALERT "usb8388-5: prism radio header still unsupported\n");
-			break;
-		case 2:
-			// mode: radiotap
+		case WLAN_RADIOMODE_RADIOTAP:
 			priv->adapter->radiomode = mode;
 			break;
 		default:
-			printk(KERN_ALERT "usb8388-5: invalid radio header mode (%#x)\n", mode);
+			PRINTM(INFO, "usb8388-5: invalid radio header mode (%#x)\n", mode);
 			return WLAN_STATUS_NOT_ACCEPTED;
 			break;
 	}
-	printk(KERN_ALERT "usb8388-5: radio-header mode is %#x\n", mode);
+	PRINTM(INFO, "usb8388-5: radio-header mode is %#x\n", mode);
+
+	adjust_mtu(priv);
 
 	LEAVE();
 	return WLAN_STATUS_SUCCESS;
@@ -4106,6 +4179,12 @@ #endif /* REASSOCIATION */
 		case WLANWLANIDLEOFF:
 			wlanidle_off(priv);
 			break;
+		case WLAN_SUBCMD_DFT_RESET:	/* dft_reset */
+			wlan_dft_reset_ioctl(priv);
+			break;
+		case WLAN_SUBCMD_BT_RESET:	/* bt_reset */
+			wlan_bt_reset_ioctl(priv);
+			break;
 		}	/* End of switch */
 		break;
 
@@ -4278,7 +4357,6 @@ #define MAX_U16_VAL	65535
 		
 		break;
 
-
 	case WLAN_SETNONE_GETTWELVE_CHAR: /* Get Antenna settings */
 		/* 
 		 * We've not used IW_PRIV_TYPE_FIXED so sub-ioctl number is
@@ -4318,6 +4396,24 @@ #define MAX_U16_VAL	65535
 		case WLAN_GET_ADHOC_STATUS:
 			ret = wlan_get_adhoc_status_ioctl(priv, wrq);
 			break;
+		case WLAN_SUBCMD_DFT_ADD:
+			ret = wlan_dft_add_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_DFT_DEL: 
+			ret = wlan_dft_del_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_DFT_LIST: 
+			ret = wlan_dft_list_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_BT_ADD:
+			ret = wlan_bt_add_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_BT_DEL: 
+			ret = wlan_bt_del_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_BT_LIST: 
+			ret = wlan_bt_list_ioctl(priv, req);
+			break;
 		}
 		break;
 
@@ -5184,4 +5280,366 @@ void get_version(wlan_adapter *adapter, 
 	snprintf(version, maxlen, driver_version, fwver);
 }
 
+static inline int hex2int(char c)
+{
+	if (c >= '0' && c <= '9')
+		return (c - '0');
+	if (c >= 'a' && c <= 'f')
+		return (c - 'a' + 10);
+	if (c >= 'A' && c <= 'F')
+		return (c - 'A' + 10);
+	return -1;
+}
+
+/* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
+   into binary format (6 bytes).
+
+   This function expects that each byte is represented with 2 characters
+   (e.g., 11:2:11:11:11:11 is invalid) 
+
+ */
+static char *eth_str2addr(char *ethstr, u8 *addr)
+{
+	int i, val, val2;
+	char *pos = ethstr;
+
+	/* get rid of initial blanks */
+	while (*pos == ' ' || *pos == '\t') ++pos;
+
+	for (i = 0; i < 6; i++) {
+		val = hex2int(*pos++);
+		if (val < 0)
+			return NULL;
+		val2 = hex2int(*pos++);
+		if (val2 < 0)
+			return NULL;
+		addr[i] = (val * 16 + val2) & 0xff;
+
+		if (i < 5 && *pos++ != ':')
+			return NULL;
+	}
+	return pos;
+}
+
+/* this writes xx:xx:xx:xx:xx:xx into ethstr 
+   (ethstr must have space for 18 chars) */
+static int eth_addr2str(u8 *addr, char *ethstr)
+{
+	int i;
+	char *pos = ethstr;
+
+	for (i = 0; i < 6; i++) {
+		sprintf (pos, "%02x", addr[i] & 0xff);
+		pos += 2;
+		if (i < 5 )
+			*pos++ = ':';
+	}
+	return 17;
+}
+
+/** 
+ *  @brief          Add an entry to the DFT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_dft_add_ioctl(wlan_private *priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *) req;
+	char ethaddrs_str[36];
+	char *pos;
+	u8 ethaddrs[2*ETH_ALEN];
+#define ethaddr1 (ethaddrs+0)
+#define ethaddr2 (ethaddrs+6)
+
+	ENTER();
+	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
+			   sizeof(ethaddrs_str)))
+		return -EFAULT;
+
+	if ((pos = eth_str2addr(ethaddrs_str, ethaddr1)) == NULL) {
+		PRINTM(FATAL, "DFT_ADD: Invalid MAC address 1\n");
+		return -EINVAL;
+	}
+
+	if (eth_str2addr(pos, ethaddr2) == NULL) {
+		PRINTM(FATAL, "DFT_ADD: Invalid MAC address 2\n");
+		return -EINVAL;
+	}
+
+#ifdef DEBUG_LEVEL4
+	{
+	char ethaddr1_str[18], ethaddr2_str[18];
+	PRINTM(INFO, "DFT: adding %s\n", ethaddrs_str);
+	eth_addr2str(ethaddr1, ethaddr1_str);
+	eth_addr2str(ethaddr2, ethaddr2_str);
+	PRINTM(INFO, "DFT: adding (%s,%s)\n", ethaddr1_str, ethaddr2_str);
+	}
+#endif
+
+	LEAVE();
+	return (PrepareAndSendCommand(priv, HostCmd_CMD_DFT_ACCESS, 
+			HostCmd_ACT_DFT_ACCESS_ADD,
+			HostCmd_OPTION_WAITFORRSP, 0,
+			ethaddrs));
+}
+
+/** 
+ *  @brief          Delete an entry from the DFT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_dft_del_ioctl(wlan_private *priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *) req;
+	char ethaddrs_str[18];
+	u8 ethaddr[ETH_ALEN];
+	char *pos;
+
+	ENTER();
+	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
+			   sizeof(ethaddrs_str)))
+		return -EFAULT;
+
+	if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
+		PRINTM(FATAL, "Invalid MAC address\n");
+		return -EINVAL;
+	}
+
+	PRINTM(INFO, "DFT: deleting %s\n", ethaddrs_str);
+
+	LEAVE();
+	return (PrepareAndSendCommand(priv, 
+			HostCmd_CMD_DFT_ACCESS, 
+			HostCmd_ACT_DFT_ACCESS_DEL,
+			HostCmd_OPTION_WAITFORRSP, 0,
+			ethaddr));
+}
+
+/** 
+ *  @brief          Reset all entries from the DFT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_dft_reset_ioctl(wlan_private *priv)
+{
+	ENTER();
+
+	PRINTM(MSG, "DFT: resetting\n");
+
+	LEAVE();
+	return (PrepareAndSendCommand(priv, 
+			HostCmd_CMD_DFT_ACCESS, 
+			HostCmd_ACT_DFT_ACCESS_RESET,
+			HostCmd_OPTION_WAITFORRSP, 0,
+			NULL));
+}
+
+/** 
+ *  @brief          List an entry from the DFT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_dft_list_ioctl(wlan_private *priv, struct ifreq *req)
+{
+	int pos;
+	char *addr1, *addr2;
+	struct iwreq *wrq = (struct iwreq *) req;
+	/* used to pass id and store the dft entry returned by the FW */
+	union {
+		int id;
+		char addr1addr2[2 * ETH_ALEN];
+	} param;
+	static char outstr[64];
+	char *pbuf = outstr;
+	int ret;
+
+	ENTER();
+
+	if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
+		PRINTM(INFO, "Copy from user failed\n");
+		return WLAN_STATUS_FAILURE;
+	}
+	param.id = simple_strtoul(outstr, NULL, 10);	
+	pos = sprintf(pbuf, "%d: ", param.id);
+	pbuf += pos;
+
+	ret = PrepareAndSendCommand(priv, HostCmd_CMD_DFT_ACCESS, 
+			HostCmd_ACT_DFT_ACCESS_LIST,
+			HostCmd_OPTION_WAITFORRSP, 0,
+			(char *) &param);
+
+	if (ret == WLAN_STATUS_SUCCESS) {
+		addr1 = param.addr1addr2;
+		addr2 = param.addr1addr2+ ETH_ALEN;
+		
+		pos = sprintf(pbuf, "da ");
+		pbuf += pos;
+		pos = eth_addr2str(addr1, pbuf);		
+		pbuf += pos;		
+		pos = sprintf(pbuf, "    next hop ");
+		pbuf += pos;		
+		pos = eth_addr2str(addr2, pbuf);		
+		pbuf += pos;		
+	} else {
+		sprintf(pbuf, "(null)");
+		pbuf += pos;
+	}
+	wrq->u.data.length = strlen(outstr);
+	if (copy_to_user(wrq->u.data.pointer, (char *) outstr, 
+			 wrq->u.data.length)) {
+		PRINTM(INFO, "DFT_LIST: Copy to user failed!\n");
+		return -EFAULT;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief          Add an entry to the BT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_bt_add_ioctl(wlan_private *priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *) req;
+	char ethaddrs_str[18];
+	char *pos;
+	u8 ethaddr[ETH_ALEN];
+
+	ENTER();
+	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
+			   sizeof(ethaddrs_str)))
+		return -EFAULT;
+
+	if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
+		PRINTM(FATAL, "BT_ADD: Invalid MAC address\n");
+		return -EINVAL;
+	}
+
+	PRINTM(INFO, "BT: adding %s\n", ethaddrs_str);
+	LEAVE();
+	return (PrepareAndSendCommand(priv, HostCmd_CMD_DFT_ACCESS, 
+			HostCmd_ACT_BT_ACCESS_ADD,
+			HostCmd_OPTION_WAITFORRSP, 0,
+			ethaddr));
+}
+
+/** 
+ *  @brief          Delete an entry from the BT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_bt_del_ioctl(wlan_private *priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *) req;
+	char ethaddrs_str[18];
+	u8 ethaddr[ETH_ALEN];
+	char *pos;
+
+	ENTER();
+	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
+			   sizeof(ethaddrs_str)))
+		return -EFAULT;
+
+	if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
+		PRINTM(FATAL, "Invalid MAC address\n"); 
+		return -EINVAL;
+	}
+
+	PRINTM(INFO, "BT: deleting %s\n", ethaddrs_str);
+
+
+	return (PrepareAndSendCommand(priv, 
+			HostCmd_CMD_DFT_ACCESS, 
+			HostCmd_ACT_BT_ACCESS_DEL,
+			HostCmd_OPTION_WAITFORRSP, 0,
+			ethaddr));
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief          Reset all entries from the BT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_bt_reset_ioctl(wlan_private *priv)
+{
+	ENTER();
+
+	PRINTM(MSG, "BT: resetting\n");
+
+	return (PrepareAndSendCommand(priv, 
+			HostCmd_CMD_DFT_ACCESS, 
+			HostCmd_ACT_BT_ACCESS_RESET,
+			HostCmd_OPTION_WAITFORRSP, 0,
+			NULL));
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief          List an entry from the BT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_bt_list_ioctl(wlan_private *priv, struct ifreq *req)
+{
+	int pos;
+	char *addr1;
+	struct iwreq *wrq = (struct iwreq *) req;
+	/* used to pass id and store the bt entry returned by the FW */
+	union {
+		int id;
+		char addr1addr2[2 * ETH_ALEN];
+	} param;
+	static char outstr[64];
+	char *pbuf = outstr;
+	int ret;
+
+	ENTER();
+
+	if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
+		PRINTM(INFO, "Copy from user failed\n");
+		return WLAN_STATUS_FAILURE;
+	}
+	param.id = simple_strtoul(outstr, NULL, 10);	
+	pos = sprintf(pbuf, "%d: ", param.id);
+	pbuf += pos;
+
+	ret = PrepareAndSendCommand(priv, HostCmd_CMD_DFT_ACCESS, 
+			HostCmd_ACT_BT_ACCESS_LIST,
+			HostCmd_OPTION_WAITFORRSP, 0,
+			(char *) &param);
+
+	if (ret == WLAN_STATUS_SUCCESS) {
+		addr1 = param.addr1addr2;
+		
+		pos = sprintf(pbuf, "ignoring traffic from ");
+		pbuf += pos;
+		pos = eth_addr2str(addr1, pbuf);		
+		pbuf += pos;		
+	} else {
+		sprintf(pbuf, "(null)");
+		pbuf += pos;
+	}
+
+	wrq->u.data.length = strlen(outstr);
+	if (copy_to_user(wrq->u.data.pointer, (char *) outstr, 
+			 wrq->u.data.length)) {
+		PRINTM(INFO, "BT_LIST: Copy to user failed!\n");
+		return -EFAULT;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
 
diff --git a/drivers/net/wireless/libertas/wlan_wext.h b/drivers/net/wireless/libertas/wlan_wext.h
index 0f227e9..041dde5 100644
--- a/drivers/net/wireless/libertas/wlan_wext.h
+++ b/drivers/net/wireless/libertas/wlan_wext.h
@@ -65,6 +65,8 @@ #endif /* REASSOCIATION */
 
 #define WLANWLANIDLEON				10
 #define WLANWLANIDLEOFF				11
+#define WLAN_SUBCMD_DFT_RESET			12
+#define WLAN_SUBCMD_BT_RESET			13
 
 #define WLANGETLOG                  	(WLANIOCTL + 9)
 #define WLAN_SETCONF_GETCONF		(WLANIOCTL + 10)
@@ -136,6 +138,12 @@ #define WLANSCAN_MODE				6
 
 #define WLAN_GET_ADHOC_STATUS			9
 
+#define WLAN_SUBCMD_DFT_ADD			15
+#define WLAN_SUBCMD_DFT_DEL   			16
+#define WLAN_SUBCMD_DFT_LIST			17 
+#define WLAN_SUBCMD_BT_ADD			18	
+#define WLAN_SUBCMD_BT_DEL   			19
+#define WLAN_SUBCMD_BT_LIST			20 
 
 #define WLANEXTSCAN			(WLANIOCTL + 26)
 
diff --git a/drivers/net/wireless/libertas/wlanconfig/wlanconfig.c b/drivers/net/wireless/libertas/wlanconfig/wlanconfig.c
index eaf1108..ba000bc 100644
--- a/drivers/net/wireless/libertas/wlanconfig/wlanconfig.c
+++ b/drivers/net/wireless/libertas/wlanconfig/wlanconfig.c
@@ -54,9 +54,9 @@ typedef unsigned char		u8;
 typedef unsigned short  	u16;
 typedef unsigned long		u32;
 typedef unsigned long long	u64;
-typedef signed char		s8;
-typedef signed short  		s16;
-typedef signed long		s32;
+typedef char		s8;
+typedef short		s16;
+typedef long		s32;
 
 #ifdef 	BYTE_SWAP
 #define 	cpu_to_le16(x)	__swab16(x)
@@ -626,7 +626,8 @@ static int wlan_get_hostcmd_data(FILE *f
  */
 static int process_host_cmd(int argc, char *argv[])
 {
-	u8		line[256], cmdname[256], *buf, *pos;
+	s8		line[256], cmdname[256], *pos;
+	u8		*buf;
 	FILE		*fp;
 	HostCmd_DS_GEN	*hostcmd;
 	struct ifreq	userdata;



More information about the libertas-dev mailing list