Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -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;
+2 −3
Original line number Diff line number Diff line
@@ -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;

+24 −17
Original line number Diff line number Diff line
@@ -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;