diff options
Diffstat (limited to 'drivers/net/wireless/libertas/cmd.c')
| -rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 392 | 
1 files changed, 226 insertions, 166 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 78c4da150a7..aaa297315c4 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1,12 +1,14 @@ -/** -  * This file contains the handling of command. -  * It prepares command and sends it to firmware when it is ready. -  */ +/* + * This file contains the handling of command. + * It prepares command and sends it to firmware when it is ready. + */ +#include <linux/hardirq.h>  #include <linux/kfifo.h>  #include <linux/sched.h>  #include <linux/slab.h>  #include <linux/if_arp.h> +#include <linux/export.h>  #include "decl.h"  #include "cfg.h" @@ -16,14 +18,14 @@  #define CAL_RSSI(snr, nf)	((s32)((s32)(snr) + CAL_NF(nf)))  /** - *  @brief Simple callback that copies response back into command + * lbs_cmd_copyback - Simple callback that copies response back into command   * - *  @param priv    	A pointer to struct lbs_private structure - *  @param extra  	A pointer to the original command structure for which - *                      'resp' is a response - *  @param resp         A pointer to the command response + * @priv:	A pointer to &struct lbs_private structure + * @extra:	A pointer to the original command structure for which + *		'resp' is a response + * @resp:	A pointer to the command response   * - *  @return 	   	0 on success, error on failure + * returns:	0 on success, error on failure   */  int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,  		     struct cmd_header *resp) @@ -38,15 +40,15 @@ int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,  EXPORT_SYMBOL_GPL(lbs_cmd_copyback);  /** - *  @brief Simple callback that ignores the result. Use this if - *  you just want to send a command to the hardware, but don't + *  lbs_cmd_async_callback - Simple callback that ignores the result. + *  Use this if you just want to send a command to the hardware, but don't   *  care for the result.   * - *  @param priv         ignored - *  @param extra        ignored - *  @param resp         ignored + *  @priv:	ignored + *  @extra:	ignored + *  @resp:	ignored   * - *  @return 	   	0 for success + *  returns:	0 for success   */  static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,  		     struct cmd_header *resp) @@ -56,10 +58,11 @@ static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,  /** - *  @brief Checks whether a command is allowed in Power Save mode + *  is_command_allowed_in_ps - tests if a command is allowed in Power Save mode   * - *  @param command the command ID - *  @return 	   1 if allowed, 0 if not allowed + *  @cmd:	the command ID + * + *  returns:	1 if allowed, 0 if not allowed   */  static u8 is_command_allowed_in_ps(u16 cmd)  { @@ -75,11 +78,12 @@ static u8 is_command_allowed_in_ps(u16 cmd)  }  /** - *  @brief Updates the hardware details like MAC address and regulatory region + *  lbs_update_hw_spec - Updates the hardware details like MAC address + *  and regulatory region   * - *  @param priv    	A pointer to struct lbs_private structure + *  @priv:	A pointer to &struct lbs_private structure   * - *  @return 	   	0 on success, error on failure + *  returns:	0 on success, error on failure   */  int lbs_update_hw_spec(struct lbs_private *priv)  { @@ -108,7 +112,7 @@ int lbs_update_hw_spec(struct lbs_private *priv)  	 * CF card    firmware 5.0.16p0:   cap 0x00000303  	 * USB dongle firmware 5.110.17p2: cap 0x00000303  	 */ -	lbs_pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n", +	netdev_info(priv->dev, "%pM, fw %u.%u.%up%u, cap 0x%08x\n",  		cmd.permanentaddr,  		priv->fwrelease >> 24 & 0xff,  		priv->fwrelease >> 16 & 0xff, @@ -139,15 +143,20 @@ int lbs_update_hw_spec(struct lbs_private *priv)  	/* if it's unidentified region code, use the default (USA) */  	if (i >= MRVDRV_MAX_REGION_CODE) {  		priv->regioncode = 0x10; -		lbs_pr_info("unidentified region code; using the default (USA)\n"); +		netdev_info(priv->dev, +			    "unidentified region code; using the default (USA)\n");  	}  	if (priv->current_addr[0] == 0xff)  		memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); -	memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN); -	if (priv->mesh_dev) -		memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); +	if (!priv->copied_hwaddr) { +		memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN); +		if (priv->mesh_dev) +			memcpy(priv->mesh_dev->dev_addr, +				priv->current_addr, ETH_ALEN); +		priv->copied_hwaddr = 1; +	}  out:  	lbs_deb_leave(LBS_DEB_CMD); @@ -205,7 +214,7 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,  					(uint8_t *)&cmd_config.wol_conf,  					sizeof(struct wol_config));  	} else { -		lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); +		netdev_info(priv->dev, "HOST_SLEEP_CFG failed %d\n", ret);  	}  	return ret; @@ -213,14 +222,14 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,  EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);  /** - *  @brief Sets the Power Save mode + *  lbs_set_ps_mode - Sets the Power Save mode   * - *  @param priv    	A pointer to struct lbs_private structure - *  @param cmd_action	The Power Save operation (PS_MODE_ACTION_ENTER_PS or + *  @priv:	A pointer to &struct lbs_private structure + *  @cmd_action: The Power Save operation (PS_MODE_ACTION_ENTER_PS or   *                         PS_MODE_ACTION_EXIT_PS) - *  @param block	Whether to block on a response or not + *  @block:	Whether to block on a response or not   * - *  @return 	   	0 on success, error on failure + *  returns:	0 on success, error on failure   */  int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)  { @@ -308,7 +317,7 @@ static int lbs_wait_for_ds_awake(struct lbs_private *priv)  	if (priv->is_deep_sleep) {  		if (!wait_event_interruptible_timeout(priv->ds_awake_q,  					!priv->is_deep_sleep, (10 * HZ))) { -			lbs_pr_err("ds_awake_q: timer expired\n"); +			netdev_err(priv->dev, "ds_awake_q: timer expired\n");  			ret = -1;  		}  	} @@ -333,7 +342,7 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)  				netif_carrier_off(priv->dev);  			}  		} else { -			lbs_pr_err("deep sleep: already enabled\n"); +			netdev_err(priv->dev, "deep sleep: already enabled\n");  		}  	} else {  		if (priv->is_deep_sleep) { @@ -343,8 +352,8 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)  			if (!ret) {  				ret = lbs_wait_for_ds_awake(priv);  				if (ret) -					lbs_pr_err("deep sleep: wakeup" -							"failed\n"); +					netdev_err(priv->dev, +						   "deep sleep: wakeup failed\n");  			}  		}  	} @@ -378,8 +387,9 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep)  			ret = lbs_host_sleep_cfg(priv, priv->wol_criteria,  					(struct wol_config *)NULL);  			if (ret) { -				lbs_pr_info("Host sleep configuration failed: " -						"%d\n", ret); +				netdev_info(priv->dev, +					    "Host sleep configuration failed: %d\n", +					    ret);  				return ret;  			}  			if (priv->psstate == PS_STATE_FULL_POWER) { @@ -389,19 +399,21 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep)  						sizeof(cmd),  						lbs_ret_host_sleep_activate, 0);  				if (ret) -					lbs_pr_info("HOST_SLEEP_ACTIVATE " -							"failed: %d\n", ret); +					netdev_info(priv->dev, +						    "HOST_SLEEP_ACTIVATE failed: %d\n", +						    ret);  			}  			if (!wait_event_interruptible_timeout(  						priv->host_sleep_q,  						priv->is_host_sleep_activated,  						(10 * HZ))) { -				lbs_pr_err("host_sleep_q: timer expired\n"); +				netdev_err(priv->dev, +					   "host_sleep_q: timer expired\n");  				ret = -1;  			}  		} else { -			lbs_pr_err("host sleep: already enabled\n"); +			netdev_err(priv->dev, "host sleep: already enabled\n");  		}  	} else {  		if (priv->is_host_sleep_activated) @@ -413,13 +425,13 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep)  }  /** - *  @brief Set an SNMP MIB value + *  lbs_set_snmp_mib - Set an SNMP MIB value   * - *  @param priv    	A pointer to struct lbs_private structure - *  @param oid  	The OID to set in the firmware - *  @param val  	Value to set the OID to + *  @priv:	A pointer to &struct lbs_private structure + *  @oid:	The OID to set in the firmware + *  @val:	Value to set the OID to   * - *  @return 	   	0 on success, error on failure + *  returns: 	   	0 on success, error on failure   */  int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)  { @@ -463,13 +475,13 @@ out:  }  /** - *  @brief Get an SNMP MIB value + *  lbs_get_snmp_mib - Get an SNMP MIB value   * - *  @param priv    	A pointer to struct lbs_private structure - *  @param oid  	The OID to retrieve from the firmware - *  @param out_val  	Location for the returned value + *  @priv:	A pointer to &struct lbs_private structure + *  @oid:	The OID to retrieve from the firmware + *  @out_val:	Location for the returned value   * - *  @return 	   	0 on success, error on failure + *  returns:	0 on success, error on failure   */  int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)  { @@ -506,14 +518,14 @@ out:  }  /** - *  @brief Get the min, max, and current TX power + *  lbs_get_tx_power - Get the min, max, and current TX power   * - *  @param priv    	A pointer to struct lbs_private structure - *  @param curlevel  	Current power level in dBm - *  @param minlevel  	Minimum supported power level in dBm (optional) - *  @param maxlevel  	Maximum supported power level in dBm (optional) + *  @priv:	A pointer to &struct lbs_private structure + *  @curlevel:	Current power level in dBm + *  @minlevel:	Minimum supported power level in dBm (optional) + *  @maxlevel:	Maximum supported power level in dBm (optional)   * - *  @return 	   	0 on success, error on failure + *  returns:	0 on success, error on failure   */  int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,  		     s16 *maxlevel) @@ -541,12 +553,12 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,  }  /** - *  @brief Set the TX power + *  lbs_set_tx_power - Set the TX power   * - *  @param priv    	A pointer to struct lbs_private structure - *  @param dbm  	The desired power level in dBm + *  @priv:	A pointer to &struct lbs_private structure + *  @dbm:	The desired power level in dBm   * - *  @return 	   	0 on success, error on failure + *  returns: 	   	0 on success, error on failure   */  int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)  { @@ -569,12 +581,13 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)  }  /** - *  @brief Enable or disable monitor mode (only implemented on OLPC usb8388 FW) + *  lbs_set_monitor_mode - Enable or disable monitor mode + *  (only implemented on OLPC usb8388 FW)   * - *  @param priv        A pointer to struct lbs_private structure - *  @param enable      1 to enable monitor mode, 0 to disable + *  @priv:	A pointer to &struct lbs_private structure + *  @enable:	1 to enable monitor mode, 0 to disable   * - *  @return            0 on success, error on failure + *  returns:	0 on success, error on failure   */  int lbs_set_monitor_mode(struct lbs_private *priv, int enable)  { @@ -600,11 +613,11 @@ int lbs_set_monitor_mode(struct lbs_private *priv, int enable)  }  /** - *  @brief Get the radio channel + *  lbs_get_channel - Get the radio channel   * - *  @param priv    	A pointer to struct lbs_private structure + *  @priv:	A pointer to &struct lbs_private structure   * - *  @return 	   	The channel on success, error on failure + *  returns:	The channel on success, error on failure   */  static int lbs_get_channel(struct lbs_private *priv)  { @@ -646,12 +659,12 @@ int lbs_update_channel(struct lbs_private *priv)  }  /** - *  @brief Set the radio channel + *  lbs_set_channel - Set the radio channel   * - *  @param priv    	A pointer to struct lbs_private structure - *  @param channel  	The desired channel, or 0 to clear a locked channel + *  @priv:	A pointer to &struct lbs_private structure + *  @channel:	The desired channel, or 0 to clear a locked channel   * - *  @return 	   	0 on success, error on failure + *  returns:	0 on success, error on failure   */  int lbs_set_channel(struct lbs_private *priv, u8 channel)  { @@ -682,12 +695,13 @@ out:  }  /** - *  @brief Get current RSSI and noise floor + * lbs_get_rssi - Get current RSSI and noise floor   * - *  @param priv		A pointer to struct lbs_private structure - *  @param rssi		On successful return, signal level in mBm + * @priv:	A pointer to &struct lbs_private structure + * @rssi:	On successful return, signal level in mBm + * @nf:		On successful return, Noise floor   * - *  @return 	   	The channel on success, error on failure + * returns:	The channel on success, error on failure   */  int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)  { @@ -715,18 +729,17 @@ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)  }  /** - *  @brief Send regulatory and 802.11d domain information to the firmware + *  lbs_set_11d_domain_info - Send regulatory and 802.11d domain information + *  to the firmware   * - *  @param priv		pointer to struct lbs_private - *  @param request	cfg80211 regulatory request structure - *  @param bands	the device's supported bands and channels + *  @priv:	pointer to &struct lbs_private   * - *  @return		0 on success, error code on failure + *  returns:	0 on success, error code on failure  */ -int lbs_set_11d_domain_info(struct lbs_private *priv, -			    struct regulatory_request *request, -			    struct ieee80211_supported_band **bands) +int lbs_set_11d_domain_info(struct lbs_private *priv)  { +	struct wiphy *wiphy = priv->wdev->wiphy; +	struct ieee80211_supported_band **bands = wiphy->bands;  	struct cmd_ds_802_11d_domain_info cmd;  	struct mrvl_ie_domain_param_set *domain = &cmd.domain;  	struct ieee80211_country_ie_triplet *t; @@ -737,21 +750,23 @@ int lbs_set_11d_domain_info(struct lbs_private *priv,  	u8 first_channel = 0, next_chan = 0, max_pwr = 0;  	u8 i, flag = 0;  	size_t triplet_size; -	int ret; +	int ret = 0;  	lbs_deb_enter(LBS_DEB_11D); +	if (!priv->country_code[0]) +		goto out;  	memset(&cmd, 0, sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_ACT_SET);  	lbs_deb_11d("Setting country code '%c%c'\n", -		    request->alpha2[0], request->alpha2[1]); +		    priv->country_code[0], priv->country_code[1]);  	domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);  	/* Set country code */ -	domain->country_code[0] = request->alpha2[0]; -	domain->country_code[1] = request->alpha2[1]; +	domain->country_code[0] = priv->country_code[0]; +	domain->country_code[1] = priv->country_code[1];  	domain->country_code[2] = ' ';  	/* Now set up the channel triplets; firmware is somewhat picky here @@ -833,20 +848,21 @@ int lbs_set_11d_domain_info(struct lbs_private *priv,  	ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd); +out:  	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);  	return ret;  }  /** - *  @brief Read a MAC, Baseband, or RF register + *  lbs_get_reg - Read a MAC, Baseband, or RF register   * - *  @param priv		pointer to struct lbs_private - *  @param cmd		register command, one of CMD_MAC_REG_ACCESS, - *                        CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS - *  @param offset       byte offset of the register to get - *  @param value        on success, the value of the register at 'offset' + *  @priv:	pointer to &struct lbs_private + *  @reg:	register command, one of CMD_MAC_REG_ACCESS, + *		CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS + *  @offset:	byte offset of the register to get + *  @value:	on success, the value of the register at 'offset'   * - *  @return		0 on success, error code on failure + *  returns:	0 on success, error code on failure  */  int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)  { @@ -860,6 +876,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)  	memset(&cmd, 0, sizeof(cmd));  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_ACT_GET); +	cmd.offset = cpu_to_le16(offset);  	if (reg != CMD_MAC_REG_ACCESS &&  	    reg != CMD_BBP_REG_ACCESS && @@ -869,7 +886,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)  	}  	ret = lbs_cmd_with_response(priv, reg, &cmd); -	if (ret) { +	if (!ret) {  		if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)  			*value = cmd.value.bbp_rf;  		else if (reg == CMD_MAC_REG_ACCESS) @@ -882,15 +899,15 @@ out:  }  /** - *  @brief Write a MAC, Baseband, or RF register + *  lbs_set_reg - Write a MAC, Baseband, or RF register   * - *  @param priv		pointer to struct lbs_private - *  @param cmd		register command, one of CMD_MAC_REG_ACCESS, - *                        CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS - *  @param offset       byte offset of the register to set - *  @param value        the value to write to the register at 'offset' + *  @priv:	pointer to &struct lbs_private + *  @reg:	register command, one of CMD_MAC_REG_ACCESS, + *		CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS + *  @offset:	byte offset of the register to set + *  @value:	the value to write to the register at 'offset'   * - *  @return		0 on success, error code on failure + *  returns:	0 on success, error code on failure  */  int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)  { @@ -902,6 +919,7 @@ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)  	memset(&cmd, 0, sizeof(cmd));  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_ACT_SET); +	cmd.offset = cpu_to_le16(offset);  	if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)  		cmd.value.bbp_rf = (u8) (value & 0xFF); @@ -981,6 +999,8 @@ static void lbs_submit_command(struct lbs_private *priv,  	cmd = cmdnode->cmdbuf;  	spin_lock_irqsave(&priv->driver_lock, flags); +	priv->seqnum++; +	cmd->seqnum = cpu_to_le16(priv->seqnum);  	priv->cur_cmd = cmdnode;  	spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -998,10 +1018,11 @@ static void lbs_submit_command(struct lbs_private *priv,  	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);  	if (ret) { -		lbs_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/4; +		netdev_info(priv->dev, "DNLD_CMD: hw_host_to_card failed: %d\n", +			    ret); +		/* Reset dnld state machine, report failure */ +		priv->dnld_sent = DNLD_RES_RECEIVED; +		lbs_complete_command(priv, cmdnode, ret);  	}  	if (command == CMD_802_11_DEEP_SLEEP) { @@ -1019,7 +1040,7 @@ static void lbs_submit_command(struct lbs_private *priv,  	lbs_deb_leave(LBS_DEB_HOST);  } -/** +/*   *  This function inserts command node to cmdfreeq   *  after cleans it. Requires priv->driver_lock held.   */ @@ -1051,16 +1072,34 @@ static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,  	spin_unlock_irqrestore(&priv->driver_lock, flags);  } -void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, -			  int result) +void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, +			    int result)  { +	/* +	 * Normally, commands are removed from cmdpendingq before being +	 * submitted. However, we can arrive here on alternative codepaths +	 * where the command is still pending. Make sure the command really +	 * isn't part of a list at this point. +	 */ +	list_del_init(&cmd->list); +  	cmd->result = result;  	cmd->cmdwaitqwoken = 1; -	wake_up_interruptible(&cmd->cmdwait_q); +	wake_up(&cmd->cmdwait_q);  	if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)  		__lbs_cleanup_and_insert_cmd(priv, cmd);  	priv->cur_cmd = NULL; +	wake_up(&priv->waitq); +} + +void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, +			  int result) +{ +	unsigned long flags; +	spin_lock_irqsave(&priv->driver_lock, flags); +	__lbs_complete_command(priv, cmd, result); +	spin_unlock_irqrestore(&priv->driver_lock, flags);  }  int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) @@ -1120,12 +1159,29 @@ void lbs_set_mac_control(struct lbs_private *priv)  	lbs_deb_leave(LBS_DEB_CMD);  } +int lbs_set_mac_control_sync(struct lbs_private *priv) +{ +	struct cmd_ds_mac_control cmd; +	int ret = 0; + +	lbs_deb_enter(LBS_DEB_CMD); + +	cmd.hdr.size = cpu_to_le16(sizeof(cmd)); +	cmd.action = cpu_to_le16(priv->mac_control); +	cmd.reserved = 0; +	ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd); + +	lbs_deb_leave(LBS_DEB_CMD); +	return ret; +} +  /** - *  @brief This function allocates the command buffer and link - *  it to command free queue. + *  lbs_allocate_cmd_buffer - allocates the command buffer and links + *  it to command free queue + * + *  @priv:	A pointer to &struct lbs_private structure   * - *  @param priv		A pointer to struct lbs_private structure - *  @return 		0 or -1 + *  returns:	0 for success or -1 on error   */  int lbs_allocate_cmd_buffer(struct lbs_private *priv)  { @@ -1167,10 +1223,11 @@ done:  }  /** - *  @brief This function frees the command buffer. + *  lbs_free_cmd_buffer - free the command buffer   * - *  @param priv		A pointer to struct lbs_private structure - *  @return 		0 or -1 + *  @priv:	A pointer to &struct lbs_private structure + * + *  returns:	0 for success   */  int lbs_free_cmd_buffer(struct lbs_private *priv)  { @@ -1207,11 +1264,13 @@ done:  }  /** - *  @brief This function gets a free command node if available in - *  command free queue. + *  lbs_get_free_cmd_node - gets a free command node if available in + *  command free queue + * + *  @priv:	A pointer to &struct lbs_private structure   * - *  @param priv		A pointer to struct lbs_private structure - *  @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL + *  returns:	A pointer to &cmd_ctrl_node structure on success + *		or %NULL on error   */  static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)  { @@ -1228,7 +1287,7 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)  	if (!list_empty(&priv->cmdfreeq)) {  		tempnode = list_first_entry(&priv->cmdfreeq,  					    struct cmd_ctrl_node, list); -		list_del(&tempnode->list); +		list_del_init(&tempnode->list);  	} else {  		lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");  		tempnode = NULL; @@ -1241,12 +1300,12 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)  }  /** - *  @brief This function executes next command in command - *  pending queue. It will put firmware back to PS mode - *  if applicable. + *  lbs_execute_next_command - execute next command in command + *  pending queue. Will put firmware back to PS mode if applicable. + * + *  @priv:	A pointer to &struct lbs_private structure   * - *  @param priv     A pointer to struct lbs_private structure - *  @return 	   0 or -1 + *  returns:	0 on success or -1 on error   */  int lbs_execute_next_command(struct lbs_private *priv)  { @@ -1263,7 +1322,8 @@ int lbs_execute_next_command(struct lbs_private *priv)  	spin_lock_irqsave(&priv->driver_lock, flags);  	if (priv->cur_cmd) { -		lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n"); +		netdev_alert(priv->dev, +			     "EXEC_NEXT_CMD: already processing command!\n");  		spin_unlock_irqrestore(&priv->driver_lock, flags);  		ret = -1;  		goto done; @@ -1335,10 +1395,7 @@ int lbs_execute_next_command(struct lbs_private *priv)  				    cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {  					lbs_deb_host(  					       "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); -					list_del(&cmdnode->list); -					spin_lock_irqsave(&priv->driver_lock, flags);  					lbs_complete_command(priv, cmdnode, 0); -					spin_unlock_irqrestore(&priv->driver_lock, flags);  					ret = 0;  					goto done; @@ -1348,10 +1405,7 @@ int lbs_execute_next_command(struct lbs_private *priv)  				    (priv->psstate == PS_STATE_PRE_SLEEP)) {  					lbs_deb_host(  					       "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n"); -					list_del(&cmdnode->list); -					spin_lock_irqsave(&priv->driver_lock, flags);  					lbs_complete_command(priv, cmdnode, 0); -					spin_unlock_irqrestore(&priv->driver_lock, flags);  					priv->needtowakeup = 1;  					ret = 0; @@ -1362,7 +1416,9 @@ int lbs_execute_next_command(struct lbs_private *priv)  				       "EXEC_NEXT_CMD: sending EXIT_PS\n");  			}  		} -		list_del(&cmdnode->list); +		spin_lock_irqsave(&priv->driver_lock, flags); +		list_del_init(&cmdnode->list); +		spin_unlock_irqrestore(&priv->driver_lock, flags);  		lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",  			    le16_to_cpu(cmd->command));  		lbs_submit_command(priv, cmdnode); @@ -1425,7 +1481,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)  	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,  		sizeof(confirm_sleep));  	if (ret) { -		lbs_pr_alert("confirm_sleep failed\n"); +		netdev_alert(priv->dev, "confirm_sleep failed\n");  		goto out;  	} @@ -1450,12 +1506,12 @@ out:  }  /** - *  @brief This function checks condition and prepares to - *  send sleep confirm command to firmware if ok. + * lbs_ps_confirm_sleep - checks condition and prepares to + * send sleep confirm command to firmware if ok + * + * @priv:	A pointer to &struct lbs_private structure   * - *  @param priv    	A pointer to struct lbs_private structure - *  @param psmode  	Power Saving mode - *  @return 	   	n/a + * returns:	n/a   */  void lbs_ps_confirm_sleep(struct lbs_private *priv)  { @@ -1495,16 +1551,16 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)  /** - * @brief Configures the transmission power control functionality. + * lbs_set_tpc_cfg - Configures the transmission power control functionality   * - * @param priv		A pointer to struct lbs_private structure - * @param enable	Transmission power control enable - * @param p0		Power level when link quality is good (dBm). - * @param p1		Power level when link quality is fair (dBm). - * @param p2		Power level when link quality is poor (dBm). - * @param usesnr	Use Signal to Noise Ratio in TPC + * @priv:	A pointer to &struct lbs_private structure + * @enable:	Transmission power control enable + * @p0:		Power level when link quality is good (dBm). + * @p1:		Power level when link quality is fair (dBm). + * @p2:		Power level when link quality is poor (dBm). + * @usesnr:	Use Signal to Noise Ratio in TPC   * - * @return 0 on success + * returns:	0 on success   */  int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,  		int8_t p2, int usesnr) @@ -1527,15 +1583,15 @@ int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,  }  /** - * @brief Configures the power adaptation settings. + * lbs_set_power_adapt_cfg - Configures the power adaptation settings   * - * @param priv		A pointer to struct lbs_private structure - * @param enable	Power adaptation enable - * @param p0		Power level for 1, 2, 5.5 and 11 Mbps (dBm). - * @param p1		Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm). - * @param p2		Power level for 48 and 54 Mbps (dBm). + * @priv:	A pointer to &struct lbs_private structure + * @enable:	Power adaptation enable + * @p0:		Power level for 1, 2, 5.5 and 11 Mbps (dBm). + * @p1:		Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm). + * @p2:		Power level for 48 and 54 Mbps (dBm).   * - * @return 0 on Success + * returns:	0 on Success   */  int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, @@ -1589,7 +1645,7 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,  		lbs_deb_host("PREP_CMD: cmdnode is NULL\n");  		/* Wake up main thread to execute next command */ -		wake_up_interruptible(&priv->waitq); +		wake_up(&priv->waitq);  		cmdnode = ERR_PTR(-ENOBUFS);  		goto done;  	} @@ -1600,18 +1656,16 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,  	/* 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++; +	/* Set command, clean result, move to buffer */  	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;  	lbs_deb_host("PREP_CMD: command 0x%04x\n", command);  	cmdnode->cmdwaitqwoken = 0;  	lbs_queue_cmd(priv, cmdnode); -	wake_up_interruptible(&priv->waitq); +	wake_up(&priv->waitq);   done:  	lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode); @@ -1646,12 +1700,18 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,  	}  	might_sleep(); -	wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); + +	/* +	 * Be careful with signals here. A signal may be received as the system +	 * goes into suspend or resume. We do not want this to interrupt the +	 * command, so we perform an uninterruptible sleep. +	 */ +	wait_event(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);  	spin_lock_irqsave(&priv->driver_lock, flags);  	ret = cmdnode->result;  	if (ret) -		lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n", +		netdev_info(priv->dev, "PREP_CMD: command 0x%04x failed: %d\n",  			    command, ret);  	__lbs_cleanup_and_insert_cmd(priv, cmdnode);  | 
