cregit-Linux how code gets into the kernel

Release 4.11 drivers/net/wireless/marvell/libertas/cmd.c

/*
 * 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"
#include "cmd.h"


#define CAL_NF(nf)		((s32)(-(s32)(nf)))

#define CAL_RSSI(snr, nf)	((s32)((s32)(snr) + CAL_NF(nf)))

/**
 * lbs_cmd_copyback - Simple callback that copies response back into command
 *
 * @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
 *
 * returns:     0 on success, error on failure
 */

int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, struct cmd_header *resp) { struct cmd_header *buf = (void *)extra; uint16_t copy_len; copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size)); memcpy(buf, resp, copy_len); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Holger Schurig64100.00%1100.00%
Total64100.00%1100.00%

EXPORT_SYMBOL_GPL(lbs_cmd_copyback); /** * 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. * * @priv: ignored * @extra: ignored * @resp: ignored * * returns: 0 for success */
static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra, struct cmd_header *resp) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Holger Schurig23100.00%1100.00%
Total23100.00%1100.00%

/** * is_command_allowed_in_ps - tests if a command is allowed in Power Save mode * * @cmd: the command ID * * returns: 1 if allowed, 0 if not allowed */
static u8 is_command_allowed_in_ps(u16 cmd) { switch (cmd) { case CMD_802_11_RSSI: return 1; case CMD_802_11_HOST_SLEEP_CFG: return 1; default: break; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Marcelo Tosatti1650.00%133.33%
Dan J Williams1031.25%133.33%
Amitkumar Karwar618.75%133.33%
Total32100.00%3100.00%

/** * lbs_update_hw_spec - Updates the hardware details like MAC address * and regulatory region * * @priv: A pointer to &struct lbs_private structure * * returns: 0 on success, error on failure */
int lbs_update_hw_spec(struct lbs_private *priv) { struct cmd_ds_get_hw_spec cmd; int ret = -1; u32 i; lbs_deb_enter(LBS_DEB_CMD); memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN); ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd); if (ret) goto out; priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo); /* The firmware release is in an interesting format: the patch * level is in the most significant nibble ... so fix that: */ priv->fwrelease = le32_to_cpu(cmd.fwrelease); priv->fwrelease = (priv->fwrelease << 8) | (priv->fwrelease >> 24 & 0xff); /* Some firmware capabilities: * CF card firmware 5.0.16p0: cap 0x00000303 * USB dongle firmware 5.110.17p2: cap 0x00000303 */ netdev_info(priv->dev, "%pM, fw %u.%u.%up%u, cap 0x%08x\n", cmd.permanentaddr, priv->fwrelease >> 24 & 0xff, priv->fwrelease >> 16 & 0xff, priv->fwrelease >> 8 & 0xff, priv->fwrelease & 0xff, priv->fwcapinfo); lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", cmd.hwifversion, cmd.version); /* Clamp region code to 8-bit since FW spec indicates that it should * only ever be 8-bit, even though the field size is 16-bit. Some firmware * returns non-zero high 8 bits here. * * Firmware version 4.0.102 used in CF8381 has region code shifted. We * need to check for this problem and handle it properly. */ if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V4) priv->regioncode = (le16_to_cpu(cmd.regioncode) >> 8) & 0xFF; else priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF; for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { /* use the region code to search for the index */ if (priv->regioncode == lbs_region_code_to_index[i]) break; } /* if it's unidentified region code, use the default (USA) */ if (i >= MRVDRV_MAX_REGION_CODE) { priv->regioncode = 0x10; 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); 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); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams20956.03%19.09%
Holger Schurig6617.69%436.36%
Marcelo Tosatti4110.99%19.09%
Marek Vašut308.04%19.09%
Vasily Khoruzhick154.02%19.09%
Joe Perches102.68%19.09%
Johannes Berg10.27%19.09%
David Woodhouse10.27%19.09%
Total373100.00%11100.00%


