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

Commit 5b8045d4 authored by Arend van Spriel's avatar Arend van Spriel Committed by John W. Linville
Browse files

brcmfmac: use asynchronous firmware request in USB



This patch adds use of asynchronous firmware request to
the driver USB layer.

Reviewed-by: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarDaniel (Deognyoun) Kim <dekim@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent bd0e1b1d
Loading
Loading
Loading
Loading
+68 −30
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <dhd_bus.h>
#include <dhd_dbg.h>

#include "firmware.h"
#include "usb_rdl.h"
#include "usb.h"

@@ -87,7 +88,7 @@ struct brcmf_usbdev_info {
	struct brcmf_usbreq *tx_reqs;
	struct brcmf_usbreq *rx_reqs;

	u8 *image;	/* buffer for combine fw and nvram */
	const u8 *image;	/* buffer for combine fw and nvram */
	int image_len;

	struct usb_device *usbdev;
@@ -1021,7 +1022,7 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
	}

	err = brcmf_usb_dlstart(devinfo,
		devinfo->image, devinfo->image_len);
		(u8 *)devinfo->image, devinfo->image_len);
	if (err == 0)
		err = brcmf_usb_dlrun(devinfo);
	return err;
@@ -1080,7 +1081,22 @@ static int check_file(const u8 *headers)
	return -1;
}

static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
{
	switch (devinfo->bus_pub.devid) {
	case 43143:
		return BRCMF_USB_43143_FW_NAME;
	case 43235:
	case 43236:
	case 43238:
		return BRCMF_USB_43236_FW_NAME;
	case 43242:
		return BRCMF_USB_43242_FW_NAME;
	default:
		return NULL;
	}
}
static __used int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
{
	s8 *fwname;
	const struct firmware *fw;
@@ -1202,16 +1218,6 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
		goto error;
	}

	if (!brcmf_usb_dlneeded(devinfo))
		return &devinfo->bus_pub;

	brcmf_dbg(USB, "Start fw downloading\n");
	if (brcmf_usb_get_fw(devinfo))
		goto error;

	if (brcmf_usb_fw_download(devinfo))
		goto error;

	return &devinfo->bus_pub;

error:
@@ -1252,12 +1258,47 @@ static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
	return ret;
}

static void brcmf_usb_probe_phase2(struct device *dev,
				   const struct firmware *fw,
				   void *nvram, u32 nvlen)
{
	struct brcmf_bus *bus = dev_get_drvdata(dev);
	struct brcmf_usbdev_info *devinfo;
	int ret;

	brcmf_dbg(USB, "Start fw downloading\n");
	ret = check_file(fw->data);
	if (ret < 0) {
		brcmf_err("invalid firmware\n");
		release_firmware(fw);
		goto error;
	}

	devinfo = bus->bus_priv.usb->devinfo;
	devinfo->image = fw->data;
	devinfo->image_len = fw->size;

	ret = brcmf_usb_fw_download(devinfo);
	release_firmware(fw);
	if (ret)
		goto error;

	ret = brcmf_usb_bus_setup(devinfo);
	if (ret)
		goto error;

	return;
error:
	brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret);
	device_release_driver(dev);
}

static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
{
	struct brcmf_bus *bus = NULL;
	struct brcmf_usbdev *bus_pub = NULL;
	int ret;
	struct device *dev = devinfo->dev;
	int ret;

	brcmf_dbg(USB, "Enter\n");
	bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
@@ -1280,13 +1321,16 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
	bus->proto_type = BRCMF_PROTO_BCDC;
	bus->always_use_fws_queue = true;

	if (!brcmf_usb_dlneeded(devinfo)) {
		ret = brcmf_usb_bus_setup(devinfo);
	if (ret) {
		brcmf_err("dongle is not responding\n");
		if (ret)
			goto fail;
	}

	/* request firmware here */
	brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), NULL,
			       brcmf_usb_probe_phase2);
	return 0;

fail:
	/* Release resources in reverse order */
	kfree(bus);
@@ -1409,12 +1453,8 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
	}

	/* Allocate interrupt URB and data buffer */
	/* RNDIS says 8-byte intr, our old drivers used 4-byte */
	if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16))
		devinfo->intr_size = 8;
	else
		devinfo->intr_size = 4;

	devinfo->intr_size =
		le16_to_cpu(IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize);
	devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;

	if (usb->speed == USB_SPEED_SUPER)
@@ -1481,13 +1521,11 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
{
	struct usb_device *usb = interface_to_usbdev(intf);
	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);

	brcmf_dbg(USB, "Enter\n");

	if (!brcmf_usb_fw_download(devinfo))
		return brcmf_usb_bus_setup(devinfo);

	return -EIO;
	return brcmf_fw_get_firmwares(&usb->dev, 0,
				      brcmf_usb_get_fwname(devinfo), NULL,
				      brcmf_usb_probe_phase2);
}

#define BRCMF_USB_VENDOR_ID_BROADCOM	0x0a5c