/** *lbtf_update_hw_spec:Updatesthehardwaredetails. * *@priv:Apointertostructlbtf_privatestructure * *Returns:0onsuccess,erroronfailure
*/ 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 *onlyeverbe8-bit,eventhoughthefieldsizeis16-bit.Some *firmwarereturnsnon-zerohigh8bitshere.
*/
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);
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_allocate_cmd_buffer-Allocatescmdbuffer,linksittofreecmdqueue * *@priv:Apointertostructlbtf_privatestructure * *Returns:0onsuccess.
*/ 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:executenextcommandincmdpendingqueue. * *@priv:Apointertostructlbtf_privatestructure * *Returns:0onsuccess.
*/ 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 *onlycallertousislbtf_thread()andwegetevenwhena
* 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))) { /* *Handlingerrorshere
*/ 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.