static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy, struct cmd_header *resp) { lbs_deb_enter(LBS_DEB_CMD); if (priv->is_host_sleep_activated) { priv->is_host_sleep_configured = 0; if (priv->psstate == PS_STATE_FULL_POWER) { priv->is_host_sleep_activated = 0; wake_up_interruptible(&priv->host_sleep_q); } } else { priv->is_host_sleep_configured = 1; } lbs_deb_leave(LBS_DEB_CMD); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Amitkumar Karwar80100.00%2100.00%
Total80100.00%2100.00%


int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, struct wol_config *p_wol_config) { struct cmd_ds_host_sleep cmd_config; int ret; /* * Certain firmware versions do not support EHS_REMOVE_WAKEUP command * and the card will return a failure. Since we need to be * able to reset the mask, in those cases we set a 0 mask instead. */ if (criteria == EHS_REMOVE_WAKEUP && !priv->ehs_remove_supported) criteria = 0; cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config)); cmd_config.criteria = cpu_to_le32(criteria); cmd_config.gpio = priv->wol_gpio; cmd_config.gap = priv->wol_gap; if (p_wol_config != NULL) memcpy((uint8_t *)&cmd_config.wol_conf, (uint8_t *)p_wol_config, sizeof(struct wol_config)); else cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE; ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr, le16_to_cpu(cmd_config.hdr.size), lbs_ret_host_sleep_cfg, 0); if (!ret) { if (p_wol_config) memcpy((uint8_t *) p_wol_config, (uint8_t *)&cmd_config.wol_conf, sizeof(struct wol_config)); } else { netdev_info(priv->dev, "HOST_SLEEP_CFG failed %d\n", ret); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse8743.94%450.00%
Anna Neal7336.87%112.50%
Amitkumar Karwar178.59%112.50%
Deepak Saxena168.08%112.50%
Joe Perches52.53%112.50%
Total198100.00%8100.00%

EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); /** * lbs_set_ps_mode - Sets the Power Save mode * * @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) * @block: Whether to block on a response or not * * returns: 0 on success, error on failure */
int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block) { struct cmd_ds_802_11_ps_mode cmd; int ret = 0; lbs_deb_enter(LBS_DEB_CMD); memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(cmd_action); if (cmd_action == PS_MODE_ACTION_ENTER_PS) { lbs_deb_cmd("PS_MODE: action ENTER_PS\n"); cmd.multipledtim = cpu_to_le16(1); /* Default DTIM multiple */ } else if (cmd_action == PS_MODE_ACTION_EXIT_PS) { lbs_deb_cmd("PS_MODE: action EXIT_PS\n"); } else { /* We don't handle CONFIRM_SLEEP here because it needs to * be fastpathed to the firmware. */ lbs_deb_cmd("PS_MODE: unknown action 0x%X\n", cmd_action); ret = -EOPNOTSUPP; goto out; } if (block) ret = lbs_cmd_with_response(priv, CMD_802_11_PS_MODE, &cmd); else lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd)); out: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams10159.41%116.67%
Marcelo Tosatti5632.94%116.67%
Holger Schurig127.06%350.00%
David Woodhouse10.59%116.67%
Total170100.00%6100.00%


int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, struct sleep_params *sp) { struct cmd_ds_802_11_sleep_params cmd; int ret; lbs_deb_enter(LBS_DEB_CMD); if (cmd_action == CMD_ACT_GET) { memset(&cmd, 0, sizeof(cmd)); } else { cmd.error = cpu_to_le16(sp->sp_error); cmd.offset = cpu_to_le16(sp->sp_offset); cmd.stabletime = cpu_to_le16(sp->sp_stabletime); cmd.calcontrol = sp->sp_calcontrol; cmd.externalsleepclk = sp->sp_extsleepclk; cmd.reserved = cpu_to_le16(sp->sp_reserved); } cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(cmd_action); ret = lbs_cmd_with_response(priv, CMD_802_11_SLEEP_PARAMS, &cmd); if (!ret) { lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, " "calcontrol 0x%x extsleepclk 0x%x\n", le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset), le16_to_cpu(cmd.stabletime), cmd.calcontrol, cmd.externalsleepclk); sp->sp_error = le16_to_cpu(cmd.error); sp->sp_offset = le16_to_cpu(cmd.offset); sp->sp_stabletime = le16_to_cpu(cmd.stabletime); sp->sp_calcontrol = cmd.calcontrol; sp->sp_extsleepclk = cmd.externalsleepclk; sp->sp_reserved = le16_to_cpu(cmd.reserved); } lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse15558.94%114.29%
Marcelo Tosatti9536.12%114.29%
Holger Schurig114.18%342.86%
Dan J Williams10.38%114.29%
Pan Bian10.38%114.29%
Total263100.00%7100.00%


static int lbs_wait_for_ds_awake(struct lbs_private *priv) { int ret = 0; lbs_deb_enter(LBS_DEB_CMD); if (priv->is_deep_sleep) { if (!wait_event_interruptible_timeout(priv->ds_awake_q, !priv->is_deep_sleep, (10 * HZ))) { netdev_err(priv->dev, "ds_awake_q: timer expired\n"); ret = -1; } } lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Amitkumar Karwar7393.59%150.00%
Joe Perches56.41%150.00%
Total78100.00%2100.00%


int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) { int ret = 0; lbs_deb_enter(LBS_DEB_CMD); if (deep_sleep) { if (priv->is_deep_sleep != 1) { lbs_deb_cmd("deep sleep: sleep\n"); BUG_ON(!priv->enter_deep_sleep); ret = priv->enter_deep_sleep(priv); if (!ret) { netif_stop_queue(priv->dev); netif_carrier_off(priv->dev); } } else { netdev_err(priv->dev, "deep sleep: already enabled\n"); } } else { if (priv->is_deep_sleep) { lbs_deb_cmd("deep sleep: wakeup\n"); BUG_ON(!priv->exit_deep_sleep); ret = priv->exit_deep_sleep(priv); if (!ret) { ret = lbs_wait_for_ds_awake(priv); if (ret) netdev_err(priv->dev, "deep sleep: wakeup failed\n"); } } } lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Amitkumar Karwar15593.37%133.33%
Joe Perches116.63%266.67%
Total166100.00%3100.00%


static int lbs_ret_host_sleep_activate(struct lbs_private *priv, unsigned long dummy, struct cmd_header *cmd) { lbs_deb_enter(LBS_DEB_FW); priv->is_host_sleep_activated = 1; wake_up_interruptible(&priv->host_sleep_q); lbs_deb_leave(LBS_DEB_FW); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Amitkumar Karwar47100.00%1100.00%
Total47100.00%1100.00%


int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep) { struct cmd_header cmd; int ret = 0; uint32_t criteria = EHS_REMOVE_WAKEUP; lbs_deb_enter(LBS_DEB_CMD); if (host_sleep) { if (priv->is_host_sleep_activated != 1) { memset(&cmd, 0, sizeof(cmd)); ret = lbs_host_sleep_cfg(priv, priv->wol_criteria, (struct wol_config *)NULL); if (ret) { netdev_info(priv->dev, "Host sleep configuration failed: %d\n", ret); return ret; } if (priv->psstate == PS_STATE_FULL_POWER) { ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, sizeof(cmd), lbs_ret_host_sleep_activate, 0); if (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))) { netdev_err(priv->dev, "host_sleep_q: timer expired\n"); ret = -1; } } else { netdev_err(priv->dev, "host sleep: already enabled\n"); } } else { if (priv->is_host_sleep_activated) ret = lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Amitkumar Karwar19990.05%133.33%
Joe Perches229.95%266.67%
Total221100.00%3100.00%

/** * lbs_set_snmp_mib - Set an SNMP MIB value * * @priv: A pointer to &struct lbs_private structure * @oid: The OID to set in the firmware * @val: Value to set the OID to * * returns: 0 on success, error on failure */
int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val) { struct cmd_ds_802_11_snmp_mib cmd; int ret; lbs_deb_enter(LBS_DEB_CMD); memset(&cmd, 0, sizeof (cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); cmd.oid = cpu_to_le16((u16) oid); switch (oid) { case SNMP_MIB_OID_BSS_TYPE: cmd.bufsize = cpu_to_le16(sizeof(u8)); cmd.value[0] = val; break; case SNMP_MIB_OID_11D_ENABLE: case SNMP_MIB_OID_FRAG_THRESHOLD: case SNMP_MIB_OID_RTS_THRESHOLD: case SNMP_MIB_OID_SHORT_RETRY_LIMIT: case SNMP_MIB_OID_LONG_RETRY_LIMIT: cmd.bufsize = cpu_to_le16(sizeof(u16)); *((__le16 *)(&cmd.value)) = cpu_to_le16(val); break; default: lbs_deb_cmd("SNMP_CMD: (set) unhandled OID 0x%x\n", oid); ret = -EINVAL; goto out; } lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n", le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val); ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd); out: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Holger Schurig11753.92%675.00%
Marcelo Tosatti7032.26%112.50%
David Woodhouse3013.82%112.50%
Total217100.00%8100.00%

/** * lbs_get_snmp_mib - Get an SNMP MIB value * * @priv: A pointer to &struct lbs_private structure * @oid: The OID to retrieve from the firmware * @out_val: Location for the returned value * * returns: 0 on success, error on failure */
int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val) { struct cmd_ds_802_11_snmp_mib cmd; int ret; lbs_deb_enter(LBS_DEB_CMD); memset(&cmd, 0, sizeof (cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_GET); cmd.oid = cpu_to_le16(oid); ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd); if (ret) goto out; switch (le16_to_cpu(cmd.bufsize)) { case sizeof(u8): *out_val = cmd.value[0]; break; case sizeof(u16): *out_val = le16_to_cpu(*((__le16 *)(&cmd.value))); break; default: lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n", oid, le16_to_cpu(cmd.bufsize)); break; } out: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Holger Schurig8849.44%545.45%
Marcelo Tosatti4324.16%19.09%
David Woodhouse3419.10%218.18%
Dan J Williams105.62%218.18%
Javier Cardona31.69%19.09%
Total178100.00%11100.00%

/** * lbs_get_tx_power - Get the min, max, and current TX power * * @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) * * returns: 0 on success, error on failure */
int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, s16 *maxlevel) { struct cmd_ds_802_11_rf_tx_power cmd; int ret; lbs_deb_enter(LBS_DEB_CMD); memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_GET); ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd); if (ret == 0) { *curlevel = le16_to_cpu(cmd.curlevel); if (minlevel) *minlevel = cmd.minlevel; if (maxlevel) *maxlevel = cmd.maxlevel; } lbs_deb_leave(LBS_DEB_CMD); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Holger Schurig6146.92%555.56%
Javier Cardona3728.46%111.11%
Marcelo Tosatti2720.77%111.11%
David Woodhouse53.85%222.22%
Total130100.00%9100.00%

/** * lbs_set_tx_power - Set the TX power * * @priv: A pointer to &struct lbs_private structure * @dbm: The desired power level in dBm * * returns: 0 on success, error on failure */
int lbs_set_tx_power(struct lbs_private *priv, s16 dbm) { struct cmd_ds_802_11_rf_tx_power cmd; int ret; lbs_deb_enter(LBS_DEB_CMD); memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); cmd.curlevel = cpu_to_le16(dbm); lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm); ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd); lbs_deb_leave(LBS_DEB_CMD); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams4849.48%133.33%
Marcelo Tosatti2626.80%133.33%
Holger Schurig2323.71%133.33%
Total97100.00%3100.00%

/** * lbs_set_monitor_mode - Enable or disable monitor mode * (only implemented on OLPC usb8388 FW) * * @priv: A pointer to &struct lbs_private structure * @enable: 1 to enable monitor mode, 0 to disable * * returns: 0 on success, error on failure */
int lbs_set_monitor_mode(struct lbs_private *priv, int enable) { struct cmd_ds_802_11_monitor_mode cmd; int ret; memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); if (enable) cmd.mode = cpu_to_le16(0x1); lbs_deb_cmd("SET_MONITOR_MODE: %d\n", enable); ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd); if (ret == 0) { priv->dev->type = enable ? ARPHRD_IEEE80211_RADIOTAP : ARPHRD_ETHER; } lbs_deb_leave(LBS_DEB_CMD); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams8371.55%233.33%
Holger Schurig2723.28%350.00%
Marcelo Tosatti65.17%116.67%
Total116100.00%6100.00%

