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: Lubomir Rintel <lkundrak@v3.sk> Reviewed-by: Steve deRosier <derosier@cal-sierra.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
be9d0d3fe1
commit
baa0280f08
3 changed files with 38 additions and 32 deletions
|
@ -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,
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ restart:
|
||||||
|
|
||||||
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 @@ restart:
|
||||||
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 @@ restart:
|
||||||
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 {
|
||||||
/** 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 {
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue