/** * 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, unsignedlong extra, struct cmd_header *resp)
{ struct cmd_header *buf = (void *)extra;
uint16_t copy_len;
/** * 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);
/* 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);
/** * 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;
ret = priv->ops->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);
}
/* * This function inserts command node to cmdfreeq * after cleans it. Requires priv->driver_lock held.
*/ staticvoid __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv, struct cmd_ctrl_node *cmdnode)
{
lbtf_deb_enter(LBTF_DEB_HOST);
/** * 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]);
}
/** * 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; unsignedlong 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 (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 */
timer_delete(&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;
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);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.