/** * lbs_get_channel - Get the radio channel * * @priv: A pointer to &struct lbs_private structure * * returns: The channel on success, error on failure */
static int lbs_get_channel(struct lbs_private *priv) { struct cmd_ds_802_11_rf_channel cmd; int ret = 0; lbs_deb_enter(LBS_DEB_CMD); memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET); ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); if (ret) goto out; ret = le16_to_cpu(cmd.channel); lbs_deb_cmd("current radio channel is %d\n", ret); out: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams5852.73%222.22%
Marcelo Tosatti3027.27%111.11%
Holger Schurig2119.09%555.56%
David Woodhouse10.91%111.11%
Total110100.00%9100.00%


int lbs_update_channel(struct lbs_private *priv) { int ret; /* the channel in f/w could be out of sync; get the current channel */ lbs_deb_enter(LBS_DEB_ASSOC); ret = lbs_get_channel(priv); if (ret > 0) { priv->channel = ret; ret = 0; } lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Holger Schurig56100.00%1100.00%
Total56100.00%1100.00%

/** * lbs_set_channel - Set the radio channel * * @priv: A pointer to &struct lbs_private structure * @channel: The desired channel, or 0 to clear a locked channel * * returns: 0 on success, error on failure */
int lbs_set_channel(struct lbs_private *priv, u8 channel) { struct cmd_ds_802_11_rf_channel cmd; #ifdef DEBUG u8 old_channel = priv->channel; #endif int ret = 0; lbs_deb_enter(LBS_DEB_CMD); memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET); cmd.channel = cpu_to_le16(channel); ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); if (ret) goto out; priv->channel = (uint8_t) le16_to_cpu(cmd.channel); lbs_deb_cmd("channel switch from %d to %d\n", old_channel, priv->channel); out: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams10976.76%228.57%
Holger Schurig1711.97%228.57%
Marcelo Tosatti107.04%114.29%
Manish Katiyar53.52%114.29%
David Woodhouse10.70%114.29%
Total142100.00%7100.00%

/** * lbs_get_rssi - Get current RSSI and noise floor * * @priv: A pointer to &struct lbs_private structure * @rssi: On successful return, signal level in mBm * @nf: On successful return, Noise floor * * returns: The channel on success, error on failure */
int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf) { struct cmd_ds_802_11_rssi cmd; int ret = 0; lbs_deb_enter(LBS_DEB_CMD); BUG_ON(rssi == NULL); BUG_ON(nf == NULL); memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); /* Average SNR over last 8 beacons */ cmd.n_or_snr = cpu_to_le16(8); ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd); if (ret == 0) { *nf = CAL_NF(le16_to_cpu(cmd.nf)); *rssi = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), le16_to_cpu(cmd.nf)); } lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams148100.00%1100.00%
Total148100.00%1100.00%

/** * lbs_set_11d_domain_info - Send regulatory and 802.11d domain information * to the firmware * * @priv: pointer to &struct lbs_private * * returns: 0 on success, error code on failure */
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; enum nl80211_band band; struct ieee80211_channel *ch; u8 num_triplet = 0; u8 num_parsed_chan = 0; u8 first_channel = 0, next_chan = 0, max_pwr = 0; u8 i, flag = 0; size_t triplet_size; 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", priv->country_code[0], priv->country_code[1]); domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); /* Set country code */ 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 * and doesn't validate channel numbers and spans; hence it would * interpret a triplet of (36, 4, 20) as channels 36, 37, 38, 39. Since * the last 3 aren't valid channels, the driver is responsible for * splitting that up into 4 triplet pairs of (36, 1, 20) + (40, 1, 20) * etc. */ for (band = 0; (band < NUM_NL80211_BANDS) && (num_triplet < MAX_11D_TRIPLETS); band++) { if (!bands[band]) continue; for (i = 0; (i < bands[band]->n_channels) && (num_triplet < MAX_11D_TRIPLETS); i++) { ch = &bands[band]->channels[i]; if (ch->flags & IEEE80211_CHAN_DISABLED) continue; if (!flag) { flag = 1; next_chan = first_channel = (u32) ch->hw_value; max_pwr = ch->max_power; num_parsed_chan = 1; continue; } if ((ch->hw_value == next_chan + 1) && (ch->max_power == max_pwr)) { /* Consolidate adjacent channels */ next_chan++; num_parsed_chan++; } else { /* Add this triplet */ lbs_deb_11d("11D triplet (%d, %d, %d)\n", first_channel, num_parsed_chan, max_pwr); t = &domain->triplet[num_triplet]; t->chans.first_channel = first_channel; t->chans.num_channels = num_parsed_chan; t->chans.max_power = max_pwr; num_triplet++; flag = 0; } } if (flag) { /* Add last triplet */ lbs_deb_11d("11D triplet (%d, %d, %d)\n", first_channel, num_parsed_chan, max_pwr); t = &domain->triplet[num_triplet]; t->chans.first_channel = first_channel; t->chans.num_channels = num_parsed_chan; t->chans.max_power = max_pwr; num_triplet++; } } lbs_deb_11d("# triplets %d\n", num_triplet); /* Set command header sizes */ triplet_size = num_triplet * sizeof(struct ieee80211_country_ie_triplet); domain->header.len = cpu_to_le16(sizeof(domain->country_code) + triplet_size); lbs_deb_hex(LBS_DEB_11D, "802.11D domain param set", (u8 *) &cmd.domain.country_code, le16_to_cpu(domain->header.len)); cmd.hdr.size = cpu_to_le16(sizeof(cmd.hdr) + sizeof(cmd.action) + sizeof(cmd.domain.header) + sizeof(cmd.domain.country_code) + triplet_size); 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; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams55092.75%133.33%
Daniel Drake416.91%133.33%
Johannes Berg20.34%133.33%
Total593100.00%3100.00%

/** * lbs_get_reg - Read a MAC, Baseband, or RF register * * @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' * * returns: 0 on success, error code on failure */
int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value) { struct cmd_ds_reg_access cmd; int ret = 0; lbs_deb_enter(LBS_DEB_CMD); BUG_ON(value == NULL); 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 && reg != CMD_RF_REG_ACCESS) { ret = -EINVAL; goto out; } ret = lbs_cmd_with_response(priv, reg, &cmd); 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) *value = le32_to_cpu(cmd.value.mac); } out: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams12569.06%114.29%
Marcelo Tosatti3820.99%114.29%
Olivier Sobrie105.52%114.29%
Holger Schurig84.42%457.14%
Total181100.00%7100.00%

/** * lbs_set_reg - Write a MAC, Baseband, or RF register * * @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' * * returns: 0 on success, error code on failure */
int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value) { struct cmd_ds_reg_access cmd; int ret = 0; lbs_deb_enter(LBS_DEB_CMD); 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); else if (reg == CMD_MAC_REG_ACCESS) cmd.value.mac = cpu_to_le32(value); else { ret = -EINVAL; goto out; } ret = lbs_cmd_with_response(priv, reg, &cmd); out: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams10667.09%120.00%
Marcelo Tosatti3824.05%120.00%
Olivier Sobrie95.70%120.00%
Holger Schurig53.16%240.00%
Total158100.00%5100.00%


static void lbs_queue_cmd(struct lbs_private *priv, struct cmd_ctrl_node *cmdnode) { unsigned long flags; int addtail = 1; lbs_deb_enter(LBS_DEB_HOST); if (!cmdnode) { lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n"); goto done; } if (!cmdnode->cmdbuf->size) { lbs_deb_host("DNLD_CMD: cmd size is zero\n"); goto done; } cmdnode->result = 0; /* Exit_PS command needs to be queued in the header always. */ if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) { struct cmd_ds_802_11_ps_mode *psm = (void *)cmdnode->cmdbuf; if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) { if (priv->psstate != PS_STATE_FULL_POWER) addtail = 0; } } if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_WAKEUP_CONFIRM) addtail = 0; spin_lock_irqsave(&priv->driver_lock, flags); if (addtail) list_add_tail(&cmdnode->list, &priv->cmdpendingq); else list_add(&cmdnode->list, &priv->cmdpendingq); spin_unlock_irqrestore(&priv->driver_lock, flags); lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n", le16_to_cpu(cmdnode->cmdbuf->command)); done: lbs_deb_leave(LBS_DEB_HOST); }

Contributors

PersonTokensPropCommitsCommitProp
Marcelo Tosatti11754.93%15.88%
David Woodhouse4521.13%635.29%
Amitkumar Karwar177.98%15.88%
Holger Schurig167.51%529.41%
Dan J Williams125.63%317.65%
Li Zefan62.82%15.88%
Total213100.00%17100.00%


static void lbs_submit_command(struct lbs_private *priv, struct cmd_ctrl_node *cmdnode) { unsigned long flags; struct cmd_header *cmd; uint16_t cmdsize; uint16_t command; int timeo = 3 * HZ; int ret; lbs_deb_enter(LBS_DEB_HOST); 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); cmdsize = le16_to_cpu(cmd->size); command = le16_to_cpu(cmd->command); /* These commands take longer */ if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE) timeo = 5 * HZ; lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n", command, le16_to_cpu(cmd->seqnum), cmdsize); lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); if (ret) { 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) { if (priv->is_auto_deep_sleep_enabled) { priv->wakeup_dev_required = 1; priv->dnld_sent = 0; } priv->is_deep_sleep = 1; lbs_complete_command(priv, cmdnode, 0); } else { /* Setup the timer after transmit command */ mod_timer(&priv->command_timer, jiffies + timeo); } lbs_deb_leave(LBS_DEB_HOST); }

Contributors

PersonTokensPropCommitsCommitProp
Marcelo Tosatti10035.97%15.26%
David Woodhouse4616.55%421.05%
Amitkumar Karwar4616.55%15.26%
Holger Schurig3914.03%947.37%
Daniel Drake3010.79%210.53%
Dan J Williams124.32%15.26%
Joe Perches51.80%15.26%
Total278100.00%19100.00%

/* * This function inserts command node to cmdfreeq * after cleans it. Requires priv->driver_lock held. */
static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv, struct cmd_ctrl_node *cmdnode) { lbs_deb_enter(LBS_DEB_HOST); if (!cmdnode) goto out; cmdnode->callback = NULL; cmdnode->callback_arg = 0; memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE); list_add_tail(&cmdnode->list, &priv->cmdfreeq); out: lbs_deb_leave(LBS_DEB_HOST); }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse4055.56%342.86%
Marcelo Tosatti2636.11%114.29%
Li Zefan34.17%114.29%
Holger Schurig34.17%228.57%
Total72100.00%7100.00%


