cregit-Linux how code gets into the kernel

Release 4.7 drivers/net/wireless/marvell/libertas_tf/cmd.c

/*
 *  Copyright (C) 2008, cozybit Inc.
 *  Copyright (C) 2003-2006, Marvell International Ltd.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  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/hardirq.h>
#include <linux/slab.h>
#include <linux/export.h>

#include "libertas_tf.h"


static const struct channel_range channel_ranges[] = {
	{ LBTF_REGDOMAIN_US,		1, 12 },
	{ LBTF_REGDOMAIN_CA,		1, 12 },
	{ LBTF_REGDOMAIN_EU,		1, 14 },
	{ LBTF_REGDOMAIN_JP,		1, 14 },
	{ LBTF_REGDOMAIN_SP,		1, 14 },
	{ LBTF_REGDOMAIN_FR,		1, 14 },
};


static u16 lbtf_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
{
	LBTF_REGDOMAIN_US, LBTF_REGDOMAIN_CA, LBTF_REGDOMAIN_EU,
	LBTF_REGDOMAIN_SP, LBTF_REGDOMAIN_FR, LBTF_REGDOMAIN_JP,
};

static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv);


/**
 *  lbtf_cmd_copyback - Simple callback that copies response back into command
 *
 *  @priv       A pointer to struct lbtf_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 lbtf_cmd_copyback(struct lbtf_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
luis carlos cobo rusluis carlos cobo rus64100.00%1100.00%
Total64100.00%1100.00%

EXPORT_SYMBOL_GPL(lbtf_cmd_copyback); #define CHAN_TO_IDX(chan) ((chan) - 1)
static void lbtf_geo_init(struct lbtf_private *priv) { const struct channel_range *range = channel_ranges; u8 ch; int i; for (i = 0; i < ARRAY_SIZE(channel_ranges); i++) if (channel_ranges[i].regdomain == priv->regioncode) { range = &channel_ranges[i]; break; } for (ch = priv->range.start; ch < priv->range.end; ch++) priv->channels[CHAN_TO_IDX(ch)].flags = 0; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus100100.00%1100.00%
Total100100.00%1100.00%

/** * lbtf_update_hw_spec: Updates the hardware details. * * @priv A pointer to struct lbtf_private structure * * Returns: 0 on success, error on failure */
int lbtf_update_hw_spec(struct lbtf_private *priv) { struct cmd_ds_get_hw_spec cmd; 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); ret = lbtf_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); printk(KERN_INFO "libertastf: %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); 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 * firmware returns non-zero high 8 bits here. */ 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 == lbtf_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; pr_info("unidentified region code; using the default (USA)\n"); } if (priv->current_addr[0] == 0xff) memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); SET_IEEE80211_PERM_ADDR(priv->hw, priv->current_addr); lbtf_geo_init(priv); out: lbtf_deb_leave(LBTF_DEB_CMD); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus27089.70%133.33%
steve derosiersteve derosier309.97%133.33%
johannes bergjohannes berg10.33%133.33%
Total301100.00%3100.00%

/** * lbtf_set_channel: Set the radio channel * * @priv A pointer to struct lbtf_private structure * @channel The desired channel, or 0 to clear a locked channel * * Returns: 0 on success, error on failure */
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); ret = lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus5971.08%150.00%
steve derosiersteve derosier2428.92%150.00%
Total83100.00%2100.00%


int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon) { struct cmd_ds_802_11_beacon_set cmd; int 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; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus11080.88%150.00%
steve derosiersteve derosier2619.12%150.00%
Total136100.00%2100.00%


int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable, 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); cmd.beacon_enable = cpu_to_le16(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; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus8189.01%150.00%
steve derosiersteve derosier1010.99%150.00%
Total91100.00%2100.00%


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) { lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n"); goto qcmd_done; } 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); }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus7361.34%150.00%
steve derosiersteve derosier4638.66%150.00%
Total119100.00%2100.00%


static void lbtf_submit_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmdnode) { unsigned long flags; struct cmd_header *cmd; uint16_t cmdsize; uint16_t command; 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) { 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); }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus13271.74%150.00%
steve derosiersteve derosier5228.26%150.00%
Total184100.00%2100.00%

