Commit baa0280f authored by Lubomir Rintel's avatar Lubomir Rintel Committed by Kalle Valo

libertas_tf: don't defer firmware loading until start()

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: default avatarLubomir Rintel <lkundrak@v3.sk>
Reviewed-by: default avatarSteve deRosier <derosier@cal-sierra.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent be9d0d3f
...@@ -42,14 +42,14 @@ MODULE_DEVICE_TABLE(usb, if_usb_table); ...@@ -42,14 +42,14 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb); static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(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, static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
uint8_t *payload, uint16_t nb); uint8_t *payload, uint16_t nb);
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
uint16_t nb, u8 data); uint16_t nb, u8 data);
static void if_usb_free(struct if_usb_card *cardp); 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_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 * if_usb_wrike_bulk_callback - call back to handle URB status
...@@ -222,13 +222,11 @@ static int if_usb_probe(struct usb_interface *intf, ...@@ -222,13 +222,11 @@ static int if_usb_probe(struct usb_interface *intf,
goto dealloc; goto dealloc;
} }
cardp->boot2_version = udev->descriptor.bcdDevice;
priv = lbtf_add_card(cardp, &udev->dev, &if_usb_ops); priv = lbtf_add_card(cardp, &udev->dev, &if_usb_ops);
if (!priv) if (!priv)
goto dealloc; goto dealloc;
cardp->priv = priv;
cardp->boot2_version = udev->descriptor.bcdDevice;
usb_get_dev(udev); usb_get_dev(udev);
usb_set_intfdata(intf, cardp); usb_set_intfdata(intf, cardp);
...@@ -253,7 +251,7 @@ static void if_usb_disconnect(struct usb_interface *intf) ...@@ -253,7 +251,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
lbtf_deb_enter(LBTF_DEB_MAIN); lbtf_deb_enter(LBTF_DEB_MAIN);
if_usb_reset_device(cardp); if_usb_reset_device(priv);
if (priv) if (priv)
lbtf_remove_card(priv); lbtf_remove_card(priv);
...@@ -336,8 +334,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) ...@@ -336,8 +334,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
return 0; 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; struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
int ret; int ret;
...@@ -808,14 +807,17 @@ static int check_fwfile_format(const u8 *data, u32 totlen) ...@@ -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; int i = 0;
static int reset_count = 10; static int reset_count = 10;
int ret = 0; int ret = 0;
lbtf_deb_enter(LBTF_DEB_USB); lbtf_deb_enter(LBTF_DEB_USB);
cardp->priv = priv;
kernel_param_lock(THIS_MODULE); kernel_param_lock(THIS_MODULE);
ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
if (ret < 0) { if (ret < 0) {
...@@ -851,7 +853,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) ...@@ -851,7 +853,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
if (cardp->bootcmdresp <= 0) { if (cardp->bootcmdresp <= 0) {
if (--reset_count >= 0) { if (--reset_count >= 0) {
if_usb_reset_device(cardp); if_usb_reset_device(priv);
goto restart; goto restart;
} }
return -1; return -1;
...@@ -880,7 +882,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) ...@@ -880,7 +882,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
if (!cardp->fwdnldover) { if (!cardp->fwdnldover) {
pr_info("failed to load fw, resetting device!\n"); pr_info("failed to load fw, resetting device!\n");
if (--reset_count >= 0) { if (--reset_count >= 0) {
if_usb_reset_device(cardp); if_usb_reset_device(priv);
goto restart; goto restart;
} }
...@@ -889,8 +891,6 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) ...@@ -889,8 +891,6 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
goto release_fw; goto release_fw;
} }
cardp->priv->fw_ready = 1;
release_fw: release_fw:
release_firmware(cardp->fw); release_firmware(cardp->fw);
cardp->fw = NULL; cardp->fw = NULL;
......
...@@ -177,8 +177,8 @@ struct lbtf_ops { ...@@ -177,8 +177,8 @@ struct lbtf_ops {
/** Hardware access */ /** Hardware access */
int (*hw_host_to_card)(struct lbtf_private *priv, u8 type, int (*hw_host_to_card)(struct lbtf_private *priv, u8 type,
u8 *payload, u16 nb); u8 *payload, u16 nb);
int (*hw_prog_firmware)(struct if_usb_card *cardp); int (*hw_prog_firmware)(struct lbtf_private *priv);
int (*hw_reset_device)(struct if_usb_card *cardp); int (*hw_reset_device)(struct lbtf_private *priv);
}; };
/** Private structure for the MV device */ /** Private structure for the MV device */
...@@ -254,7 +254,6 @@ struct lbtf_private { ...@@ -254,7 +254,6 @@ struct lbtf_private {
struct ieee80211_supported_band band; struct ieee80211_supported_band band;
struct lbtf_offset_value offsetvalue; struct lbtf_offset_value offsetvalue;
u8 fw_ready;
u8 surpriseremoved; u8 surpriseremoved;
struct sk_buff_head bc_ps_buf; struct sk_buff_head bc_ps_buf;
......
...@@ -118,11 +118,6 @@ static void lbtf_cmd_work(struct work_struct *work) ...@@ -118,11 +118,6 @@ static void lbtf_cmd_work(struct work_struct *work)
priv->cmd_timed_out = 0; priv->cmd_timed_out = 0;
spin_unlock_irq(&priv->driver_lock); 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 */ /* Execute the next command */
if (!priv->cur_cmd) if (!priv->cur_cmd)
lbtf_execute_next_command(priv); lbtf_execute_next_command(priv);
...@@ -294,36 +289,29 @@ static void lbtf_tx_work(struct work_struct *work) ...@@ -294,36 +289,29 @@ static void lbtf_tx_work(struct work_struct *work)
static int lbtf_op_start(struct ieee80211_hw *hw) static int lbtf_op_start(struct ieee80211_hw *hw)
{ {
struct lbtf_private *priv = hw->priv; struct lbtf_private *priv = hw->priv;
void *card = priv->card;
int ret = -1; int ret = -1;
lbtf_deb_enter(LBTF_DEB_MACOPS); 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 */ /* poke the firmware */
priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
priv->radioon = RADIO_ON; priv->radioon = RADIO_ON;
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
ret = lbtf_setup_firmware(priv); ret = lbtf_setup_firmware(priv);
if (ret) if (ret)
goto err_prog_firmware; goto err_setup_firmware;
if ((priv->fwrelease < LBTF_FW_VER_MIN) || if ((priv->fwrelease < LBTF_FW_VER_MIN) ||
(priv->fwrelease > LBTF_FW_VER_MAX)) { (priv->fwrelease > LBTF_FW_VER_MAX)) {
ret = -1; ret = -1;
goto err_prog_firmware; goto err_setup_firmware;
} }
lbtf_deb_leave(LBTF_DEB_MACOPS); lbtf_deb_leave(LBTF_DEB_MACOPS);
return 0; return 0;
err_prog_firmware: err_setup_firmware:
priv->ops->hw_reset_device(card); lbtf_deb_leave_args(LBTF_DEB_MACOPS, "fw setup error; ret=%d", ret);
lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret);
return ret; return ret;
} }
...@@ -554,6 +542,11 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) ...@@ -554,6 +542,11 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
lbtf_deb_enter(LBTF_DEB_RX); 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; prxpd = (struct rxpd *) skb->data;
memset(&stats, 0, sizeof(stats)); memset(&stats, 0, sizeof(stats));
...@@ -591,13 +584,14 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) ...@@ -591,13 +584,14 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
ieee80211_rx_irqsafe(priv->hw, skb); ieee80211_rx_irqsafe(priv->hw, skb);
done:
lbtf_deb_leave(LBTF_DEB_RX); lbtf_deb_leave(LBTF_DEB_RX);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(lbtf_rx); 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 * @card A pointer to card
* *
...@@ -623,6 +617,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev, ...@@ -623,6 +617,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
priv->card = card; priv->card = card;
priv->ops = ops; priv->ops = ops;
priv->tx_skb = NULL; priv->tx_skb = NULL;
priv->radioon = RADIO_OFF;
hw->queues = 1; hw->queues = 1;
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
...@@ -646,6 +641,18 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev, ...@@ -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->cmd_work, lbtf_cmd_work);
INIT_WORK(&priv->tx_work, lbtf_tx_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)) if (ieee80211_register_hw(hw))
goto err_init_adapter; goto err_init_adapter;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment