]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
libertas_tf: don't defer firmware loading until start()
authorLubomir Rintel <lkundrak@v3.sk>
Wed, 20 Feb 2019 10:58:39 +0000 (11:58 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 20 Feb 2019 17:55:54 +0000 (19:55 +0200)
In order to be able to get a MAC address before we register the device
with ieee80211 we'll need to load the firmware way earlier.

There seems to be one problem with this: the device seems to start
with radio enabled and starts sending in frames right after the firmware
load finishes. Disable the radio as soon as possible.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Reviewed-by: Steve deRosier <derosier@cal-sierra.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/marvell/libertas_tf/if_usb.c
drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
drivers/net/wireless/marvell/libertas_tf/main.c

index 7a5a1a85dcf76561e0e62b66357e18cd3b0f0e81..a4b9ede707054c16886d7514612ffb5003cc1ea0 100644 (file)
@@ -42,14 +42,14 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
 
 static void if_usb_receive(struct urb *urb);
 static void if_usb_receive_fwload(struct urb *urb);
-static int if_usb_prog_firmware(struct if_usb_card *cardp);
+static int if_usb_prog_firmware(struct lbtf_private *priv);
 static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
                               uint8_t *payload, uint16_t nb);
 static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
                        uint16_t nb, u8 data);
 static void if_usb_free(struct if_usb_card *cardp);
 static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
-static int if_usb_reset_device(struct if_usb_card *cardp);
+static int if_usb_reset_device(struct lbtf_private *priv);
 
 /**
  *  if_usb_wrike_bulk_callback -  call back to handle URB status
@@ -222,13 +222,11 @@ static int if_usb_probe(struct usb_interface *intf,
                goto dealloc;
        }
 
+       cardp->boot2_version = udev->descriptor.bcdDevice;
        priv = lbtf_add_card(cardp, &udev->dev, &if_usb_ops);
        if (!priv)
                goto dealloc;
 
-       cardp->priv = priv;
-       cardp->boot2_version = udev->descriptor.bcdDevice;
-
        usb_get_dev(udev);
        usb_set_intfdata(intf, cardp);
 
@@ -253,7 +251,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
 
        lbtf_deb_enter(LBTF_DEB_MAIN);
 
-       if_usb_reset_device(cardp);
+       if_usb_reset_device(priv);
 
        if (priv)
                lbtf_remove_card(priv);
@@ -336,8 +334,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
        return 0;
 }
 
-static int if_usb_reset_device(struct if_usb_card *cardp)
+static int if_usb_reset_device(struct lbtf_private *priv)
 {
+       struct if_usb_card *cardp = priv->card;
        struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
        int ret;
 
@@ -808,14 +807,17 @@ static int check_fwfile_format(const u8 *data, u32 totlen)
 }
 
 
-static int if_usb_prog_firmware(struct if_usb_card *cardp)
+static int if_usb_prog_firmware(struct lbtf_private *priv)
 {
+       struct if_usb_card *cardp = priv->card;
        int i = 0;
        static int reset_count = 10;
        int ret = 0;
 
        lbtf_deb_enter(LBTF_DEB_USB);
 
+       cardp->priv = priv;
+
        kernel_param_lock(THIS_MODULE);
        ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
        if (ret < 0) {
@@ -851,7 +853,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
 
        if (cardp->bootcmdresp <= 0) {
                if (--reset_count >= 0) {
-                       if_usb_reset_device(cardp);
+                       if_usb_reset_device(priv);
                        goto restart;
                }
                return -1;
@@ -880,7 +882,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
        if (!cardp->fwdnldover) {
                pr_info("failed to load fw, resetting device!\n");
                if (--reset_count >= 0) {
-                       if_usb_reset_device(cardp);
+                       if_usb_reset_device(priv);
                        goto restart;
                }
 
@@ -889,8 +891,6 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
                goto release_fw;
        }
 
-       cardp->priv->fw_ready = 1;
-
  release_fw:
        release_firmware(cardp->fw);
        cardp->fw = NULL;
index 11d5ff68bc5e4fa1e89fbef2d4e92a45334165ca..3ed1fbe28798164908876c547d3a696690ab4809 100644 (file)
@@ -177,8 +177,8 @@ struct lbtf_ops {
        /** Hardware access */
        int (*hw_host_to_card)(struct lbtf_private *priv, u8 type,
                               u8 *payload, u16 nb);