/** * This function inserts command node to cmdfreeq * after cleans it. Requires priv->driver_lock held. */
static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv, struct cmd_ctrl_node *cmdnode) { lbtf_deb_enter(LBTF_DEB_HOST); if (!cmdnode) goto cl_ins_out; cmdnode->callback = NULL; cmdnode->callback_arg = 0; memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE); list_add_tail(&cmdnode->list, &priv->cmdfreeq); cl_ins_out: lbtf_deb_leave(LBTF_DEB_HOST); }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus5779.17%150.00%
steve derosiersteve derosier1520.83%150.00%
Total72100.00%2100.00%


static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv, struct cmd_ctrl_node *ptempcmd) { unsigned long flags; spin_lock_irqsave(&priv->driver_lock, flags); __lbtf_cleanup_and_insert_cmd(priv, ptempcmd); spin_unlock_irqrestore(&priv->driver_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus47100.00%1100.00%
Total47100.00%1100.00%


void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd, int result) { cmd->result = result; cmd->cmdwaitqwoken = 1; wake_up_interruptible(&cmd->cmdwait_q); if (!cmd->callback) __lbtf_cleanup_and_insert_cmd(priv, cmd); priv->cur_cmd = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus58100.00%1100.00%
Total58100.00%1100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus8882.24%150.00%
steve derosiersteve derosier1917.76%150.00%
Total107100.00%2100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus5877.33%150.00%
steve derosiersteve derosier1722.67%150.00%
Total75100.00%2100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus7787.50%133.33%
steve derosiersteve derosier1011.36%133.33%
johannes bergjohannes berg11.14%133.33%
Total88100.00%3100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus7287.80%150.00%
steve derosiersteve derosier1012.20%150.00%
Total82100.00%2100.00%


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); switch (priv->preamble) { case CMD_TYPE_SHORT_PREAMBLE: cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE); break; case CMD_TYPE_LONG_PREAMBLE: cmd.control = cpu_to_le16(SET_LONG_PREAMBLE); break; case CMD_TYPE_AUTO_PREAMBLE: default: cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE); break; } if (priv->radioon) cmd.control |= cpu_to_le16(TURN_ON_RF); 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; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus13182.91%150.00%
steve derosiersteve derosier2717.09%150.00%
Total158100.00%2100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus6286.11%150.00%
steve derosiersteve derosier1013.89%150.00%
Total72100.00%2100.00%

/** * lbtf_allocate_cmd_buffer - Allocates cmd buffer, links it to free cmd queue * * @priv A pointer to struct lbtf_private structure * * Returns: 0 on success. */
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) { 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) { 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]); } ret = 0; done: lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus13572.19%150.00%
steve derosiersteve derosier5227.81%150.00%
Total187100.00%2100.00%

/** * lbtf_free_cmd_buffer - Frees the cmd buffer. * * @priv A pointer to struct lbtf_private structure * * Returns: 0 */
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) { lbtf_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++) { kfree(cmdarray[i].cmdbuf); cmdarray[i].cmdbuf = NULL; } /* Release cmd_ctrl_node */ kfree(priv->cmd_array); priv->cmd_array = NULL; done: lbtf_deb_leave(LBTF_DEB_HOST); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus8679.63%150.00%
steve derosiersteve derosier2220.37%150.00%
Total108100.00%2100.00%

/** * lbtf_get_cmd_ctrl_node - Gets free cmd node from free cmd queue. * * @priv A pointer to struct lbtf_private structure * * Returns: pointer to a struct cmd_ctrl_node or NULL if none available. */
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; 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(&tempnode->list); } 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; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus9484.68%150.00%
steve derosiersteve derosier1715.32%150.00%
Total111100.00%2100.00%

/** * lbtf_execute_next_command: execute next command in cmd pending queue. * * @priv A pointer to struct lbtf_private structure * * Returns: 0 on success. */
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 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); ret = -1; goto done; } if (!list_empty(&priv->cmdpendingq)) { cmdnode = list_first_entry(&priv->cmdpendingq, struct cmd_ctrl_node, list); } if (cmdnode) { 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); ret = 0; done: lbtf_deb_leave(LBTF_DEB_THREAD); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus13474.44%150.00%
steve derosiersteve derosier4625.56%150.00%
Total180100.00%2100.00%