static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv, struct cmd_ctrl_node *ptempcmd) { unsigned long flags; spin_lock_irqsave(&priv->driver_lock, flags); __lbs_cleanup_and_insert_cmd(priv, ptempcmd); spin_unlock_irqrestore(&priv->driver_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams2042.55%225.00%
Marcelo Tosatti1429.79%112.50%
Holger Schurig714.89%450.00%
David Woodhouse612.77%112.50%
Total47100.00%8100.00%


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(&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); }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams3644.44%112.50%
Daniel Drake2024.69%225.00%
Holger Schurig1518.52%450.00%
Marcelo Tosatti1012.35%112.50%
Total81100.00%8100.00%


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); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Drake5098.04%150.00%
Marcelo Tosatti11.96%150.00%
Total51100.00%2100.00%


int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) { struct cmd_ds_802_11_radio_control cmd; int ret = -EINVAL; lbs_deb_enter(LBS_DEB_CMD); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); cmd.control = 0; /* Only v8 and below support setting the preamble */ if (priv->fwrelease < 0x09000000) { switch (preamble) { case RADIO_PREAMBLE_SHORT: case RADIO_PREAMBLE_AUTO: case RADIO_PREAMBLE_LONG: cmd.control = cpu_to_le16(preamble); break; default: goto out; } } if (radio_on) cmd.control |= cpu_to_le16(0x1); else { cmd.control &= cpu_to_le16(~0x1); priv->txpower_cur = 0; } lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n", radio_on ? "ON" : "OFF", preamble); priv->radio_on = radio_on; ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd); out: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams11263.28%133.33%
Kiran Divekar5933.33%133.33%
Rickard Strandqvist63.39%133.33%
Total177100.00%3100.00%


void lbs_set_mac_control(struct lbs_private *priv) { struct cmd_ds_mac_control cmd; 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; lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd)); lbs_deb_leave(LBS_DEB_CMD); }

Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams3954.17%150.00%
Kiran Divekar3345.83%150.00%
Total72100.00%2100.00%


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; }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Drake75100.00%1100.00%
Total75100.00%1100.00%

/** * lbs_allocate_cmd_buffer - allocates the command buffer and links * it to command free queue * * @priv: A pointer to &struct lbs_private structure * * returns: 0 for success or -1 on error */
int lbs_allocate_cmd_buffer(struct lbs_private *priv) { int ret = 0; u32 bufsize; u32 i; struct cmd_ctrl_node *cmdarray; lbs_deb_enter(LBS_DEB_HOST); /* Allocate and initialize the command array */ bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS; if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) { lbs_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) { lbs_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); lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]); } ret = 0; done: lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Marcelo Tosatti13471.66%112.50%
Dan J Williams3016.04%112.50%
Holger Schurig2211.76%562.50%
David Woodhouse10.53%112.50%
Total187100.00%8100.00%

