aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/usb.c
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2014-05-27 06:56:23 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-05-29 13:10:23 -0400
commit5b8045d484d0ef77d6aa9444023220c5671fa3fe (patch)
tree30c506a845f0a6bde6084c6500180e83a6084eec /drivers/net/wireless/brcm80211/brcmfmac/usb.c
parentbd0e1b1d380efe713a612c91417b948e7ebea58d (diff)
brcmfmac: use asynchronous firmware request in USB
This patch adds use of asynchronous firmware request to the driver USB layer. Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/usb.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c98
1 files changed, 68 insertions, 30 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 8d679403518f..21335e2ca0e6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -25,6 +25,7 @@
25#include <dhd_bus.h> 25#include <dhd_bus.h>
26#include <dhd_dbg.h> 26#include <dhd_dbg.h>
27 27
28#include "firmware.h"
28#include "usb_rdl.h" 29#include "usb_rdl.h"
29#include "usb.h" 30#include "usb.h"
30 31
@@ -87,7 +88,7 @@ struct brcmf_usbdev_info {
87 struct brcmf_usbreq *tx_reqs; 88 struct brcmf_usbreq *tx_reqs;
88 struct brcmf_usbreq *rx_reqs; 89 struct brcmf_usbreq *rx_reqs;
89 90
90 u8 *image; /* buffer for combine fw and nvram */ 91 const u8 *image; /* buffer for combine fw and nvram */
91 int image_len; 92 int image_len;
92 93
93 struct usb_device *usbdev; 94 struct usb_device *usbdev;
@@ -1021,7 +1022,7 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
1021 } 1022 }
1022 1023
1023 err = brcmf_usb_dlstart(devinfo, 1024 err = brcmf_usb_dlstart(devinfo,
1024 devinfo->image, devinfo->image_len); 1025 (u8 *)devinfo->image, devinfo->image_len);
1025 if (err == 0) 1026 if (err == 0)
1026 err = brcmf_usb_dlrun(devinfo); 1027 err = brcmf_usb_dlrun(devinfo);
1027 return err; 1028 return err;
@@ -1080,7 +1081,22 @@ static int check_file(const u8 *headers)
1080 return -1; 1081 return -1;
1081} 1082}
1082 1083
1083static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) 1084static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
1085{
1086 switch (devinfo->bus_pub.devid) {
1087 case 43143:
1088 return BRCMF_USB_43143_FW_NAME;
1089 case 43235:
1090 case 43236:
1091 case 43238:
1092 return BRCMF_USB_43236_FW_NAME;
1093 case 43242:
1094 return BRCMF_USB_43242_FW_NAME;
1095 default:
1096 return NULL;
1097 }
1098}
1099static __used int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
1084{ 1100{
1085 s8 *fwname; 1101 s8 *fwname;
1086 const struct firmware *fw; 1102 const struct firmware *fw;
@@ -1202,16 +1218,6 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
1202 goto error; 1218 goto error;
1203 } 1219 }
1204 1220
1205 if (!brcmf_usb_dlneeded(devinfo))
1206 return &devinfo->bus_pub;
1207
1208 brcmf_dbg(USB, "Start fw downloading\n");
1209 if (brcmf_usb_get_fw(devinfo))
1210 goto error;
1211
1212 if (brcmf_usb_fw_download(devinfo))
1213 goto error;
1214
1215 return &devinfo->bus_pub; 1221 return &devinfo->bus_pub;
1216 1222
1217error: 1223error:
@@ -1252,12 +1258,47 @@ fail:
1252 return ret; 1258 return ret;
1253} 1259}
1254 1260
1261static void brcmf_usb_probe_phase2(struct device *dev,
1262 const struct firmware *fw,
1263 void *nvram, u32 nvlen)
1264{
1265 struct brcmf_bus *bus = dev_get_drvdata(dev);
1266 struct brcmf_usbdev_info *devinfo;
1267 int ret;
1268
1269 brcmf_dbg(USB, "Start fw downloading\n");
1270 ret = check_file(fw->data);
1271 if (ret < 0) {
1272 brcmf_err("invalid firmware\n");
1273 release_firmware(fw);
1274 goto error;
1275 }
1276
1277 devinfo = bus->bus_priv.usb->devinfo;
1278 devinfo->image = fw->data;
1279 devinfo->image_len = fw->size;
1280
1281 ret = brcmf_usb_fw_download(devinfo);
1282 release_firmware(fw);
1283 if (ret)
1284 goto error;
1285
1286 ret = brcmf_usb_bus_setup(devinfo);
1287 if (ret)
1288 goto error;
1289
1290 return;
1291error:
1292 brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret);
1293 device_release_driver(dev);
1294}
1295
1255static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) 1296static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
1256{ 1297{
1257 struct brcmf_bus *bus = NULL; 1298 struct brcmf_bus *bus = NULL;
1258 struct brcmf_usbdev *bus_pub = NULL; 1299 struct brcmf_usbdev *bus_pub = NULL;
1259 int ret;
1260 struct device *dev = devinfo->dev; 1300 struct device *dev = devinfo->dev;
1301 int ret;
1261 1302
1262 brcmf_dbg(USB, "Enter\n"); 1303 brcmf_dbg(USB, "Enter\n");
1263 bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ); 1304 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)
1280 bus->proto_type = BRCMF_PROTO_BCDC; 1321 bus->proto_type = BRCMF_PROTO_BCDC;
1281 bus->always_use_fws_queue = true; 1322 bus->always_use_fws_queue = true;
1282 1323
1283 ret = brcmf_usb_bus_setup(devinfo); 1324 if (!brcmf_usb_dlneeded(devinfo)) {
1284 if (ret) { 1325 ret = brcmf_usb_bus_setup(devinfo);
1285 brcmf_err("dongle is not responding\n"); 1326 if (ret)
1286 goto fail; 1327 goto fail;
1287 } 1328 }
1288 1329 /* request firmware here */
1330 brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), NULL,
1331 brcmf_usb_probe_phase2);
1289 return 0; 1332 return 0;
1333
1290fail: 1334fail:
1291 /* Release resources in reverse order */ 1335 /* Release resources in reverse order */
1292 kfree(bus); 1336 kfree(bus);
@@ -1409,12 +1453,8 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
1409 } 1453 }
1410 1454
1411 /* Allocate interrupt URB and data buffer */ 1455 /* Allocate interrupt URB and data buffer */
1412 /* RNDIS says 8-byte intr, our old drivers used 4-byte */ 1456 devinfo->intr_size =
1413 if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16)) 1457 le16_to_cpu(IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize);
1414 devinfo->intr_size = 8;
1415 else
1416 devinfo->intr_size = 4;
1417
1418 devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval; 1458 devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
1419 1459
1420 if (usb->speed == USB_SPEED_SUPER) 1460 if (usb->speed == USB_SPEED_SUPER)
@@ -1481,13 +1521,11 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
1481{ 1521{
1482 struct usb_device *usb = interface_to_usbdev(intf); 1522 struct usb_device *usb = interface_to_usbdev(intf);
1483 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); 1523 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
1484
1485 brcmf_dbg(USB, "Enter\n"); 1524 brcmf_dbg(USB, "Enter\n");
1486 1525
1487 if (!brcmf_usb_fw_download(devinfo)) 1526 return brcmf_fw_get_firmwares(&usb->dev, 0,
1488 return brcmf_usb_bus_setup(devinfo); 1527 brcmf_usb_get_fwname(devinfo), NULL,
1489 1528 brcmf_usb_probe_phase2);
1490 return -EIO;
1491} 1529}
1492 1530
1493#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c 1531#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c