diff options
| author | Patrick McHardy <kaber@trash.net> | 2010-05-10 18:39:28 +0200 | 
|---|---|---|
| committer | Patrick McHardy <kaber@trash.net> | 2010-05-10 18:39:28 +0200 | 
| commit | 1e4b1057121bc756b91758a434b504d2010f6088 (patch) | |
| tree | b016cf2c728289c7e36d9e4e488f30ab0bd0ae6e /drivers/net/wireless/libertas_tf/cmd.c | |
| parent | 3b254c54ec46eb022cb26ee6ab37fae23f5f7d6a (diff) | |
| parent | 3ee943728fff536edaf8f59faa58aaa1aa7366e3 (diff) | |
| download | olio-linux-3.10-1e4b1057121bc756b91758a434b504d2010f6088.tar.xz olio-linux-3.10-1e4b1057121bc756b91758a434b504d2010f6088.zip  | |
Merge branch 'master' of /repos/git/net-next-2.6
Conflicts:
	net/bridge/br_device.c
	net/bridge/br_forward.c
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'drivers/net/wireless/libertas_tf/cmd.c')
| -rw-r--r-- | drivers/net/wireless/libertas_tf/cmd.c | 203 | 
1 files changed, 169 insertions, 34 deletions
diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c index b620daf59ef..8945afd6ce3 100644 --- a/drivers/net/wireless/libertas_tf/cmd.c +++ b/drivers/net/wireless/libertas_tf/cmd.c @@ -7,6 +7,8 @@   *  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/slab.h>  #include "libertas_tf.h" @@ -82,6 +84,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)  	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); @@ -104,6 +108,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)  		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 @@ -118,8 +124,10 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)  	}  	/* if it's unidentified region code, use the default (USA) */ -	if (i >= MRVDRV_MAX_REGION_CODE) +	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); @@ -128,6 +136,7 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)  	lbtf_geo_init(priv);  out: +	lbtf_deb_leave(LBTF_DEB_CMD);  	return ret;  } @@ -141,13 +150,18 @@ out:   */  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); -	return lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); +	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) @@ -155,20 +169,28 @@ int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)  	struct cmd_ds_802_11_beacon_set cmd;  	int size; -	if (beacon->len > MRVL_MAX_BCN_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) { +		     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); @@ -176,6 +198,8 @@ int lbtf_beacon_ctrl(struct lbtf_private *priv, bool 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;  } @@ -183,17 +207,28 @@ 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) -		return; +	if (!cmdnode) { +		lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n"); +		goto qcmd_done; +	} -	if (!cmdnode->cmdbuf->size) -		return; +	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, @@ -206,22 +241,33 @@ static void lbtf_submit_command(struct lbtf_private *priv,  	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) +	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);  }  /** @@ -231,8 +277,10 @@ static void lbtf_submit_command(struct lbtf_private *priv,  static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,  					 struct cmd_ctrl_node *cmdnode)  { +	lbtf_deb_enter(LBTF_DEB_HOST); +  	if (!cmdnode) -		return; +		goto cl_ins_out;  	cmdnode->callback = NULL;  	cmdnode->callback_arg = 0; @@ -240,6 +288,9 @@ static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,  	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, @@ -268,29 +319,41 @@ 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; @@ -298,11 +361,13 @@ void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)  		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); @@ -310,6 +375,7 @@ int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)  	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;  } @@ -318,6 +384,8 @@ 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); @@ -341,19 +409,28 @@ int lbtf_set_radio_control(struct lbtf_private *priv)  	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);  }  /** @@ -365,29 +442,43 @@ void lbtf_set_mac_control(struct lbtf_private *priv)   */  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) -		return -1; +	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) -			return -1; +		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]);  	} -	return 0; + +	ret = 0; + +done: +	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret); +	return ret;  }  /** @@ -402,9 +493,13 @@ 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) -		return 0; +	if (priv->cmd_array == NULL) { +		lbtf_deb_host("FREE_CMD_BUF: cmd_array is NULL\n"); +		goto done; +	}  	cmdarray = priv->cmd_array; @@ -418,6 +513,8 @@ int lbtf_free_cmd_buffer(struct lbtf_private *priv)  	kfree(priv->cmd_array);  	priv->cmd_array = NULL; +done: +	lbtf_deb_leave(LBTF_DEB_HOST);  	return 0;  } @@ -433,6 +530,8 @@ 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; @@ -442,11 +541,14 @@ static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)  		tempnode = list_first_entry(&priv->cmdfreeq,  					    struct cmd_ctrl_node, list);  		list_del(&tempnode->list); -	} else +	} 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;  } @@ -462,16 +564,20 @@ 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 LBS_DEB_THREAD and not LBS_DEB_HOST, because the +	/* 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); -		return -1; +		ret = -1; +		goto done;  	}  	if (!list_empty(&priv->cmdpendingq)) { @@ -483,11 +589,17 @@ int lbtf_execute_next_command(struct lbtf_private *priv)  		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); -	return 0; + +	ret = 0; +done: +	lbtf_deb_leave(LBTF_DEB_THREAD); +	return ret;  }  static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv, @@ -498,14 +610,22 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,  {  	struct cmd_ctrl_node *cmdnode; -	if (priv->surpriseremoved) -		return ERR_PTR(-ENOENT); +	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); -		return ERR_PTR(-ENOBUFS); +		cmdnode = ERR_PTR(-ENOBUFS); +		goto done;  	}  	cmdnode->callback = callback; @@ -520,17 +640,24 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,  	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, @@ -543,30 +670,35 @@ int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,  	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)) -		return PTR_ERR(cmdnode); +	if (IS_ERR(cmdnode)) { +		ret = PTR_ERR(cmdnode); +		goto done; +	}  	might_sleep();  	ret = wait_event_interruptible(cmdnode->cmdwait_q,  				       cmdnode->cmdwaitqwoken); -       if (ret)	{ -		printk(KERN_DEBUG -		       "libertastf: command 0x%04x interrupted by signal", -		       command); -		return ret; +	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) -		printk(KERN_DEBUG "libertastf: command 0x%04x failed: %d\n", +		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); @@ -587,6 +719,8 @@ int lbtf_process_rx_command(struct lbtf_private *priv)  	unsigned long flags;  	uint16_t result; +	lbtf_deb_enter(LBTF_DEB_CMD); +  	mutex_lock(&priv->lock);  	spin_lock_irqsave(&priv->driver_lock, flags); @@ -602,7 +736,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv)  	result = le16_to_cpu(resp->result);  	if (net_ratelimit()) -		printk(KERN_DEBUG "libertastf: cmd response 0x%04x, seq %d, size %d\n", +		pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n",  			respcmd, le16_to_cpu(resp->seqnum),  			le16_to_cpu(resp->size)); @@ -639,7 +773,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv)  		switch (respcmd) {  		case CMD_RET(CMD_GET_HW_SPEC):  		case CMD_RET(CMD_802_11_RESET): -			printk(KERN_DEBUG "libertastf: reset failed\n"); +			pr_info("libertastf: reset failed\n");  			break;  		} @@ -666,5 +800,6 @@ int lbtf_process_rx_command(struct lbtf_private *priv)  done:  	mutex_unlock(&priv->lock); +	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);  	return ret;  }  |