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 
0011 #include <linux/etherdevice.h>
0012 #include <linux/module.h>
0013 #include "libertas_tf.h"
0014 
0015 /* thinfirm version: 5.132.X.pX */
0016 #define LBTF_FW_VER_MIN     0x05840300
0017 #define LBTF_FW_VER_MAX     0x0584ffff
0018 
0019 /* Module parameters */
0020 unsigned int lbtf_debug;
0021 EXPORT_SYMBOL_GPL(lbtf_debug);
0022 module_param_named(libertas_tf_debug, lbtf_debug, int, 0644);
0023 
0024 struct workqueue_struct *lbtf_wq;
0025 
0026 static const struct ieee80211_channel lbtf_channels[] = {
0027     { .center_freq = 2412, .hw_value = 1 },
0028     { .center_freq = 2417, .hw_value = 2 },
0029     { .center_freq = 2422, .hw_value = 3 },
0030     { .center_freq = 2427, .hw_value = 4 },
0031     { .center_freq = 2432, .hw_value = 5 },
0032     { .center_freq = 2437, .hw_value = 6 },
0033     { .center_freq = 2442, .hw_value = 7 },
0034     { .center_freq = 2447, .hw_value = 8 },
0035     { .center_freq = 2452, .hw_value = 9 },
0036     { .center_freq = 2457, .hw_value = 10 },
0037     { .center_freq = 2462, .hw_value = 11 },
0038     { .center_freq = 2467, .hw_value = 12 },
0039     { .center_freq = 2472, .hw_value = 13 },
0040     { .center_freq = 2484, .hw_value = 14 },
0041 };
0042 
0043 /* This table contains the hardware specific values for the modulation rates. */
0044 static const struct ieee80211_rate lbtf_rates[] = {
0045     { .bitrate = 10,
0046       .hw_value = 0, },
0047     { .bitrate = 20,
0048       .hw_value = 1,
0049       .flags = IEEE80211_RATE_SHORT_PREAMBLE },
0050     { .bitrate = 55,
0051       .hw_value = 2,
0052       .flags = IEEE80211_RATE_SHORT_PREAMBLE },
0053     { .bitrate = 110,
0054       .hw_value = 3,
0055       .flags = IEEE80211_RATE_SHORT_PREAMBLE },
0056     { .bitrate = 60,
0057       .hw_value = 5,
0058       .flags = 0 },
0059     { .bitrate = 90,
0060       .hw_value = 6,
0061       .flags = 0 },
0062     { .bitrate = 120,
0063       .hw_value = 7,
0064       .flags = 0 },
0065     { .bitrate = 180,
0066       .hw_value = 8,
0067       .flags = 0 },
0068     { .bitrate = 240,
0069       .hw_value = 9,
0070       .flags = 0 },
0071     { .bitrate = 360,
0072       .hw_value = 10,
0073       .flags = 0 },
0074     { .bitrate = 480,
0075       .hw_value = 11,
0076       .flags = 0 },
0077     { .bitrate = 540,
0078       .hw_value = 12,
0079       .flags = 0 },
0080 };
0081 
0082 static void lbtf_cmd_work(struct work_struct *work)
0083 {
0084     struct lbtf_private *priv = container_of(work, struct lbtf_private,
0085                      cmd_work);
0086 
0087     lbtf_deb_enter(LBTF_DEB_CMD);
0088 
0089     spin_lock_irq(&priv->driver_lock);
0090     /* command response? */
0091     if (priv->cmd_response_rxed) {
0092         priv->cmd_response_rxed = 0;
0093         spin_unlock_irq(&priv->driver_lock);
0094         lbtf_process_rx_command(priv);
0095         spin_lock_irq(&priv->driver_lock);
0096     }
0097 
0098     if (priv->cmd_timed_out && priv->cur_cmd) {
0099         struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
0100 
0101         if (++priv->nr_retries > 10) {
0102             lbtf_complete_command(priv, cmdnode,
0103                           -ETIMEDOUT);
0104             priv->nr_retries = 0;
0105         } else {
0106             priv->cur_cmd = NULL;
0107 
0108             /* Stick it back at the _top_ of the pending
0109              * queue for immediate resubmission */
0110             list_add(&cmdnode->list, &priv->cmdpendingq);
0111         }
0112     }
0113     priv->cmd_timed_out = 0;
0114     spin_unlock_irq(&priv->driver_lock);
0115 
0116     /* Execute the next command */
0117     if (!priv->cur_cmd)
0118         lbtf_execute_next_command(priv);
0119 
0120     lbtf_deb_leave(LBTF_DEB_CMD);
0121 }
0122 
0123 /*
0124  *  This function handles the timeout of command sending.
0125  *  It will re-send the same command again.
0126  */
0127 static void command_timer_fn(struct timer_list *t)
0128 {
0129     struct lbtf_private *priv = from_timer(priv, t, command_timer);
0130     unsigned long flags;
0131     lbtf_deb_enter(LBTF_DEB_CMD);
0132 
0133     spin_lock_irqsave(&priv->driver_lock, flags);
0134 
0135     if (!priv->cur_cmd) {
0136         printk(KERN_DEBUG "libertastf: command timer expired; "
0137                   "no pending command\n");
0138         goto out;
0139     }
0140 
0141     printk(KERN_DEBUG "libertas: command %x timed out\n",
0142         le16_to_cpu(priv->cur_cmd->cmdbuf->command));
0143 
0144     priv->cmd_timed_out = 1;
0145     queue_work(lbtf_wq, &priv->cmd_work);
0146 out:
0147     spin_unlock_irqrestore(&priv->driver_lock, flags);
0148     lbtf_deb_leave(LBTF_DEB_CMD);
0149 }
0150 
0151 static int lbtf_init_adapter(struct lbtf_private *priv)
0152 {
0153     lbtf_deb_enter(LBTF_DEB_MAIN);
0154     eth_broadcast_addr(priv->current_addr);
0155     mutex_init(&priv->lock);
0156 
0157     priv->vif = NULL;
0158     timer_setup(&priv->command_timer, command_timer_fn, 0);
0159 
0160     INIT_LIST_HEAD(&priv->cmdfreeq);
0161     INIT_LIST_HEAD(&priv->cmdpendingq);
0162 
0163     spin_lock_init(&priv->driver_lock);
0164 
0165     /* Allocate the command buffers */
0166     if (lbtf_allocate_cmd_buffer(priv))
0167         return -1;
0168 
0169     lbtf_deb_leave(LBTF_DEB_MAIN);
0170     return 0;
0171 }
0172 
0173 static void lbtf_free_adapter(struct lbtf_private *priv)
0174 {
0175     lbtf_deb_enter(LBTF_DEB_MAIN);
0176     lbtf_free_cmd_buffer(priv);
0177     del_timer(&priv->command_timer);
0178     lbtf_deb_leave(LBTF_DEB_MAIN);
0179 }
0180 
0181 static void lbtf_op_tx(struct ieee80211_hw *hw,
0182                struct ieee80211_tx_control *control,
0183                struct sk_buff *skb)
0184 {
0185     struct lbtf_private *priv = hw->priv;
0186 
0187     priv->skb_to_tx = skb;
0188     queue_work(lbtf_wq, &priv->tx_work);
0189     /*
0190      * queue will be restarted when we receive transmission feedback if
0191      * there are no buffered multicast frames to send
0192      */
0193     ieee80211_stop_queues(priv->hw);
0194 }
0195 
0196 static void lbtf_tx_work(struct work_struct *work)
0197 {
0198     struct lbtf_private *priv = container_of(work, struct lbtf_private,
0199                      tx_work);
0200     unsigned int len;
0201     struct ieee80211_tx_info *info;
0202     struct txpd *txpd;
0203     struct sk_buff *skb = NULL;
0204     int err;
0205 
0206     lbtf_deb_enter(LBTF_DEB_MACOPS | LBTF_DEB_TX);
0207 
0208     if ((priv->vif->type == NL80211_IFTYPE_AP) &&
0209         (!skb_queue_empty(&priv->bc_ps_buf)))
0210         skb = skb_dequeue(&priv->bc_ps_buf);
0211     else if (priv->skb_to_tx) {
0212         skb = priv->skb_to_tx;
0213         priv->skb_to_tx = NULL;
0214     } else {
0215         lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
0216         return;
0217     }
0218 
0219     len = skb->len;
0220     info  = IEEE80211_SKB_CB(skb);
0221     txpd = skb_push(skb, sizeof(struct txpd));
0222 
0223     if (priv->surpriseremoved) {
0224         dev_kfree_skb_any(skb);
0225         lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
0226         return;
0227     }
0228 
0229     memset(txpd, 0, sizeof(struct txpd));
0230     /* Activate per-packet rate selection */
0231     txpd->tx_control |= cpu_to_le32(MRVL_PER_PACKET_RATE |
0232                  ieee80211_get_tx_rate(priv->hw, info)->hw_value);
0233 
0234     /* copy destination address from 802.11 header */
0235     BUILD_BUG_ON(sizeof(txpd->tx_dest_addr) != ETH_ALEN);
0236     memcpy(&txpd->tx_dest_addr, skb->data + sizeof(struct txpd) + 4,
0237         ETH_ALEN);
0238     txpd->tx_packet_length = cpu_to_le16(len);
0239     txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
0240     lbtf_deb_hex(LBTF_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
0241     BUG_ON(priv->tx_skb);
0242     spin_lock_irq(&priv->driver_lock);
0243     priv->tx_skb = skb;
0244     err = priv->ops->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len);
0245     spin_unlock_irq(&priv->driver_lock);
0246     if (err) {
0247         dev_kfree_skb_any(skb);
0248         priv->tx_skb = NULL;
0249         pr_err("TX error: %d", err);
0250     }
0251     lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
0252 }
0253 
0254 static int lbtf_op_start(struct ieee80211_hw *hw)
0255 {
0256     struct lbtf_private *priv = hw->priv;
0257 
0258     lbtf_deb_enter(LBTF_DEB_MACOPS);
0259 
0260     priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
0261     priv->radioon = RADIO_ON;
0262     priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
0263     lbtf_set_mac_control(priv);
0264     lbtf_set_radio_control(priv);
0265 
0266     lbtf_deb_leave(LBTF_DEB_MACOPS);
0267     return 0;
0268 }
0269 
0270 static void lbtf_op_stop(struct ieee80211_hw *hw)
0271 {
0272     struct lbtf_private *priv = hw->priv;
0273     unsigned long flags;
0274     struct sk_buff *skb;
0275 
0276     struct cmd_ctrl_node *cmdnode;
0277 
0278     lbtf_deb_enter(LBTF_DEB_MACOPS);
0279 
0280     /* Flush pending command nodes */
0281     spin_lock_irqsave(&priv->driver_lock, flags);
0282     list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
0283         cmdnode->result = -ENOENT;
0284         cmdnode->cmdwaitqwoken = 1;
0285         wake_up_interruptible(&cmdnode->cmdwait_q);
0286     }
0287 
0288     spin_unlock_irqrestore(&priv->driver_lock, flags);
0289     cancel_work_sync(&priv->cmd_work);
0290     cancel_work_sync(&priv->tx_work);
0291     while ((skb = skb_dequeue(&priv->bc_ps_buf)))
0292         dev_kfree_skb_any(skb);
0293     priv->radioon = RADIO_OFF;
0294     lbtf_set_radio_control(priv);
0295 
0296     lbtf_deb_leave(LBTF_DEB_MACOPS);
0297 }
0298 
0299 static int lbtf_op_add_interface(struct ieee80211_hw *hw,
0300             struct ieee80211_vif *vif)
0301 {
0302     struct lbtf_private *priv = hw->priv;
0303     lbtf_deb_enter(LBTF_DEB_MACOPS);
0304     if (priv->vif != NULL)
0305         return -EOPNOTSUPP;
0306 
0307     priv->vif = vif;
0308     switch (vif->type) {
0309     case NL80211_IFTYPE_MESH_POINT:
0310     case NL80211_IFTYPE_AP:
0311         lbtf_set_mode(priv, LBTF_AP_MODE);
0312         break;
0313     case NL80211_IFTYPE_STATION:
0314         lbtf_set_mode(priv, LBTF_STA_MODE);
0315         break;
0316     default:
0317         priv->vif = NULL;
0318         return -EOPNOTSUPP;
0319     }
0320     lbtf_set_mac_address(priv, (u8 *) vif->addr);
0321     lbtf_deb_leave(LBTF_DEB_MACOPS);
0322     return 0;
0323 }
0324 
0325 static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
0326             struct ieee80211_vif *vif)
0327 {
0328     struct lbtf_private *priv = hw->priv;
0329     lbtf_deb_enter(LBTF_DEB_MACOPS);
0330 
0331     if (priv->vif->type == NL80211_IFTYPE_AP ||
0332         priv->vif->type == NL80211_IFTYPE_MESH_POINT)
0333         lbtf_beacon_ctrl(priv, 0, 0);
0334     lbtf_set_mode(priv, LBTF_PASSIVE_MODE);
0335     lbtf_set_bssid(priv, 0, NULL);
0336     priv->vif = NULL;
0337     lbtf_deb_leave(LBTF_DEB_MACOPS);
0338 }
0339 
0340 static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
0341 {
0342     struct lbtf_private *priv = hw->priv;
0343     struct ieee80211_conf *conf = &hw->conf;
0344     lbtf_deb_enter(LBTF_DEB_MACOPS);
0345 
0346     if (conf->chandef.chan->center_freq != priv->cur_freq) {
0347         priv->cur_freq = conf->chandef.chan->center_freq;
0348         lbtf_set_channel(priv, conf->chandef.chan->hw_value);
0349     }
0350     lbtf_deb_leave(LBTF_DEB_MACOPS);
0351     return 0;
0352 }
0353 
0354 static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw,
0355                      struct netdev_hw_addr_list *mc_list)
0356 {
0357     struct lbtf_private *priv = hw->priv;
0358     int i;
0359     struct netdev_hw_addr *ha;
0360     int mc_count = netdev_hw_addr_list_count(mc_list);
0361 
0362     if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE)
0363         return mc_count;
0364 
0365     priv->nr_of_multicastmacaddr = mc_count;
0366     i = 0;
0367     netdev_hw_addr_list_for_each(ha, mc_list)
0368         memcpy(&priv->multicastlist[i++], ha->addr, ETH_ALEN);
0369 
0370     return mc_count;
0371 }
0372 
0373 #define SUPPORTED_FIF_FLAGS  FIF_ALLMULTI
0374 static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
0375             unsigned int changed_flags,
0376             unsigned int *new_flags,
0377             u64 multicast)
0378 {
0379     struct lbtf_private *priv = hw->priv;
0380     int old_mac_control = priv->mac_control;
0381 
0382     lbtf_deb_enter(LBTF_DEB_MACOPS);
0383 
0384     changed_flags &= SUPPORTED_FIF_FLAGS;
0385     *new_flags &= SUPPORTED_FIF_FLAGS;
0386 
0387     if (!changed_flags) {
0388         lbtf_deb_leave(LBTF_DEB_MACOPS);
0389         return;
0390     }
0391 
0392     priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
0393     if (*new_flags & (FIF_ALLMULTI) ||
0394         multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
0395         priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
0396         priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE;
0397     } else if (multicast) {
0398         priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE;
0399         priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
0400         lbtf_cmd_set_mac_multicast_addr(priv);
0401     } else {
0402         priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE |
0403                        CMD_ACT_MAC_ALL_MULTICAST_ENABLE);
0404         if (priv->nr_of_multicastmacaddr) {
0405             priv->nr_of_multicastmacaddr = 0;
0406             lbtf_cmd_set_mac_multicast_addr(priv);
0407         }
0408     }
0409 
0410 
0411     if (priv->mac_control != old_mac_control)
0412         lbtf_set_mac_control(priv);
0413 
0414     lbtf_deb_leave(LBTF_DEB_MACOPS);
0415 }
0416 
0417 static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
0418             struct ieee80211_vif *vif,
0419             struct ieee80211_bss_conf *bss_conf,
0420             u64 changes)
0421 {
0422     struct lbtf_private *priv = hw->priv;
0423     struct sk_buff *beacon;
0424     lbtf_deb_enter(LBTF_DEB_MACOPS);
0425 
0426     if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) {
0427         switch (priv->vif->type) {
0428         case NL80211_IFTYPE_AP:
0429         case NL80211_IFTYPE_MESH_POINT:
0430             beacon = ieee80211_beacon_get(hw, vif, 0);
0431             if (beacon) {
0432                 lbtf_beacon_set(priv, beacon);
0433                 kfree_skb(beacon);
0434                 lbtf_beacon_ctrl(priv, 1,
0435                          bss_conf->beacon_int);
0436             }
0437             break;
0438         default:
0439             break;
0440         }
0441     }
0442 
0443     if (changes & BSS_CHANGED_BSSID) {
0444         bool activate = !is_zero_ether_addr(bss_conf->bssid);
0445         lbtf_set_bssid(priv, activate, bss_conf->bssid);
0446     }
0447 
0448     if (changes & BSS_CHANGED_ERP_PREAMBLE) {
0449         if (bss_conf->use_short_preamble)
0450             priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
0451         else
0452             priv->preamble = CMD_TYPE_LONG_PREAMBLE;
0453         lbtf_set_radio_control(priv);
0454     }
0455 
0456     lbtf_deb_leave(LBTF_DEB_MACOPS);
0457 }
0458 
0459 static int lbtf_op_get_survey(struct ieee80211_hw *hw, int idx,
0460                 struct survey_info *survey)
0461 {
0462     struct lbtf_private *priv = hw->priv;
0463     struct ieee80211_conf *conf = &hw->conf;
0464 
0465     if (idx != 0)
0466         return -ENOENT;
0467 
0468     survey->channel = conf->chandef.chan;
0469     survey->filled = SURVEY_INFO_NOISE_DBM;
0470     survey->noise = priv->noise;
0471 
0472     return 0;
0473 }
0474 
0475 static const struct ieee80211_ops lbtf_ops = {
0476     .tx         = lbtf_op_tx,
0477     .start          = lbtf_op_start,
0478     .stop           = lbtf_op_stop,
0479     .add_interface      = lbtf_op_add_interface,
0480     .remove_interface   = lbtf_op_remove_interface,
0481     .config         = lbtf_op_config,
0482     .prepare_multicast  = lbtf_op_prepare_multicast,
0483     .configure_filter   = lbtf_op_configure_filter,
0484     .bss_info_changed   = lbtf_op_bss_info_changed,
0485     .get_survey     = lbtf_op_get_survey,
0486 };
0487 
0488 int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
0489 {
0490     struct ieee80211_rx_status stats;
0491     struct rxpd *prxpd;
0492     int need_padding;
0493     struct ieee80211_hdr *hdr;
0494 
0495     lbtf_deb_enter(LBTF_DEB_RX);
0496 
0497     if (priv->radioon != RADIO_ON) {
0498         lbtf_deb_rx("rx before we turned on the radio");
0499         goto done;
0500     }
0501 
0502     prxpd = (struct rxpd *) skb->data;
0503 
0504     memset(&stats, 0, sizeof(stats));
0505     if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
0506         stats.flag |= RX_FLAG_FAILED_FCS_CRC;
0507     stats.freq = priv->cur_freq;
0508     stats.band = NL80211_BAND_2GHZ;
0509     stats.signal = prxpd->snr - prxpd->nf;
0510     priv->noise = prxpd->nf;
0511     /* Marvell rate index has a hole at value 4 */
0512     if (prxpd->rx_rate > 4)
0513         --prxpd->rx_rate;
0514     stats.rate_idx = prxpd->rx_rate;
0515     skb_pull(skb, sizeof(struct rxpd));
0516 
0517     hdr = (struct ieee80211_hdr *)skb->data;
0518 
0519     need_padding = ieee80211_is_data_qos(hdr->frame_control);
0520     need_padding ^= ieee80211_has_a4(hdr->frame_control);
0521     need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
0522             (*ieee80211_get_qos_ctl(hdr) &
0523              IEEE80211_QOS_CTL_A_MSDU_PRESENT);
0524 
0525     if (need_padding) {
0526         memmove(skb->data + 2, skb->data, skb->len);
0527         skb_reserve(skb, 2);
0528     }
0529 
0530     memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
0531 
0532     lbtf_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
0533            skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
0534     lbtf_deb_hex(LBTF_DEB_RX, "RX Data", skb->data,
0535                  min_t(unsigned int, skb->len, 100));
0536 
0537     ieee80211_rx_irqsafe(priv->hw, skb);
0538 
0539 done:
0540     lbtf_deb_leave(LBTF_DEB_RX);
0541     return 0;
0542 }
0543 EXPORT_SYMBOL_GPL(lbtf_rx);
0544 
0545 /*
0546  * lbtf_add_card: Add and initialize the card.
0547  *
0548  *  Returns: pointer to struct lbtf_priv.
0549  */
0550 struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
0551                    const struct lbtf_ops *ops)
0552 {
0553     struct ieee80211_hw *hw;
0554     struct lbtf_private *priv = NULL;
0555 
0556     lbtf_deb_enter(LBTF_DEB_MAIN);
0557 
0558     hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops);
0559     if (!hw)
0560         goto done;
0561 
0562     priv = hw->priv;
0563     if (lbtf_init_adapter(priv))
0564         goto err_init_adapter;
0565 
0566     priv->hw = hw;
0567     priv->card = card;
0568     priv->ops = ops;
0569     priv->tx_skb = NULL;
0570     priv->radioon = RADIO_OFF;
0571 
0572     hw->queues = 1;
0573     ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
0574     ieee80211_hw_set(hw, SIGNAL_DBM);
0575     hw->extra_tx_headroom = sizeof(struct txpd);
0576     memcpy(priv->channels, lbtf_channels, sizeof(lbtf_channels));
0577     memcpy(priv->rates, lbtf_rates, sizeof(lbtf_rates));
0578     priv->band.n_bitrates = ARRAY_SIZE(lbtf_rates);
0579     priv->band.bitrates = priv->rates;
0580     priv->band.n_channels = ARRAY_SIZE(lbtf_channels);
0581     priv->band.channels = priv->channels;
0582     hw->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band;
0583     hw->wiphy->interface_modes =
0584         BIT(NL80211_IFTYPE_STATION) |
0585         BIT(NL80211_IFTYPE_ADHOC);
0586     skb_queue_head_init(&priv->bc_ps_buf);
0587 
0588     wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
0589 
0590     SET_IEEE80211_DEV(hw, dmdev);
0591 
0592     INIT_WORK(&priv->cmd_work, lbtf_cmd_work);
0593     INIT_WORK(&priv->tx_work, lbtf_tx_work);
0594 
0595     if (priv->ops->hw_prog_firmware(priv)) {
0596         lbtf_deb_usbd(dmdev, "Error programming the firmware\n");
0597         priv->ops->hw_reset_device(priv);
0598         goto err_init_adapter;
0599     }
0600 
0601     eth_broadcast_addr(priv->current_addr);
0602     if (lbtf_update_hw_spec(priv))
0603         goto err_init_adapter;
0604 
0605     if (priv->fwrelease < LBTF_FW_VER_MIN ||
0606         priv->fwrelease > LBTF_FW_VER_MAX) {
0607         goto err_init_adapter;
0608     }
0609 
0610     /* The firmware seems to start with the radio enabled. Turn it
0611      * off before an actual mac80211 start callback is invoked.
0612      */
0613     lbtf_set_radio_control(priv);
0614 
0615     if (ieee80211_register_hw(hw))
0616         goto err_init_adapter;
0617 
0618     dev_info(dmdev, "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
0619     goto done;
0620 
0621 err_init_adapter:
0622     lbtf_free_adapter(priv);
0623     ieee80211_free_hw(hw);
0624     priv = NULL;
0625 
0626 done:
0627     lbtf_deb_leave_args(LBTF_DEB_MAIN, "priv %p", priv);
0628     return priv;
0629 }
0630 EXPORT_SYMBOL_GPL(lbtf_add_card);
0631 
0632 
0633 int lbtf_remove_card(struct lbtf_private *priv)
0634 {
0635     struct ieee80211_hw *hw = priv->hw;
0636 
0637     lbtf_deb_enter(LBTF_DEB_MAIN);
0638 
0639     priv->surpriseremoved = 1;
0640     del_timer(&priv->command_timer);
0641     lbtf_free_adapter(priv);
0642     priv->hw = NULL;
0643     ieee80211_unregister_hw(hw);
0644     ieee80211_free_hw(hw);
0645 
0646     lbtf_deb_leave(LBTF_DEB_MAIN);
0647     return 0;
0648 }
0649 EXPORT_SYMBOL_GPL(lbtf_remove_card);
0650 
0651 void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail)
0652 {
0653     struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb);
0654 
0655     ieee80211_tx_info_clear_status(info);
0656     /*
0657      * Commented out, otherwise we never go beyond 1Mbit/s using mac80211
0658      * default pid rc algorithm.
0659      *
0660      * info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt;
0661      */
0662     if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail)
0663         info->flags |= IEEE80211_TX_STAT_ACK;
0664     skb_pull(priv->tx_skb, sizeof(struct txpd));
0665     ieee80211_tx_status_irqsafe(priv->hw, priv->tx_skb);
0666     priv->tx_skb = NULL;
0667     if (!priv->skb_to_tx && skb_queue_empty(&priv->bc_ps_buf))
0668         ieee80211_wake_queues(priv->hw);
0669     else
0670         queue_work(lbtf_wq, &priv->tx_work);
0671 }
0672 EXPORT_SYMBOL_GPL(lbtf_send_tx_feedback);
0673 
0674 void lbtf_bcn_sent(struct lbtf_private *priv)
0675 {
0676     struct sk_buff *skb = NULL;
0677 
0678     if (priv->vif->type != NL80211_IFTYPE_AP)
0679         return;
0680 
0681     if (skb_queue_empty(&priv->bc_ps_buf)) {
0682         bool tx_buff_bc = false;
0683 
0684         while ((skb = ieee80211_get_buffered_bc(priv->hw, priv->vif))) {
0685             skb_queue_tail(&priv->bc_ps_buf, skb);
0686             tx_buff_bc = true;
0687         }
0688         if (tx_buff_bc) {
0689             ieee80211_stop_queues(priv->hw);
0690             queue_work(lbtf_wq, &priv->tx_work);
0691         }
0692     }
0693 
0694     skb = ieee80211_beacon_get(priv->hw, priv->vif, 0);
0695 
0696     if (skb) {
0697         lbtf_beacon_set(priv, skb);
0698         kfree_skb(skb);
0699     }
0700 }
0701 EXPORT_SYMBOL_GPL(lbtf_bcn_sent);
0702 
0703 static int __init lbtf_init_module(void)
0704 {
0705     lbtf_deb_enter(LBTF_DEB_MAIN);
0706     lbtf_wq = alloc_workqueue("libertastf", WQ_MEM_RECLAIM, 0);
0707     if (lbtf_wq == NULL) {
0708         printk(KERN_ERR "libertastf: couldn't create workqueue\n");
0709         return -ENOMEM;
0710     }
0711     lbtf_deb_leave(LBTF_DEB_MAIN);
0712     return 0;
0713 }
0714 
0715 static void __exit lbtf_exit_module(void)
0716 {
0717     lbtf_deb_enter(LBTF_DEB_MAIN);
0718     destroy_workqueue(lbtf_wq);
0719     lbtf_deb_leave(LBTF_DEB_MAIN);
0720 }
0721 
0722 module_init(lbtf_init_module);
0723 module_exit(lbtf_exit_module);
0724 
0725 MODULE_DESCRIPTION("Libertas WLAN Thinfirm Driver Library");
0726 MODULE_AUTHOR("Cozybit Inc.");
0727 MODULE_LICENSE("GPL");