/** * lbs_free_cmd_buffer - free the command buffer * * @priv: A pointer to &struct lbs_private structure * * returns: 0 for success */
int lbs_free_cmd_buffer(struct lbs_private *priv) { struct cmd_ctrl_node *cmdarray; unsigned int i; lbs_deb_enter(LBS_DEB_HOST); /* need to check if cmd array is allocated or not */ if (priv->cmd_array == NULL) { lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n"); goto done; } cmdarray = priv->cmd_array; /* Release shared memory buffers */ for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { if (cmdarray[i].cmdbuf) { kfree(cmdarray[i].cmdbuf); cmdarray[i].cmdbuf = NULL; } } /* Release cmd_ctrl_node */ if (priv->cmd_array) { kfree(priv->cmd_array); priv->cmd_array = NULL; } done: lbs_deb_leave(LBS_DEB_HOST); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Marcelo Tosatti9776.38%114.29%
Holger Schurig1310.24%457.14%
Dan J Williams129.45%114.29%
David Woodhouse53.94%114.29%
Total127100.00%7100.00%

/** * lbs_get_free_cmd_node - gets a free command node if available in * command free queue * * @priv: A pointer to &struct lbs_private structure * * 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) { struct cmd_ctrl_node *tempnode; unsigned long flags; lbs_deb_enter(LBS_DEB_HOST); if (!priv) return NULL; spin_lock_irqsave(&priv->driver_lock, flags); if (!list_empty(&priv->cmdfreeq)) { tempnode = list_first_entry(&priv->cmdfreeq, struct cmd_ctrl_node, list); list_del_init(&tempnode->list); } else { lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n"); tempnode = NULL; } spin_unlock_irqrestore(&priv->driver_lock, flags); lbs_deb_leave(LBS_DEB_HOST); return tempnode; }

Contributors

PersonTokensPropCommitsCommitProp
Marcelo Tosatti7870.27%111.11%
Holger Schurig1311.71%333.33%
Li Zefan1210.81%111.11%
David Woodhouse65.41%222.22%
Dan J Williams10.90%111.11%
Daniel Drake10.90%111.11%
Total111100.00%9100.00%

/** * 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 * * returns: 0 on success or -1 on error */
int lbs_execute_next_command(struct lbs_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 * only caller to us is lbs_thread() and we get even when a * data packet is received */ lbs_deb_enter(LBS_DEB_THREAD); spin_lock_irqsave(&priv->driver_lock, flags); if (priv->cur_cmd) { netdev_alert(priv->dev, "EXEC_NEXT_CMD: already processing command!\n"); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; } if (!list_empty(&priv->cmdpendingq)) { cmdnode = list_first_entry(&priv->cmdpendingq, struct cmd_ctrl_node, list); } spin_unlock_irqrestore(&priv->driver_lock, flags); if (cmdnode) { cmd = cmdnode->cmdbuf; if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) { if ((priv->psstate == PS_STATE_SLEEP) || (priv->psstate == PS_STATE_PRE_SLEEP)) { lbs_deb_host( "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n", le16_to_cpu(cmd->command), priv->psstate); ret = -1; goto done; } lbs_deb_host("EXEC_NEXT_CMD: OK to send command " "0x%04x in psstate %d\n", le16_to_cpu(cmd->command), priv->psstate); } else if (priv->psstate != PS_STATE_FULL_POWER) { /* * 1. Non-PS command: * Queue it. set needtowakeup to TRUE if current state * is SLEEP, otherwise call send EXIT_PS. * 2. PS command but not EXIT_PS: * Ignore it. * 3. PS command EXIT_PS: * Set needtowakeup to TRUE if current state is SLEEP, * otherwise send this command down to firmware * immediately. */ if (cmd->command != cpu_to_le16(CMD_802_11_PS_MODE)) { /* Prepare to send Exit PS, * this non PS command will be sent later */ if ((priv->psstate == PS_STATE_SLEEP) || (priv->psstate == PS_STATE_PRE_SLEEP) ) { /* w/ new scheme, it will not reach here. since it is blocked in main_thread. */ priv->needtowakeup = 1; } else { lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false); } ret = 0; goto done; } else { /* * PS command. Ignore it if it is not Exit_PS. * otherwise send it down immediately. */ struct cmd_ds_802_11_ps_mode *psm = (void *)cmd; lbs_deb_host( "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n", psm->action); if (psm->action != cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) { lbs_deb_host( "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); lbs_complete_command(priv, cmdnode, 0); ret = 0; goto done; } if ((priv->psstate == PS_STATE_SLEEP) || (priv->psstate == PS_STATE_PRE_SLEEP)) { lbs_deb_host( "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n"); lbs_complete_command(priv, cmdnode, 0); priv->needtowakeup = 1; ret = 0; goto done; } lbs_deb_host( "EXEC_NEXT_CMD: sending EXIT_PS\n"); } } 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); } else { /* * check if in power save mode, if yes, put the device back * to PS mode */ if ((priv->psmode != LBS802_11POWERMODECAM) && (priv->psstate == PS_STATE_FULL_POWER) && (priv->connect_status == LBS_CONNECTED)) { lbs_deb_host( "EXEC_NEXT_CMD: cmdpendingq empty, go back to PS_SLEEP"); lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS, false); } } ret = 0; done: lbs_deb_leave(LBS_DEB_THREAD); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Marcelo Tosatti35771.98%15.26%
David Woodhouse408.06%421.05%
Dan J Williams357.06%526.32%
Holger Schurig255.04%421.05%
Paul Fox204.03%15.26%
Li Zefan122.42%15.26%
Joe Perches51.01%15.26%
Andreas Kemnade10.20%15.26%
Daniel Drake10.20%15.26%
Total496100.00%19100.00%


static void lbs_send_confirmsleep(struct lbs_private *priv) { unsigned long flags; int ret; lbs_deb_enter(LBS_DEB_HOST); lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep, sizeof(confirm_sleep)); ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, sizeof(confirm_sleep)); if (ret) { netdev_alert(priv->dev, "confirm_sleep failed\n"); goto out; } spin_lock_irqsave(&priv->driver_lock, flags); /* We don't get a response on the sleep-confirmation */ priv->dnld_sent = DNLD_RES_RECEIVED; if (priv->is_host_sleep_configured) { priv->is_host_sleep_activated = 1; wake_up_interruptible(&priv->host_sleep_q); } /* If nothing to do, go back to sleep (?) */ if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) priv->psstate = PS_STATE_SLEEP; spin_unlock_irqrestore(&priv->driver_lock, flags); out: lbs_deb_leave(LBS_DEB_HOST); }

Contributors

PersonTokensPropCommitsCommitProp
Marcelo Tosatti7142.51%16.67%
Holger Schurig6337.72%960.00%
Amitkumar Karwar2213.17%16.67%
Joe Perches52.99%16.67%
David Woodhouse42.40%16.67%
Stefani Seibold21.20%213.33%
Total167100.00%15100.00%

/** * 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 * * returns: n/a */
void lbs_ps_confirm_sleep(struct lbs_private *priv) { unsigned long flags =0; int allowed = 1; lbs_deb_enter(LBS_DEB_HOST); spin_lock_irqsave(&priv->driver_lock, flags); if (priv->dnld_sent) { allowed = 0; lbs_deb_host("dnld_sent was set\n"); } /* In-progress command? */ if (priv->cur_cmd) { allowed = 0; lbs_deb_host("cur_cmd was set\n"); } /* Pending events or command responses? */ if (kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) { allowed = 0; lbs_deb_host("pending events or command responses\n"); } spin_unlock_irqrestore(&priv->driver_lock, flags); if (allowed) { lbs_deb_host("sending lbs_ps_confirm_sleep\n"); lbs_send_confirmsleep(priv); } else { lbs_deb_host("sleep confirm has been delayed\n"); } lbs_deb_leave(LBS_DEB_HOST); }

Contributors

PersonTokensPropCommitsCommitProp
Marcelo Tosatti8963.12%17.69%
Holger Schurig4531.91%861.54%
David Woodhouse53.55%215.38%
Stefani Seibold21.42%215.38%
Total141100.00%13100.00%

/** * lbs_set_tpc_cfg - Configures the transmission power control functionality * * @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 * * 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) { struct cmd_ds_802_11_tpc_cfg cmd; int ret; memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); cmd.enable = !!enable; cmd.usesnr = !!usesnr; cmd.P0 = p0; cmd.P1 = p1; cmd.P2 = p2; ret = lbs_cmd_with_response(priv, CMD_802_11_TPC_CFG, &cmd); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Anna Neal117100.00%2100.00%
Total117100.00%2100.00%

/** * lbs_set_power_adapt_cfg - Configures the power adaptation settings * * @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). * * returns: 0 on Success */
int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, int8_t p2) { struct cmd_ds_802_11_pa_cfg cmd; int ret; memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); cmd.enable = !!enable; cmd.P0 = p0; cmd.P1 = p1; cmd.P2 = p2; ret = lbs_cmd_with_response(priv, CMD_802_11_PA_CFG , &cmd); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Anna Neal106100.00%1100.00%
Total106100.00%1100.00%


struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), unsigned long callback_arg) { struct cmd_ctrl_node *cmdnode; lbs_deb_enter(LBS_DEB_HOST); if (priv->surpriseremoved) { lbs_deb_host("PREP_CMD: card removed\n"); cmdnode = ERR_PTR(-ENOENT); goto done; } /* No commands are allowed in Deep Sleep until we toggle the GPIO * to wake up the card and it has signaled that it's ready. */ if (!priv->is_auto_deep_sleep_enabled) { if (priv->is_deep_sleep) { lbs_deb_cmd("command not allowed in deep sleep\n"); cmdnode = ERR_PTR(-EBUSY); goto done; } } cmdnode = lbs_get_free_cmd_node(priv); if (cmdnode == NULL) { lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); /* Wake up main thread to execute next command */ wake_up(&priv->waitq); cmdnode = ERR_PTR(-ENOBUFS); goto done; } cmdnode->callback = callback; cmdnode->callback_arg = callback_arg; /* Copy the incoming command to the buffer */ memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size); /* Set command, clean result, move to buffer */ cmdnode->cmdbuf->command = cpu_to_le16(command); cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size); cmdnode->cmdbuf->result = 0; lbs_deb_host("PREP_CMD: command 0x%04x\n", command); cmdnode->cmdwaitqwoken = 0; lbs_queue_cmd(priv, cmdnode); wake_up(&priv->waitq); done: lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode); return cmdnode; }

