c729fe0269
To work correctly hostapd requires wireless driver to allow interfaces removal. It was working with brcmfmac only partially. Firmware for BCM43602 got some special hack (feature?) that allowed removing all interfaces by disabling mbss mode. It wasn't working with BCM4366 firmware and remaining interfaces were preventing hostapd from starting again. Those patches add support for "interface_remove" firmware method which works with BCM4366 firmware and they make it finally possible to use BCM4366 & brcmfmac & multiple interfaces. Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
97 lines
2.9 KiB
Diff
97 lines
2.9 KiB
Diff
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
|
Date: Mon, 8 Jun 2015 16:11:40 +0200
|
|
Subject: [PATCH] brcmfmac: register wiphy(s) during module_init
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
This is needed by OpenWrt which expects all PHYs to be created after
|
|
module loads successfully.
|
|
|
|
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|
---
|
|
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
|
@@ -1213,6 +1213,7 @@ int __init brcmf_core_init(void)
|
|
{
|
|
if (!schedule_work(&brcmf_driver_work))
|
|
return -EBUSY;
|
|
+ flush_work(&brcmf_driver_work);
|
|
|
|
return 0;
|
|
}
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
|
@@ -444,6 +444,7 @@ struct brcmf_fw {
|
|
u16 bus_nr;
|
|
void (*done)(struct device *dev, const struct firmware *fw,
|
|
void *nvram_image, u32 nvram_len);
|
|
+ struct completion *completion;
|
|
};
|
|
|
|
static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
|
|
@@ -478,6 +479,8 @@ static void brcmf_fw_request_nvram_done(
|
|
goto fail;
|
|
|
|
fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
|
|
+ if (fwctx->completion)
|
|
+ complete(fwctx->completion);
|
|
kfree(fwctx);
|
|
return;
|
|
|
|
@@ -485,6 +488,8 @@ fail:
|
|
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
|
|
release_firmware(fwctx->code);
|
|
device_release_driver(fwctx->dev);
|
|
+ if (fwctx->completion)
|
|
+ complete(fwctx->completion);
|
|
kfree(fwctx);
|
|
}
|
|
|
|
@@ -500,6 +505,8 @@ static void brcmf_fw_request_code_done(c
|
|
/* only requested code so done here */
|
|
if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
|
|
fwctx->done(fwctx->dev, fw, NULL, 0);
|
|
+ if (fwctx->completion)
|
|
+ complete(fwctx->completion);
|
|
kfree(fwctx);
|
|
return;
|
|
}
|
|
@@ -517,6 +524,8 @@ static void brcmf_fw_request_code_done(c
|
|
fail:
|
|
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
|
|
device_release_driver(fwctx->dev);
|
|
+ if (fwctx->completion)
|
|
+ complete(fwctx->completion);
|
|
kfree(fwctx);
|
|
}
|
|
|
|
@@ -528,6 +537,8 @@ int brcmf_fw_get_firmwares_pcie(struct d
|
|
u16 domain_nr, u16 bus_nr)
|
|
{
|
|
struct brcmf_fw *fwctx;
|
|
+ struct completion completion;
|
|
+ int err;
|
|
|
|
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
|
|
if (!fw_cb || !code)
|
|
@@ -548,9 +559,17 @@ int brcmf_fw_get_firmwares_pcie(struct d
|
|
fwctx->domain_nr = domain_nr;
|
|
fwctx->bus_nr = bus_nr;
|
|
|
|
- return request_firmware_nowait(THIS_MODULE, true, code, dev,
|
|
+ init_completion(&completion);
|
|
+ fwctx->completion = &completion;
|
|
+
|
|
+ err = request_firmware_nowait(THIS_MODULE, true, code, dev,
|
|
GFP_KERNEL, fwctx,
|
|
brcmf_fw_request_code_done);
|
|
+ if (!err)
|
|
+ wait_for_completion_timeout(fwctx->completion,
|
|
+ msecs_to_jiffies(5000));
|
|
+ fwctx->completion = NULL;
|
|
+ return err;
|
|
}
|
|
|
|
int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
|