static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv, uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, int (*callback)(struct lbtf_private *, unsigned long, struct cmd_header *), unsigned long callback_arg) { struct cmd_ctrl_node *cmdnode; 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); 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 sequence number, clean result, move to buffer */ priv->seqnum++; 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; 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; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus19280.33%150.00%
steve derosiersteve derosier4719.67%150.00%
Total239100.00%2100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus3678.26%150.00%
steve derosiersteve derosier1021.74%150.00%
Total46100.00%2100.00%


int __lbtf_cmd(struct lbtf_private *priv, uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, int (*callback)(struct lbtf_private *, unsigned long, struct cmd_header *), unsigned long callback_arg) { struct cmd_ctrl_node *cmdnode; 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)) { ret = PTR_ERR(cmdnode); goto done; } might_sleep(); ret = wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); 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) 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; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus15982.81%150.00%
steve derosiersteve derosier3317.19%150.00%
Total192100.00%2100.00%

EXPORT_SYMBOL_GPL(__lbtf_cmd); /* Call holding driver_lock */
void lbtf_cmd_response_rx(struct lbtf_private *priv) { priv->cmd_response_rxed = 1; queue_work(lbtf_wq, &priv->cmd_work); }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus26100.00%1100.00%
Total26100.00%1100.00%

EXPORT_SYMBOL_GPL(lbtf_cmd_response_rx);
int lbtf_process_rx_command(struct lbtf_private *priv) { uint16_t respcmd, curcmd; struct cmd_header *resp; int ret = 0; unsigned long flags; uint16_t result; lbtf_deb_enter(LBTF_DEB_CMD); mutex_lock(&priv->lock); spin_lock_irqsave(&priv->driver_lock, flags); if (!priv->cur_cmd) { ret = -1; spin_unlock_irqrestore(&priv->driver_lock, flags); goto done; } resp = (void *)priv->cmd_resp_buff; curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); respcmd = le16_to_cpu(resp->command); result = le16_to_cpu(resp->result); if (net_ratelimit()) pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n", respcmd, le16_to_cpu(resp->seqnum), le16_to_cpu(resp->size)); if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; } if (respcmd != CMD_RET(curcmd)) { spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; } if (resp->result == cpu_to_le16(0x0004)) { /* 0x0004 means -EAGAIN. Drop the response, let it time out and be resubmitted */ spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; } /* Now we got response from FW, cancel the command timer */ del_timer(&priv->command_timer); priv->cmd_timed_out = 0; if (priv->nr_retries) priv->nr_retries = 0; /* If the command is not successful, cleanup and return failure */ if ((result != 0 || !(respcmd & 0x8000))) { /* * Handling errors here */ switch (respcmd) { case CMD_RET(CMD_GET_HW_SPEC): case CMD_RET(CMD_802_11_RESET): pr_info("libertastf: reset failed\n"); break; } lbtf_complete_command(priv, priv->cur_cmd, result); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; } spin_unlock_irqrestore(&priv->driver_lock, flags); if (priv->cur_cmd && priv->cur_cmd->callback) { ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg, resp); } spin_lock_irqsave(&priv->driver_lock, flags); if (priv->cur_cmd) { /* Clean up and Put current command back to cmdfreeq */ lbtf_complete_command(priv, priv->cur_cmd, result); } spin_unlock_irqrestore(&priv->driver_lock, flags); done: mutex_unlock(&priv->lock); lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus43296.43%150.00%
steve derosiersteve derosier163.57%150.00%
Total448100.00%2100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
luis carlos cobo rusluis carlos cobo rus295884.15%112.50%
steve derosiersteve derosier53915.33%112.50%
john w. linvillejohn w. linville70.20%112.50%
alexey dobriyanalexey dobriyan30.09%112.50%
tejun heotejun heo30.09%112.50%
paul gortmakerpaul gortmaker30.09%112.50%
johannes bergjohannes berg20.06%225.00%
Total3515100.00%8100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}