Contributors

PersonTokensPropCommitsCommitProp
Holger Schurig12349.20%17.14%
David Woodhouse6224.80%642.86%
Dan J Williams4417.60%428.57%
Amitkumar Karwar187.20%17.14%
Daniel Drake31.20%214.29%
Total250100.00%14100.00%


void lbs_cmd_async(struct lbs_private *priv, uint16_t command, struct cmd_header *in_cmd, int in_cmd_size) { lbs_deb_enter(LBS_DEB_CMD); __lbs_cmd_async(priv, command, in_cmd, in_cmd_size, lbs_cmd_async_callback, 0); lbs_deb_leave(LBS_DEB_CMD); }

Contributors

PersonTokensPropCommitsCommitProp
Holger Schurig46100.00%1100.00%
Total46100.00%1100.00%


int __lbs_cmd(struct lbs_private *priv, uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), unsigned long callback_arg) { struct cmd_ctrl_node *cmdnode; unsigned long flags; int ret = 0; lbs_deb_enter(LBS_DEB_HOST); cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size, callback, callback_arg); if (IS_ERR(cmdnode)) { ret = PTR_ERR(cmdnode); goto done; } might_sleep(); /* * 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) netdev_info(priv->dev, "PREP_CMD: command 0x%04x failed: %d\n", command, ret); __lbs_cleanup_and_insert_cmd(priv, cmdnode); spin_unlock_irqrestore(&priv->driver_lock, flags); done: lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse11766.10%457.14%
Holger Schurig5329.94%114.29%
Joe Perches52.82%114.29%
Daniel Drake21.13%114.29%
Total177100.00%7100.00%

EXPORT_SYMBOL_GPL(__lbs_cmd);

Overall Contributors

PersonTokensPropCommitsCommitProp
Dan J Williams193227.94%2017.70%
Marcelo Tosatti159523.07%10.88%
Holger Schurig109715.86%2824.78%
David Woodhouse69710.08%2723.89%
Amitkumar Karwar6809.83%43.54%
Anna Neal2964.28%32.65%
Daniel Drake2243.24%65.31%
Kiran Divekar931.34%21.77%
Joe Perches731.06%21.77%
Javier Cardona400.58%10.88%
Li Zefan330.48%10.88%
Marek Vašut300.43%10.88%
Randy Dunlap240.35%10.88%
Paul Fox200.29%10.88%
Olivier Sobrie190.27%10.88%
Deepak Saxena160.23%10.88%
Vasily Khoruzhick150.22%10.88%
Rickard Strandqvist60.09%10.88%
Manish Katiyar50.07%10.88%
Stefani Seibold40.06%21.77%
Tejun Heo30.04%10.88%
Alexey Dobriyan30.04%10.88%
Johannes Berg30.04%21.77%
Paul Gortmaker30.04%10.88%
John W. Linville20.03%10.88%
Pan Bian10.01%10.88%
Andreas Kemnade10.01%10.88%
Total6915100.00%113100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.