wl12xx: cmd and acx interface rework

Rework cmd and acx interfaces, it was just too confusing earlier. Now
all commands need to contain all the needed headers, either just cmd
headers or both cmd and acx headers. This accomplish to remove the
extra copy done for each command. The interfaces are now properly
documented as well.

Also try to make all commands safe for DMA transfers. I might have missed
some, but most of them should be fixed now.

And this is not all! As a free bonus you will also get some cosmetic
cleanups and code reorganisation. Order today!

Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 603d611..c6a4544 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -618,7 +618,8 @@
 }
 
 /* HW encryption */
-static int wl12xx_set_key_type(struct wl12xx *wl, struct acx_set_key *key,
+static int wl12xx_set_key_type(struct wl12xx *wl,
+			       struct wl12xx_cmd_set_keys *key,
 			       enum set_key_cmd cmd,
 			       struct ieee80211_key_conf *mac80211_key,
 			       const u8 *addr)
@@ -661,7 +662,7 @@
 			     struct ieee80211_key_conf *key)
 {
 	struct wl12xx *wl = hw->priv;
-	struct acx_set_key wl_key;
+	struct wl12xx_cmd_set_keys *wl_cmd;
 	const u8 *addr;
 	int ret;
 
@@ -670,7 +671,11 @@
 
 	wl12xx_debug(DEBUG_MAC80211, "mac80211 set key");
 
-	memset(&wl_key, 0, sizeof(wl_key));
+	wl_cmd = kzalloc(sizeof(*wl_cmd), GFP_KERNEL);
+	if (!wl_cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
 	addr = sta ? sta->addr : bcast_addr;
 
@@ -680,59 +685,69 @@
 		     key->alg, key->keyidx, key->keylen, key->flags);
 	wl12xx_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen);
 
+	if (is_zero_ether_addr(addr)) {
+		/* We dont support TX only encryption */
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
 	mutex_lock(&wl->mutex);
 
 	switch (cmd) {
 	case SET_KEY:
-		wl_key.key_action = KEY_ADD_OR_REPLACE;
+		wl_cmd->key_action = KEY_ADD_OR_REPLACE;
 		break;
 	case DISABLE_KEY:
-		wl_key.key_action = KEY_REMOVE;
+		wl_cmd->key_action = KEY_REMOVE;
 		break;
 	default:
 		wl12xx_error("Unsupported key cmd 0x%x", cmd);
 		break;
 	}
 
-	ret = wl12xx_set_key_type(wl, &wl_key, cmd, key, addr);
+	ret = wl12xx_set_key_type(wl, wl_cmd, cmd, key, addr);
 	if (ret < 0) {
 		wl12xx_error("Set KEY type failed");
-		goto out;
+		goto out_unlock;
 	}
 
-	if (wl_key.key_type != KEY_WEP_DEFAULT)
-		memcpy(wl_key.addr, addr, ETH_ALEN);
+	if (wl_cmd->key_type != KEY_WEP_DEFAULT)
+		memcpy(wl_cmd->addr, addr, ETH_ALEN);
 
-	if ((wl_key.key_type == KEY_TKIP_MIC_GROUP) ||
-	    (wl_key.key_type == KEY_TKIP_MIC_PAIRWISE)) {
+	if ((wl_cmd->key_type == KEY_TKIP_MIC_GROUP) ||
+	    (wl_cmd->key_type == KEY_TKIP_MIC_PAIRWISE)) {
 		/*
 		 * We get the key in the following form:
 		 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
 		 * but the target is expecting:
 		 * TKIP - RX MIC - TX MIC
 		 */
-		memcpy(wl_key.key, key->key, 16);
-		memcpy(wl_key.key + 16, key->key + 24, 8);
-		memcpy(wl_key.key + 24, key->key + 16, 8);
+		memcpy(wl_cmd->key, key->key, 16);
+		memcpy(wl_cmd->key + 16, key->key + 24, 8);
+		memcpy(wl_cmd->key + 24, key->key + 16, 8);
 
 	} else {
-		memcpy(wl_key.key, key->key, key->keylen);
+		memcpy(wl_cmd->key, key->key, key->keylen);
 	}
-	wl_key.key_size = key->keylen;
+	wl_cmd->key_size = key->keylen;
 
-	wl_key.id = key->keyidx;
-	wl_key.ssid_profile = 0;
+	wl_cmd->id = key->keyidx;
+	wl_cmd->ssid_profile = 0;
 
-	wl12xx_dump(DEBUG_CRYPT, "TARGET KEY: ", &wl_key, sizeof(wl_key));
+	wl12xx_dump(DEBUG_CRYPT, "TARGET KEY: ", wl_cmd, sizeof(*wl_cmd));
 
-	if (wl12xx_cmd_send(wl, CMD_SET_KEYS, &wl_key, sizeof(wl_key)) < 0) {
-		wl12xx_error("Set KEY failed");
-		ret = -EOPNOTSUPP;
-		goto out;
+	ret = wl12xx_cmd_send(wl, CMD_SET_KEYS, wl_cmd, sizeof(*wl_cmd));
+	if (ret < 0) {
+		wl12xx_warning("could not set keys");
+		goto out_unlock;
 	}
 
+out_unlock:
+	mutex_unlock(&wl->mutex);
+
 out:
-	mutex_unlock(&wl->mutex);
+	kfree(wl_cmd);
+
 	return ret;
 }
 
@@ -812,11 +827,10 @@
 			  u8 active_scan, u8 high_prio, u8 num_channels,
 			  u8 probe_requests)
 {
+	struct wl12xx_cmd_trigger_scan_to *trigger = NULL;
+	struct cmd_scan *params = NULL;
 	int i, ret;
-	u32 split_scan = 0;
 	u16 scan_options = 0;
-	struct cmd_scan *params;
-	struct wl12xx_command *cmd_answer;
 
 	if (wl->scanning)
 		return -EINVAL;
@@ -870,10 +884,16 @@
 		goto out;
 	}
 
-	ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, &split_scan,
-			      sizeof(u32));
+	trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
+	if (!trigger)
+		goto out;
+
+	trigger->timeout = 0;
+
+	ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
+			      sizeof(*trigger));
 	if (ret < 0) {
-		wl12xx_error("Split SCAN failed");
+		wl12xx_error("trigger scan to failed for hw scan");
 		goto out;
 	}
 
@@ -887,10 +907,9 @@
 
 	wl12xx_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
 
-	cmd_answer = (struct wl12xx_command *) params;
-	if (cmd_answer->status != CMD_STATUS_SUCCESS) {
+	if (params->header.status != CMD_STATUS_SUCCESS) {
 		wl12xx_error("TEST command answer error: %d",
-			     cmd_answer->status);
+			     params->header.status);
 		wl->scanning = false;
 		ret = -EIO;
 		goto out;
@@ -942,7 +961,7 @@
 				       struct ieee80211_bss_conf *bss_conf,
 				       u32 changed)
 {
-	enum acx_ps_mode mode;
+	enum wl12xx_cmd_ps_mode mode;
 	struct wl12xx *wl = hw->priv;
 	struct sk_buff *beacon;
 	int ret;