Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (C) 2008, cozybit Inc.
0004  *  Copyright (C) 2003-2006, Marvell International Ltd.
0005  */
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007 
0008 #include <linux/hardirq.h>
0009 #include <linux/slab.h>
0010 #include <linux/export.h>
0011 
0012 #include "libertas_tf.h"
0013 
0014 static const struct channel_range channel_ranges[] = {
0015     { LBTF_REGDOMAIN_US,        1, 12 },
0016     { LBTF_REGDOMAIN_CA,        1, 12 },
0017     { LBTF_REGDOMAIN_EU,        1, 14 },
0018     { LBTF_REGDOMAIN_JP,        1, 14 },
0019     { LBTF_REGDOMAIN_SP,        1, 14 },
0020     { LBTF_REGDOMAIN_FR,        1, 14 },
0021 };
0022 
0023 static u16 lbtf_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
0024 {
0025     LBTF_REGDOMAIN_US, LBTF_REGDOMAIN_CA, LBTF_REGDOMAIN_EU,
0026     LBTF_REGDOMAIN_SP, LBTF_REGDOMAIN_FR, LBTF_REGDOMAIN_JP,
0027 };
0028 
0029 static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv);
0030 
0031 
0032 /**
0033  *  lbtf_cmd_copyback - Simple callback that copies response back into command
0034  *
0035  *  @priv:  A pointer to struct lbtf_private structure
0036  *  @extra: A pointer to the original command structure for which
0037  *      'resp' is a response
0038  *  @resp:  A pointer to the command response
0039  *
0040  *  Returns: 0 on success, error on failure
0041  */
0042 int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra,
0043              struct cmd_header *resp)
0044 {
0045     struct cmd_header *buf = (void *)extra;
0046     uint16_t copy_len;
0047 
0048     copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
0049     memcpy(buf, resp, copy_len);
0050     return 0;
0051 }
0052 EXPORT_SYMBOL_GPL(lbtf_cmd_copyback);
0053 
0054 #define CHAN_TO_IDX(chan) ((chan) - 1)
0055 
0056 static void lbtf_geo_init(struct lbtf_private *priv)
0057 {
0058     const struct channel_range *range = channel_ranges;
0059     u8 ch;
0060     int i;
0061 
0062     for (i = 0; i < ARRAY_SIZE(channel_ranges); i++)
0063         if (channel_ranges[i].regdomain == priv->regioncode) {
0064             range = &channel_ranges[i];
0065             break;
0066         }
0067 
0068     for (ch = range->start; ch < range->end; ch++)
0069         priv->channels[CHAN_TO_IDX(ch)].flags = 0;
0070 }
0071 
0072 /**
0073  *  lbtf_update_hw_spec: Updates the hardware details.
0074  *
0075  *  @priv:      A pointer to struct lbtf_private structure
0076  *
0077  *  Returns: 0 on success, error on failure
0078  */
0079 int lbtf_update_hw_spec(struct lbtf_private *priv)
0080 {
0081     struct cmd_ds_get_hw_spec cmd;
0082     int ret = -1;
0083     u32 i;
0084 
0085     lbtf_deb_enter(LBTF_DEB_CMD);
0086 
0087     memset(&cmd, 0, sizeof(cmd));
0088     cmd.hdr.size = cpu_to_le16(sizeof(cmd));
0089     memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
0090     ret = lbtf_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
0091     if (ret)
0092         goto out;
0093 
0094     priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
0095 
0096     /* The firmware release is in an interesting format: the patch
0097      * level is in the most significant nibble ... so fix that: */
0098     priv->fwrelease = le32_to_cpu(cmd.fwrelease);
0099     priv->fwrelease = (priv->fwrelease << 8) |
0100         (priv->fwrelease >> 24 & 0xff);
0101 
0102     printk(KERN_INFO "libertastf: %pM, fw %u.%u.%up%u, cap 0x%08x\n",
0103         cmd.permanentaddr,
0104         priv->fwrelease >> 24 & 0xff,
0105         priv->fwrelease >> 16 & 0xff,
0106         priv->fwrelease >>  8 & 0xff,
0107         priv->fwrelease       & 0xff,
0108         priv->fwcapinfo);
0109     lbtf_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
0110             cmd.hwifversion, cmd.version);
0111 
0112     /* Clamp region code to 8-bit since FW spec indicates that it should
0113      * only ever be 8-bit, even though the field size is 16-bit.  Some
0114      * firmware returns non-zero high 8 bits here.
0115      */
0116     priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
0117 
0118     for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
0119         /* use the region code to search for the index */
0120         if (priv->regioncode == lbtf_region_code_to_index[i])
0121             break;
0122     }
0123 
0124     /* if it's unidentified region code, use the default (USA) */
0125     if (i >= MRVDRV_MAX_REGION_CODE) {
0126         priv->regioncode = 0x10;
0127         pr_info("unidentified region code; using the default (USA)\n");
0128     }
0129 
0130     if (priv->current_addr[0] == 0xff)
0131         memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
0132 
0133     SET_IEEE80211_PERM_ADDR(priv->hw, priv->current_addr);
0134 
0135     lbtf_geo_init(priv);
0136 out:
0137     lbtf_deb_leave(LBTF_DEB_CMD);
0138     return ret;
0139 }
0140 
0141 /**
0142  *  lbtf_set_channel: Set the radio channel
0143  *
0144  *  @priv:  A pointer to struct lbtf_private structure
0145  *  @channel:   The desired channel, or 0 to clear a locked channel
0146  *
0147  *  Returns: 0 on success, error on failure
0148  */
0149 int lbtf_set_channel(struct lbtf_private *priv, u8 channel)
0150 {
0151     int ret = 0;
0152     struct cmd_ds_802_11_rf_channel cmd;
0153 
0154     lbtf_deb_enter(LBTF_DEB_CMD);
0155 
0156     cmd.hdr.size = cpu_to_le16(sizeof(cmd));
0157     cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
0158     cmd.channel = cpu_to_le16(channel);
0159 
0160     ret = lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
0161     lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
0162     return ret;
0163 }
0164 
0165 int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
0166 {
0167     struct cmd_ds_802_11_beacon_set cmd;
0168     int size;
0169 
0170     lbtf_deb_enter(LBTF_DEB_CMD);
0171 
0172     if (beacon->len > MRVL_MAX_BCN_SIZE) {
0173         lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", -1);
0174         return -1;
0175     }
0176     size =  sizeof(cmd) - sizeof(cmd.beacon) + beacon->len;
0177     cmd.hdr.size = cpu_to_le16(size);
0178     cmd.len = cpu_to_le16(beacon->len);
0179     memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len);
0180 
0181     lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size);
0182 
0183     lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", 0);
0184     return 0;
0185 }
0186 
0187 int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
0188              int beacon_int)
0189 {
0190     struct cmd_ds_802_11_beacon_control cmd;
0191     lbtf_deb_enter(LBTF_DEB_CMD);
0192 
0193     cmd.hdr.size = cpu_to_le16(sizeof(cmd));
0194     cmd.action = cpu_to_le16(CMD_ACT_SET);
0195     cmd.beacon_enable = cpu_to_le16(beacon_enable);
0196     cmd.beacon_period = cpu_to_le16(beacon_int);
0197 
0198     lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd));
0199 
0200     lbtf_deb_leave(LBTF_DEB_CMD);
0201     return 0;
0202 }
0203 
0204 static void lbtf_queue_cmd(struct lbtf_private *priv,
0205               struct cmd_ctrl_node *cmdnode)
0206 {
0207     unsigned long flags;
0208     lbtf_deb_enter(LBTF_DEB_HOST);
0209 
0210     if (!cmdnode) {
0211         lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n");
0212         goto qcmd_done;
0213     }
0214 
0215     if (!cmdnode->cmdbuf->size) {
0216         lbtf_deb_host("DNLD_CMD: cmd size is zero\n");
0217         goto qcmd_done;
0218     }
0219 
0220     cmdnode->result = 0;
0221     spin_lock_irqsave(&priv->driver_lock, flags);
0222     list_add_tail(&cmdnode->list, &priv->cmdpendingq);
0223     spin_unlock_irqrestore(&priv->driver_lock, flags);
0224 
0225     lbtf_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
0226              le16_to_cpu(cmdnode->cmdbuf->command));
0227 
0228 qcmd_done:
0229     lbtf_deb_leave(LBTF_DEB_HOST);
0230 }
0231 
0232 static void lbtf_submit_command(struct lbtf_private *priv,
0233                    struct cmd_ctrl_node *cmdnode)
0234 {
0235     unsigned long flags;
0236     struct cmd_header *cmd;
0237     uint16_t cmdsize;
0238     uint16_t command;
0239     int timeo = 5 * HZ;
0240     int ret;
0241 
0242     lbtf_deb_enter(LBTF_DEB_HOST);
0243 
0244     cmd = cmdnode->cmdbuf;
0245 
0246     spin_lock_irqsave(&priv->driver_lock, flags);
0247     priv->cur_cmd = cmdnode;
0248     cmdsize = le16_to_cpu(cmd->size);
0249     command = le16_to_cpu(cmd->command);
0250 
0251     lbtf_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
0252              command, le16_to_cpu(cmd->seqnum), cmdsize);
0253     lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
0254 
0255     ret = priv->ops->hw_host_to_card(priv, MVMS_CMD, (u8 *)cmd, cmdsize);
0256     spin_unlock_irqrestore(&priv->driver_lock, flags);
0257 
0258     if (ret) {
0259         pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
0260         /* Let the timer kick in and retry, and potentially reset
0261            the whole thing if the condition persists */
0262         timeo = HZ;
0263     }
0264 
0265     /* Setup the timer after transmit command */
0266     mod_timer(&priv->command_timer, jiffies + timeo);
0267 
0268     lbtf_deb_leave(LBTF_DEB_HOST);
0269 }
0270 
0271 /*
0272  *  This function inserts command node to cmdfreeq
0273  *  after cleans it. Requires priv->driver_lock held.
0274  */
0275 static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
0276                      struct cmd_ctrl_node *cmdnode)
0277 {
0278     lbtf_deb_enter(LBTF_DEB_HOST);
0279 
0280     if (!cmdnode)
0281         goto cl_ins_out;
0282 
0283     cmdnode->callback = NULL;
0284     cmdnode->callback_arg = 0;
0285 
0286     memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
0287 
0288     list_add_tail(&cmdnode->list, &priv->cmdfreeq);
0289 
0290 cl_ins_out:
0291     lbtf_deb_leave(LBTF_DEB_HOST);
0292 }
0293 
0294 static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
0295     struct cmd_ctrl_node *ptempcmd)
0296 {
0297     unsigned long flags;
0298 
0299     spin_lock_irqsave(&priv->driver_lock, flags);
0300     __lbtf_cleanup_and_insert_cmd(priv, ptempcmd);
0301     spin_unlock_irqrestore(&priv->driver_lock, flags);
0302 }
0303 
0304 void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd,
0305               int result)
0306 {
0307     cmd->result = result;
0308     cmd->cmdwaitqwoken = 1;
0309     wake_up_interruptible(&cmd->cmdwait_q);
0310 
0311     if (!cmd->callback)
0312         __lbtf_cleanup_and_insert_cmd(priv, cmd);
0313     priv->cur_cmd = NULL;
0314 }
0315 
0316 int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv)
0317 {
0318     struct cmd_ds_mac_multicast_addr cmd;
0319 
0320     lbtf_deb_enter(LBTF_DEB_CMD);
0321 
0322     cmd.hdr.size = cpu_to_le16(sizeof(cmd));
0323     cmd.action = cpu_to_le16(CMD_ACT_SET);
0324 
0325     cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
0326 
0327     lbtf_deb_cmd("MULTICAST_ADR: setting %d addresses\n", cmd.nr_of_adrs);
0328 
0329     memcpy(cmd.maclist, priv->multicastlist,
0330            priv->nr_of_multicastmacaddr * ETH_ALEN);
0331 
0332     lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd));
0333 
0334     lbtf_deb_leave(LBTF_DEB_CMD);
0335     return 0;
0336 }
0337 
0338 void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)
0339 {
0340     struct cmd_ds_set_mode cmd;
0341     lbtf_deb_enter(LBTF_DEB_WEXT);
0342 
0343     cmd.hdr.size = cpu_to_le16(sizeof(cmd));
0344     cmd.mode = cpu_to_le16(mode);
0345     lbtf_deb_wext("Switching to mode: 0x%x\n", mode);
0346     lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd));
0347 
0348     lbtf_deb_leave(LBTF_DEB_WEXT);
0349 }
0350 
0351 void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
0352 {
0353     struct cmd_ds_set_bssid cmd;
0354     lbtf_deb_enter(LBTF_DEB_CMD);
0355 
0356     cmd.hdr.size = cpu_to_le16(sizeof(cmd));
0357     cmd.activate = activate ? 1 : 0;
0358     if (activate)
0359         memcpy(cmd.bssid, bssid, ETH_ALEN);
0360 
0361     lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd));
0362     lbtf_deb_leave(LBTF_DEB_CMD);
0363 }
0364 
0365 int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
0366 {
0367     struct cmd_ds_802_11_mac_address cmd;
0368     lbtf_deb_enter(LBTF_DEB_CMD);
0369 
0370     cmd.hdr.size = cpu_to_le16(sizeof(cmd));
0371     cmd.action = cpu_to_le16(CMD_ACT_SET);
0372 
0373     memcpy(cmd.macadd, mac_addr, ETH_ALEN);
0374 
0375     lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd));
0376     lbtf_deb_leave(LBTF_DEB_CMD);
0377     return 0;
0378 }
0379 
0380 int lbtf_set_radio_control(struct lbtf_private *priv)
0381 {
0382     int ret = 0;
0383     struct cmd_ds_802_11_radio_control cmd;
0384 
0385     lbtf_deb_enter(LBTF_DEB_CMD);
0386 
0387     cmd.hdr.size = cpu_to_le16(sizeof(cmd));
0388     cmd.action = cpu_to_le16(CMD_ACT_SET);
0389 
0390     switch (priv->preamble) {
0391     case CMD_TYPE_SHORT_PREAMBLE:
0392         cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE);
0393         break;
0394 
0395     case CMD_TYPE_LONG_PREAMBLE:
0396         cmd.control = cpu_to_le16(SET_LONG_PREAMBLE);
0397         break;
0398 
0399     case CMD_TYPE_AUTO_PREAMBLE:
0400     default:
0401         cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE);
0402         break;
0403     }
0404 
0405     if (priv->radioon)
0406         cmd.control |= cpu_to_le16(TURN_ON_RF);
0407     else
0408         cmd.control &= cpu_to_le16(~TURN_ON_RF);
0409 
0410     lbtf_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
0411             priv->preamble);
0412 
0413     ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
0414 
0415     lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
0416     return ret;
0417 }
0418 
0419 void lbtf_set_mac_control(struct lbtf_private *priv)
0420 {
0421     struct cmd_ds_mac_control cmd;
0422     lbtf_deb_enter(LBTF_DEB_CMD);
0423 
0424     cmd.hdr.size = cpu_to_le16(sizeof(cmd));
0425     cmd.action = cpu_to_le16(priv->mac_control);
0426     cmd.reserved = 0;
0427 
0428     lbtf_cmd_async(priv, CMD_MAC_CONTROL,
0429         &cmd.hdr, sizeof(cmd));
0430 
0431     lbtf_deb_leave(LBTF_DEB_CMD);
0432 }
0433 
0434 /**
0435  *  lbtf_allocate_cmd_buffer - Allocates cmd buffer, links it to free cmd queue
0436  *
0437  *  @priv:  A pointer to struct lbtf_private structure
0438  *
0439  *  Returns: 0 on success.
0440  */
0441 int lbtf_allocate_cmd_buffer(struct lbtf_private *priv)
0442 {
0443     int ret = 0;
0444     u32 bufsize;
0445     u32 i;
0446     struct cmd_ctrl_node *cmdarray;
0447 
0448     lbtf_deb_enter(LBTF_DEB_HOST);
0449 
0450     /* Allocate and initialize the command array */
0451     bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
0452     cmdarray = kzalloc(bufsize, GFP_KERNEL);
0453     if (!cmdarray) {
0454         lbtf_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
0455         ret = -1;
0456         goto done;
0457     }
0458     priv->cmd_array = cmdarray;
0459 
0460     /* Allocate and initialize each command buffer in the command array */
0461     for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
0462         cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
0463         if (!cmdarray[i].cmdbuf) {
0464             lbtf_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
0465             ret = -1;
0466             goto done;
0467         }
0468     }
0469 
0470     for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
0471         init_waitqueue_head(&cmdarray[i].cmdwait_q);
0472         lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]);
0473     }
0474 
0475     ret = 0;
0476 
0477 done:
0478     lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
0479     return ret;
0480 }
0481 
0482 /**
0483  *  lbtf_free_cmd_buffer - Frees the cmd buffer.
0484  *
0485  *  @priv:  A pointer to struct lbtf_private structure
0486  *
0487  *  Returns: 0
0488  */
0489 int lbtf_free_cmd_buffer(struct lbtf_private *priv)
0490 {
0491     struct cmd_ctrl_node *cmdarray;
0492     unsigned int i;
0493 
0494     lbtf_deb_enter(LBTF_DEB_HOST);
0495 
0496     /* need to check if cmd array is allocated or not */
0497     if (priv->cmd_array == NULL) {
0498         lbtf_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
0499         goto done;
0500     }
0501 
0502     cmdarray = priv->cmd_array;
0503 
0504     /* Release shared memory buffers */
0505     for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
0506         kfree(cmdarray[i].cmdbuf);
0507         cmdarray[i].cmdbuf = NULL;
0508     }
0509 
0510     /* Release cmd_ctrl_node */
0511     kfree(priv->cmd_array);
0512     priv->cmd_array = NULL;
0513 
0514 done:
0515     lbtf_deb_leave(LBTF_DEB_HOST);
0516     return 0;
0517 }
0518 
0519 /**
0520  *  lbtf_get_cmd_ctrl_node - Gets free cmd node from free cmd queue.
0521  *
0522  *  @priv:      A pointer to struct lbtf_private structure
0523  *
0524  *  Returns: pointer to a struct cmd_ctrl_node or NULL if none available.
0525  */
0526 static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)
0527 {
0528     struct cmd_ctrl_node *tempnode;
0529     unsigned long flags;
0530 
0531     lbtf_deb_enter(LBTF_DEB_HOST);
0532 
0533     if (!priv)
0534         return NULL;
0535 
0536     spin_lock_irqsave(&priv->driver_lock, flags);
0537 
0538     if (!list_empty(&priv->cmdfreeq)) {
0539         tempnode = list_first_entry(&priv->cmdfreeq,
0540                         struct cmd_ctrl_node, list);
0541         list_del(&tempnode->list);
0542     } else {
0543         lbtf_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
0544         tempnode = NULL;
0545     }
0546 
0547     spin_unlock_irqrestore(&priv->driver_lock, flags);
0548 
0549     lbtf_deb_leave(LBTF_DEB_HOST);
0550     return tempnode;
0551 }
0552 
0553 /**
0554  *  lbtf_execute_next_command: execute next command in cmd pending queue.
0555  *
0556  *  @priv:     A pointer to struct lbtf_private structure
0557  *
0558  *  Returns: 0 on success.
0559  */
0560 int lbtf_execute_next_command(struct lbtf_private *priv)
0561 {
0562     struct cmd_ctrl_node *cmdnode = NULL;
0563     struct cmd_header *cmd;
0564     unsigned long flags;
0565     int ret = 0;
0566 
0567     /* Debug group is lbtf_deb_THREAD and not lbtf_deb_HOST, because the
0568      * only caller to us is lbtf_thread() and we get even when a
0569      * data packet is received */
0570     lbtf_deb_enter(LBTF_DEB_THREAD);
0571 
0572     spin_lock_irqsave(&priv->driver_lock, flags);
0573 
0574     if (priv->cur_cmd) {
0575         pr_alert("EXEC_NEXT_CMD: already processing command!\n");
0576         spin_unlock_irqrestore(&priv->driver_lock, flags);
0577         ret = -1;
0578         goto done;
0579     }
0580 
0581     if (!list_empty(&priv->cmdpendingq)) {
0582         cmdnode = list_first_entry(&priv->cmdpendingq,
0583                        struct cmd_ctrl_node, list);
0584     }
0585 
0586     if (cmdnode) {
0587         cmd = cmdnode->cmdbuf;
0588 
0589         list_del(&cmdnode->list);
0590         lbtf_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
0591                 le16_to_cpu(cmd->command));
0592         spin_unlock_irqrestore(&priv->driver_lock, flags);
0593         lbtf_submit_command(priv, cmdnode);
0594     } else
0595         spin_unlock_irqrestore(&priv->driver_lock, flags);
0596 
0597     ret = 0;
0598 done:
0599     lbtf_deb_leave(LBTF_DEB_THREAD);
0600     return ret;
0601 }
0602 
0603 static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
0604     uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
0605     int (*callback)(struct lbtf_private *, unsigned long,
0606             struct cmd_header *),
0607     unsigned long callback_arg)
0608 {
0609     struct cmd_ctrl_node *cmdnode;
0610 
0611     lbtf_deb_enter(LBTF_DEB_HOST);
0612 
0613     if (priv->surpriseremoved) {
0614         lbtf_deb_host("PREP_CMD: card removed\n");
0615         cmdnode = ERR_PTR(-ENOENT);
0616         goto done;
0617     }
0618 
0619     cmdnode = lbtf_get_cmd_ctrl_node(priv);
0620     if (cmdnode == NULL) {
0621         lbtf_deb_host("PREP_CMD: cmdnode is NULL\n");
0622 
0623         /* Wake up main thread to execute next command */
0624         queue_work(lbtf_wq, &priv->cmd_work);
0625         cmdnode = ERR_PTR(-ENOBUFS);
0626         goto done;
0627     }
0628 
0629     cmdnode->callback = callback;
0630     cmdnode->callback_arg = callback_arg;
0631 
0632     /* Copy the incoming command to the buffer */
0633     memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
0634 
0635     /* Set sequence number, clean result, move to buffer */
0636     priv->seqnum++;
0637     cmdnode->cmdbuf->command = cpu_to_le16(command);
0638     cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
0639     cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);
0640     cmdnode->cmdbuf->result  = 0;
0641 
0642     lbtf_deb_host("PREP_CMD: command 0x%04x\n", command);
0643 
0644     cmdnode->cmdwaitqwoken = 0;
0645     lbtf_queue_cmd(priv, cmdnode);
0646     queue_work(lbtf_wq, &priv->cmd_work);
0647 
0648  done:
0649     lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %p", cmdnode);
0650     return cmdnode;
0651 }
0652 
0653 void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
0654     struct cmd_header *in_cmd, int in_cmd_size)
0655 {
0656     lbtf_deb_enter(LBTF_DEB_CMD);
0657     __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0);
0658     lbtf_deb_leave(LBTF_DEB_CMD);
0659 }
0660 
0661 int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
0662           struct cmd_header *in_cmd, int in_cmd_size,
0663           int (*callback)(struct lbtf_private *,
0664                   unsigned long, struct cmd_header *),
0665           unsigned long callback_arg)
0666 {
0667     struct cmd_ctrl_node *cmdnode;
0668     unsigned long flags;
0669     int ret = 0;
0670 
0671     lbtf_deb_enter(LBTF_DEB_HOST);
0672 
0673     cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size,
0674                   callback, callback_arg);
0675     if (IS_ERR(cmdnode)) {
0676         ret = PTR_ERR(cmdnode);
0677         goto done;
0678     }
0679 
0680     might_sleep();
0681     ret = wait_event_interruptible(cmdnode->cmdwait_q,
0682                        cmdnode->cmdwaitqwoken);
0683     if (ret) {
0684         pr_info("PREP_CMD: command 0x%04x interrupted by signal: %d\n",
0685                 command, ret);
0686         goto done;
0687     }
0688 
0689     spin_lock_irqsave(&priv->driver_lock, flags);
0690     ret = cmdnode->result;
0691     if (ret)
0692         pr_info("PREP_CMD: command 0x%04x failed: %d\n",
0693                 command, ret);
0694 
0695     __lbtf_cleanup_and_insert_cmd(priv, cmdnode);
0696     spin_unlock_irqrestore(&priv->driver_lock, flags);
0697 
0698 done:
0699     lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
0700     return ret;
0701 }
0702 EXPORT_SYMBOL_GPL(__lbtf_cmd);
0703 
0704 /* Call holding driver_lock */
0705 void lbtf_cmd_response_rx(struct lbtf_private *priv)
0706 {
0707     priv->cmd_response_rxed = 1;
0708     queue_work(lbtf_wq, &priv->cmd_work);
0709 }
0710 EXPORT_SYMBOL_GPL(lbtf_cmd_response_rx);
0711 
0712 int lbtf_process_rx_command(struct lbtf_private *priv)
0713 {
0714     uint16_t respcmd, curcmd;
0715     struct cmd_header *resp;
0716     int ret = 0;
0717     unsigned long flags;
0718     uint16_t result;
0719 
0720     lbtf_deb_enter(LBTF_DEB_CMD);
0721 
0722     mutex_lock(&priv->lock);
0723     spin_lock_irqsave(&priv->driver_lock, flags);
0724 
0725     if (!priv->cur_cmd) {
0726         ret = -1;
0727         spin_unlock_irqrestore(&priv->driver_lock, flags);
0728         goto done;
0729     }
0730 
0731     resp = (void *)priv->cmd_resp_buff;
0732     curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
0733     respcmd = le16_to_cpu(resp->command);
0734     result = le16_to_cpu(resp->result);
0735 
0736     lbtf_deb_cmd("libertastf: cmd response 0x%04x, seq %d, size %d\n",
0737              respcmd, le16_to_cpu(resp->seqnum),
0738              le16_to_cpu(resp->size));
0739 
0740     if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
0741         spin_unlock_irqrestore(&priv->driver_lock, flags);
0742         ret = -1;
0743         goto done;
0744     }
0745     if (respcmd != CMD_RET(curcmd)) {
0746         spin_unlock_irqrestore(&priv->driver_lock, flags);
0747         ret = -1;
0748         goto done;
0749     }
0750 
0751     if (resp->result == cpu_to_le16(0x0004)) {
0752         /* 0x0004 means -EAGAIN. Drop the response, let it time out
0753            and be resubmitted */
0754         spin_unlock_irqrestore(&priv->driver_lock, flags);
0755         ret = -1;
0756         goto done;
0757     }
0758 
0759     /* Now we got response from FW, cancel the command timer */
0760     del_timer(&priv->command_timer);
0761     priv->cmd_timed_out = 0;
0762     if (priv->nr_retries)
0763         priv->nr_retries = 0;
0764 
0765     /* If the command is not successful, cleanup and return failure */
0766     if ((result != 0 || !(respcmd & 0x8000))) {
0767         /*
0768          * Handling errors here
0769          */
0770         switch (respcmd) {
0771         case CMD_RET(CMD_GET_HW_SPEC):
0772         case CMD_RET(CMD_802_11_RESET):
0773             pr_info("libertastf: reset failed\n");
0774             break;
0775 
0776         }
0777         lbtf_complete_command(priv, priv->cur_cmd, result);
0778         spin_unlock_irqrestore(&priv->driver_lock, flags);
0779 
0780         ret = -1;
0781         goto done;
0782     }
0783 
0784     spin_unlock_irqrestore(&priv->driver_lock, flags);
0785 
0786     if (priv->cur_cmd && priv->cur_cmd->callback) {
0787         ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
0788                 resp);
0789     }
0790     spin_lock_irqsave(&priv->driver_lock, flags);
0791 
0792     if (priv->cur_cmd) {
0793         /* Clean up and Put current command back to cmdfreeq */
0794         lbtf_complete_command(priv, priv->cur_cmd, result);
0795     }
0796     spin_unlock_irqrestore(&priv->driver_lock, flags);
0797 
0798 done:
0799     mutex_unlock(&priv->lock);
0800     lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
0801     return ret;
0802 }