-       int (*hw_prog_firmware)(struct if_usb_card *cardp);
-       int (*hw_reset_device)(struct if_usb_card *cardp);
+       int (*hw_prog_firmware)(struct lbtf_private *priv);
+       int (*hw_reset_device)(struct lbtf_private *priv);
 };
 
 /** Private structure for the MV device */
@@ -254,7 +254,6 @@ struct lbtf_private {
        struct ieee80211_supported_band band;
        struct lbtf_offset_value offsetvalue;
 
-       u8 fw_ready;
        u8 surpriseremoved;
        struct sk_buff_head bc_ps_buf;
 
index a9c04ca75ccc50ce2b0664a09ac783e865ae54ef..d8bf0a4071da8a4d1ae0da93b37d0af4d53b1c01 100644 (file)
@@ -118,11 +118,6 @@ static void lbtf_cmd_work(struct work_struct *work)
        priv->cmd_timed_out = 0;
        spin_unlock_irq(&priv->driver_lock);
 
-       if (!priv->fw_ready) {
-               lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready");
-               return;
-       }
-
        /* Execute the next command */
        if (!priv->cur_cmd)
                lbtf_execute_next_command(priv);
@@ -294,36 +289,29 @@ static void lbtf_tx_work(struct work_struct *work)
 static int lbtf_op_start(struct ieee80211_hw *hw)
 {
        struct lbtf_private *priv = hw->priv;
-       void *card = priv->card;
        int ret = -1;
 
        lbtf_deb_enter(LBTF_DEB_MACOPS);
 
-       if (!priv->fw_ready)
-               /* Upload firmware */
-               if (priv->ops->hw_prog_firmware(card))
-                       goto err_prog_firmware;
-
        /* poke the firmware */
        priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
        priv->radioon = RADIO_ON;
        priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
        ret = lbtf_setup_firmware(priv);
        if (ret)
-               goto err_prog_firmware;
+               goto err_setup_firmware;
 
        if ((priv->fwrelease < LBTF_FW_VER_MIN) ||
            (priv->fwrelease > LBTF_FW_VER_MAX)) {
                ret = -1;
-               goto err_prog_firmware;
+               goto err_setup_firmware;
        }
 
        lbtf_deb_leave(LBTF_DEB_MACOPS);
        return 0;
 
-err_prog_firmware:
-       priv->ops->hw_reset_device(card);
-       lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret);
+err_setup_firmware:
+       lbtf_deb_leave_args(LBTF_DEB_MACOPS, "fw setup error; ret=%d", ret);
        return ret;
 }
 
@@ -554,6 +542,11 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 
        lbtf_deb_enter(LBTF_DEB_RX);
 
+       if (priv->radioon != RADIO_ON) {
+               lbtf_deb_rx("rx before we turned on the radio");
+               goto done;
+       }
+
        prxpd = (struct rxpd *) skb->data;
 
        memset(&stats, 0, sizeof(stats));
@@ -591,13 +584,14 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 
        ieee80211_rx_irqsafe(priv->hw, skb);
 
+done:
        lbtf_deb_leave(LBTF_DEB_RX);
        return 0;
 }
 EXPORT_SYMBOL_GPL(lbtf_rx);
 
 /**
- * lbtf_add_card: Add and initialize the card, no fw upload yet.
+ * lbtf_add_card: Add and initialize the card.
  *
  *  @card    A pointer to card
  *
@@ -623,6 +617,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
        priv->card = card;
        priv->ops = ops;
        priv->tx_skb = NULL;
+       priv->radioon = RADIO_OFF;
 
        hw->queues = 1;
        ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
@@ -646,6 +641,18 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
 
        INIT_WORK(&priv->cmd_work, lbtf_cmd_work);
        INIT_WORK(&priv->tx_work, lbtf_tx_work);
+
+       if (priv->ops->hw_prog_firmware(priv)) {
+               lbtf_deb_usbd(dmdev, "Error programming the firmware\n");
+               priv->ops->hw_reset_device(priv);
+               goto err_init_adapter;
+       }
+
+       /* The firmware seems to start with the radio enabled. Turn it
+        * off before an actual mac80211 start callback is invoked.
+        */
+       lbtf_set_radio_control(priv);
+
        if (ieee80211_register_hw(hw))
                goto err_init_adapter;