mac80211: brcmfmac: support dumping stations
authorRafał Miłecki <zajec5@gmail.com>
Sun, 10 Jan 2016 00:19:16 +0000 (00:19 +0000)
committerRafał Miłecki <zajec5@gmail.com>
Sun, 10 Jan 2016 00:19:16 +0000 (00:19 +0000)
It allows user-space fetch associated STAs and e.g. iwinfo/luci display
them.

SVN-Revision: 48167

13 files changed:
package/kernel/mac80211/patches/371-brcmfmac-include-linux-atomic.h.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0001-brcmfmac-expose-device-memory-to-devcoredump-subsyst.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0002-brcmfmac-Fix-race-condition-between-USB-probe-load-a.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0003-brcmfmac-rename-firmware_path-to-alternative_fw_path.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0004-brcmfmac-remove-conversational-comment.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0005-brcmfmac-Rework-p2p-attach-use-single-method-for-p2p.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0006-brcmfmac-Fix-station-info-rate-information.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0007-brcmfmac-Add-RSSI-information-to-get_station.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0008-brcmfmac-Add-dump_station-support-to-cfg80221-ops.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0009-brcmfmac-Move-brcmf_c_preinit_dcmds-prototype-to-cor.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0010-brcmfmac-Remove-unused-state-AP-creating.patch [new file with mode: 0644]
package/kernel/mac80211/patches/372-0011-brcmfmac-Properly-set-carrier-state-of-netdev.patch [new file with mode: 0644]
package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch

diff --git a/package/kernel/mac80211/patches/371-brcmfmac-include-linux-atomic.h.patch b/package/kernel/mac80211/patches/371-brcmfmac-include-linux-atomic.h.patch
new file mode 100644 (file)
index 0000000..9311a9d
--- /dev/null
@@ -0,0 +1,23 @@
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 19 Sep 2015 12:47:20 +0200
+Subject: [PATCH] brcmfmac: include linux/atomic.h
+
+brcmfmac uses atomic_or() and other atomic_* functions, but does not
+include linux/atomic.h. This file gets included by some other header
+file so this normally does not cause problems.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+Acked-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+@@ -15,6 +15,7 @@
+  */
+ #include <linux/types.h>
++#include <linux/atomic.h>
+ #include <linux/kernel.h>
+ #include <linux/kthread.h>
+ #include <linux/printk.h>
diff --git a/package/kernel/mac80211/patches/372-0001-brcmfmac-expose-device-memory-to-devcoredump-subsyst.patch b/package/kernel/mac80211/patches/372-0001-brcmfmac-expose-device-memory-to-devcoredump-subsyst.patch
new file mode 100644 (file)
index 0000000..cf3f278
--- /dev/null
@@ -0,0 +1,347 @@
+From: Arend van Spriel <arend@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:11 +0200
+Subject: [PATCH] brcmfmac: expose device memory to devcoredump subsystem
+
+Upon PSM watchdog event received from firmware the driver will obtain
+a memory snapshot of the device and expose it to user-space through
+the devcoredump framework. This will trigger a uevent.
+
+Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/Kconfig
++++ b/drivers/net/wireless/brcm80211/Kconfig
+@@ -85,5 +85,6 @@ config BRCM_TRACING
+ config BRCMDBG
+       bool "Broadcom driver debug functions"
+       depends on BRCMSMAC || BRCMFMAC
++      select WANT_DEV_COREDUMP
+       ---help---
+         Selecting this enables additional code for debug purposes.
+--- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h
+@@ -65,6 +65,8 @@ struct brcmf_bus_dcmd {
+  * @rxctl: receive a control response message from dongle.
+  * @gettxq: obtain a reference of bus transmit queue (optional).
+  * @wowl_config: specify if dongle is configured for wowl when going to suspend
++ * @get_ramsize: obtain size of device memory.
++ * @get_memdump: obtain device memory dump in provided buffer.
+  *
+  * This structure provides an abstract interface towards the
+  * bus specific driver. For control messages to common driver
+@@ -79,6 +81,8 @@ struct brcmf_bus_ops {
+       int (*rxctl)(struct device *dev, unsigned char *msg, uint len);
+       struct pktq * (*gettxq)(struct device *dev);
+       void (*wowl_config)(struct device *dev, bool enabled);
++      size_t (*get_ramsize)(struct device *dev);
++      int (*get_memdump)(struct device *dev, void *data, size_t len);
+ };
+@@ -185,6 +189,23 @@ void brcmf_bus_wowl_config(struct brcmf_
+               bus->ops->wowl_config(bus->dev, enabled);
+ }
++static inline size_t brcmf_bus_get_ramsize(struct brcmf_bus *bus)
++{
++      if (!bus->ops->get_ramsize)
++              return 0;
++
++      return bus->ops->get_ramsize(bus->dev);
++}
++
++static inline
++int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)
++{
++      if (!bus->ops->get_memdump)
++              return -EOPNOTSUPP;
++
++      return bus->ops->get_memdump(bus->dev, data, len);
++}
++
+ /*
+  * interface functions from common layer
+  */
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -957,8 +957,8 @@ int brcmf_attach(struct device *dev)
+       drvr->bus_if = dev_get_drvdata(dev);
+       drvr->bus_if->drvr = drvr;
+-      /* create device debugfs folder */
+-      brcmf_debugfs_attach(drvr);
++      /* attach debug facilities */
++      brcmf_debug_attach(drvr);
+       /* Attach and link in the protocol */
+       ret = brcmf_proto_attach(drvr);
+@@ -1155,7 +1155,7 @@ void brcmf_detach(struct device *dev)
+       brcmf_proto_detach(drvr);
+-      brcmf_debugfs_detach(drvr);
++      brcmf_debug_detach(drvr);
+       bus_if->drvr = NULL;
+       kfree(drvr);
+ }
+--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+@@ -16,15 +16,45 @@
+ #include <linux/debugfs.h>
+ #include <linux/netdevice.h>
+ #include <linux/module.h>
++#include <linux/devcoredump.h>
+ #include <brcmu_wifi.h>
+ #include <brcmu_utils.h>
+ #include "core.h"
+ #include "bus.h"
++#include "fweh.h"
+ #include "debug.h"
+ static struct dentry *root_folder;
++static int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
++                                    size_t len)
++{
++      void *dump;
++      size_t ramsize;
++
++      ramsize = brcmf_bus_get_ramsize(bus);
++      if (ramsize) {
++              dump = vzalloc(len + ramsize);
++              if (!dump)
++                      return -ENOMEM;
++              memcpy(dump, data, len);
++              brcmf_bus_get_memdump(bus, dump + len, ramsize);
++              dev_coredumpv(bus->dev, dump, len + ramsize, GFP_KERNEL);
++      }
++      return 0;
++}
++
++static int brcmf_debug_psm_watchdog_notify(struct brcmf_if *ifp,
++                                         const struct brcmf_event_msg *evtmsg,
++                                         void *data)
++{
++      brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
++
++      return brcmf_debug_create_memdump(ifp->drvr->bus_if, data,
++                                        evtmsg->datalen);
++}
++
+ void brcmf_debugfs_init(void)
+ {
+       root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
+@@ -41,7 +71,7 @@ void brcmf_debugfs_exit(void)
+       root_folder = NULL;
+ }
+-int brcmf_debugfs_attach(struct brcmf_pub *drvr)
++int brcmf_debug_attach(struct brcmf_pub *drvr)
+ {
+       struct device *dev = drvr->bus_if->dev;
+@@ -49,12 +79,18 @@ int brcmf_debugfs_attach(struct brcmf_pu
+               return -ENODEV;
+       drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
++      if (IS_ERR(drvr->dbgfs_dir))
++              return PTR_ERR(drvr->dbgfs_dir);
+-      return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
++
++      return brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG,
++                                 brcmf_debug_psm_watchdog_notify);
+ }
+-void brcmf_debugfs_detach(struct brcmf_pub *drvr)
++void brcmf_debug_detach(struct brcmf_pub *drvr)
+ {
++      brcmf_fweh_unregister(drvr, BRCMF_E_PSM_WATCHDOG);
++
+       if (!IS_ERR_OR_NULL(drvr->dbgfs_dir))
+               debugfs_remove_recursive(drvr->dbgfs_dir);
+ }
+--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h
+@@ -109,8 +109,8 @@ struct brcmf_pub;
+ #ifdef DEBUG
+ void brcmf_debugfs_init(void);
+ void brcmf_debugfs_exit(void);
+-int brcmf_debugfs_attach(struct brcmf_pub *drvr);
+-void brcmf_debugfs_detach(struct brcmf_pub *drvr);
++int brcmf_debug_attach(struct brcmf_pub *drvr);
++void brcmf_debug_detach(struct brcmf_pub *drvr);
+ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
+ int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+                           int (*read_fn)(struct seq_file *seq, void *data));
+@@ -121,11 +121,11 @@ static inline void brcmf_debugfs_init(vo
+ static inline void brcmf_debugfs_exit(void)
+ {
+ }
+-static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr)
++static inline int brcmf_debug_attach(struct brcmf_pub *drvr)
+ {
+       return 0;
+ }
+-static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
++static inline void brcmf_debug_detach(struct brcmf_pub *drvr)
+ {
+ }
+ static inline
+--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+@@ -448,6 +448,47 @@ brcmf_pcie_copy_mem_todev(struct brcmf_p
+ }
++static void
++brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
++                        void *dstaddr, u32 len)
++{
++      void __iomem *address = devinfo->tcm + mem_offset;
++      __le32 *dst32;
++      __le16 *dst16;
++      u8 *dst8;
++
++      if (((ulong)address & 4) || ((ulong)dstaddr & 4) || (len & 4)) {
++              if (((ulong)address & 2) || ((ulong)dstaddr & 2) || (len & 2)) {
++                      dst8 = (u8 *)dstaddr;
++                      while (len) {
++                              *dst8 = ioread8(address);
++                              address++;
++                              dst8++;
++                              len--;
++                      }
++              } else {
++                      len = len / 2;
++                      dst16 = (__le16 *)dstaddr;
++                      while (len) {
++                              *dst16 = cpu_to_le16(ioread16(address));
++                              address += 2;
++                              dst16++;
++                              len--;
++                      }
++              }
++      } else {
++              len = len / 4;
++              dst32 = (__le32 *)dstaddr;
++              while (len) {
++                      *dst32 = cpu_to_le32(ioread32(address));
++                      address += 4;
++                      dst32++;
++                      len--;
++              }
++      }
++}
++
++
+ #define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \
+               CHIPCREGOFFS(reg), value)
+@@ -1352,12 +1393,36 @@ static void brcmf_pcie_wowl_config(struc
+ }
++static size_t brcmf_pcie_get_ramsize(struct device *dev)
++{
++      struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++      struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
++      struct brcmf_pciedev_info *devinfo = buspub->devinfo;
++
++      return devinfo->ci->ramsize - devinfo->ci->srsize;
++}
++
++
++static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
++{
++      struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++      struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
++      struct brcmf_pciedev_info *devinfo = buspub->devinfo;
++
++      brcmf_dbg(PCIE, "dump at 0x%08X: len=%zu\n", devinfo->ci->rambase, len);
++      brcmf_pcie_copy_dev_tomem(devinfo, devinfo->ci->rambase, data, len);
++      return 0;
++}
++
++
+ static struct brcmf_bus_ops brcmf_pcie_bus_ops = {
+       .txdata = brcmf_pcie_tx,
+       .stop = brcmf_pcie_down,
+       .txctl = brcmf_pcie_tx_ctlpkt,
+       .rxctl = brcmf_pcie_rx_ctlpkt,
+       .wowl_config = brcmf_pcie_wowl_config,
++      .get_ramsize = brcmf_pcie_get_ramsize,
++      .get_memdump = brcmf_pcie_get_memdump,
+ };
+--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+@@ -3539,6 +3539,51 @@ done:
+       return err;
+ }
++static size_t brcmf_sdio_bus_get_ramsize(struct device *dev)
++{
++      struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++      struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
++      struct brcmf_sdio *bus = sdiodev->bus;
++
++      return bus->ci->ramsize - bus->ci->srsize;
++}
++
++static int brcmf_sdio_bus_get_memdump(struct device *dev, void *data,
++                                    size_t mem_size)
++{
++      struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++      struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
++      struct brcmf_sdio *bus = sdiodev->bus;
++      int err;
++      int address;
++      int offset;
++      int len;
++
++      brcmf_dbg(INFO, "dump at 0x%08x: size=%zu\n", bus->ci->rambase,
++                mem_size);
++
++      address = bus->ci->rambase;
++      offset = err = 0;
++      sdio_claim_host(sdiodev->func[1]);
++      while (offset < mem_size) {
++              len = ((offset + MEMBLOCK) < mem_size) ? MEMBLOCK :
++                    mem_size - offset;
++              err = brcmf_sdiod_ramrw(sdiodev, false, address, data, len);
++              if (err) {
++                      brcmf_err("error %d on reading %d membytes at 0x%08x\n",
++                                err, len, address);
++                      goto done;
++              }
++              data += len;
++              offset += len;
++              address += len;
++      }
++
++done:
++      sdio_release_host(sdiodev->func[1]);
++      return err;
++}
++
+ void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus)
+ {
+       if (!bus->dpc_triggered) {
+@@ -3987,7 +4032,9 @@ static struct brcmf_bus_ops brcmf_sdio_b
+       .txctl = brcmf_sdio_bus_txctl,
+       .rxctl = brcmf_sdio_bus_rxctl,
+       .gettxq = brcmf_sdio_bus_gettxq,
+-      .wowl_config = brcmf_sdio_wowl_config
++      .wowl_config = brcmf_sdio_wowl_config,
++      .get_ramsize = brcmf_sdio_bus_get_ramsize,
++      .get_memdump = brcmf_sdio_bus_get_memdump,
+ };
+ static void brcmf_sdio_firmware_callback(struct device *dev,
diff --git a/package/kernel/mac80211/patches/372-0002-brcmfmac-Fix-race-condition-between-USB-probe-load-a.patch b/package/kernel/mac80211/patches/372-0002-brcmfmac-Fix-race-condition-between-USB-probe-load-a.patch
new file mode 100644 (file)
index 0000000..5b82bca
--- /dev/null
@@ -0,0 +1,108 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:12 +0200
+Subject: [PATCH] brcmfmac: Fix race condition between USB probe/load and
+ disconnect.
+
+When a USB device gets disconnected due to for example removal
+then it is possible that it is still in the loading phase due to
+the asynchronous load routines. These routines can then possible
+access memory which has been freed. Fix this by mutex locking the
+device init phase.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+@@ -144,6 +144,7 @@ struct brcmf_usbdev_info {
+       struct usb_device *usbdev;
+       struct device *dev;
++      struct mutex dev_init_lock;
+       int ctl_in_pipe, ctl_out_pipe;
+       struct urb *ctl_urb; /* URB for control endpoint */
+@@ -1204,6 +1205,8 @@ static void brcmf_usb_probe_phase2(struc
+       int ret;
+       brcmf_dbg(USB, "Start fw downloading\n");
++
++      devinfo = bus->bus_priv.usb->devinfo;
+       ret = check_file(fw->data);
+       if (ret < 0) {
+               brcmf_err("invalid firmware\n");
+@@ -1211,7 +1214,6 @@ static void brcmf_usb_probe_phase2(struc
+               goto error;
+       }
+-      devinfo = bus->bus_priv.usb->devinfo;
+       devinfo->image = fw->data;
+       devinfo->image_len = fw->size;
+@@ -1224,9 +1226,11 @@ static void brcmf_usb_probe_phase2(struc
+       if (ret)
+               goto error;
++      mutex_unlock(&devinfo->dev_init_lock);
+       return;
+ error:
+       brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret);
++      mutex_unlock(&devinfo->dev_init_lock);
+       device_release_driver(dev);
+ }
+@@ -1264,6 +1268,7 @@ static int brcmf_usb_probe_cb(struct brc
+               if (ret)
+                       goto fail;
+               /* we are done */
++              mutex_unlock(&devinfo->dev_init_lock);
+               return 0;
+       }
+       bus->chip = bus_pub->devid;
+@@ -1317,6 +1322,12 @@ brcmf_usb_probe(struct usb_interface *in
+       devinfo->usbdev = usb;
+       devinfo->dev = &usb->dev;
++      /* Take an init lock, to protect for disconnect while still loading.
++       * Necessary because of the asynchronous firmware load construction
++       */
++      mutex_init(&devinfo->dev_init_lock);
++      mutex_lock(&devinfo->dev_init_lock);
++
+       usb_set_intfdata(intf, devinfo);
+       /* Check that the device supports only one configuration */
+@@ -1391,6 +1402,7 @@ brcmf_usb_probe(struct usb_interface *in
+       return 0;
+ fail:
++      mutex_unlock(&devinfo->dev_init_lock);
+       kfree(devinfo);
+       usb_set_intfdata(intf, NULL);
+       return ret;
+@@ -1403,8 +1415,19 @@ brcmf_usb_disconnect(struct usb_interfac
+       brcmf_dbg(USB, "Enter\n");
+       devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
+-      brcmf_usb_disconnect_cb(devinfo);
+-      kfree(devinfo);
++
++      if (devinfo) {
++              mutex_lock(&devinfo->dev_init_lock);
++              /* Make sure that devinfo still exists. Firmware probe routines
++               * may have released the device and cleared the intfdata.
++               */
++              if (!usb_get_intfdata(intf))
++                      goto done;
++
++              brcmf_usb_disconnect_cb(devinfo);
++              kfree(devinfo);
++      }
++done:
+       brcmf_dbg(USB, "Exit\n");
+ }
diff --git a/package/kernel/mac80211/patches/372-0003-brcmfmac-rename-firmware_path-to-alternative_fw_path.patch b/package/kernel/mac80211/patches/372-0003-brcmfmac-rename-firmware_path-to-alternative_fw_path.patch
new file mode 100644 (file)
index 0000000..f877c23
--- /dev/null
@@ -0,0 +1,28 @@
+From: Franky Lin <frankyl@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:13 +0200
+Subject: [PATCH] brcmfmac: rename firmware_path to alternative_fw_path
+
+In brcmfmac the module parameter "firmware_path" is used as an
+alternative relative path under the search path used by firmware_class
+or ueventhelper. Rename the parameter to alternative_fw_path to avoid
+confusion.
+
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Franky Lin <frankyl@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+@@ -28,7 +28,7 @@
+ #define BRCMF_FW_NVRAM_PCIEDEV_LEN            10      /* pcie/1/4/ + \0 */
+ char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
+-module_param_string(firmware_path, brcmf_firmware_path,
++module_param_string(alternative_fw_path, brcmf_firmware_path,
+                   BRCMF_FW_PATH_LEN, 0440);
+ enum nvram_parser_state {
diff --git a/package/kernel/mac80211/patches/372-0004-brcmfmac-remove-conversational-comment.patch b/package/kernel/mac80211/patches/372-0004-brcmfmac-remove-conversational-comment.patch
new file mode 100644 (file)
index 0000000..0bfd9ef
--- /dev/null
@@ -0,0 +1,25 @@
+From: Arend van Spriel <arend@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:14 +0200
+Subject: [PATCH] brcmfmac: remove conversational comment
+
+Removing a comment that was only useful during the review of
+the change that introduced it and which should never have been
+submitted.
+
+Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+@@ -873,9 +873,6 @@ brcmf_msgbuf_process_txstatus(struct brc
+       commonring = msgbuf->flowrings[flowid];
+       atomic_dec(&commonring->outstanding_tx);
+-      /* Hante: i believe this was a bug as tx_status->msg.ifidx was used
+-       * in brcmf_txfinalize as index in drvr->iflist. Can you confirm/deny?
+-       */
+       brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx),
+                        skb, true);
+ }
diff --git a/package/kernel/mac80211/patches/372-0005-brcmfmac-Rework-p2p-attach-use-single-method-for-p2p.patch b/package/kernel/mac80211/patches/372-0005-brcmfmac-Rework-p2p-attach-use-single-method-for-p2p.patch
new file mode 100644 (file)
index 0000000..3ffada8
--- /dev/null
@@ -0,0 +1,226 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:15 +0200
+Subject: [PATCH] brcmfmac: Rework p2p attach, use single method for p2p dev
+ creation.
+
+When module param p2pon is used a p2p device is created at init.
+This patch reworks how this is done by using the same method as
+for a dynamically (by user space) created p2p device.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -6237,6 +6237,17 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+               else
+                       *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+       }
++      /* p2p might require that "if-events" get processed by fweh. So
++       * activate the already registered event handlers now and activate
++       * the rest when initialization has completed. drvr->config needs to
++       * be assigned before activating events.
++       */
++      drvr->config = cfg;
++      err = brcmf_fweh_activate_events(ifp);
++      if (err) {
++              brcmf_err("FWEH activation failed (%d)\n", err);
++              goto wiphy_unreg_out;
++      }
+       err = brcmf_p2p_attach(cfg, p2pdev_forced);
+       if (err) {
+@@ -6259,6 +6270,13 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+                                   brcmf_notify_tdls_peer_event);
+       }
++      /* (re-) activate FWEH event handling */
++      err = brcmf_fweh_activate_events(ifp);
++      if (err) {
++              brcmf_err("FWEH activation failed (%d)\n", err);
++              goto wiphy_unreg_out;
++      }
++
+       return cfg;
+ wiphy_unreg_out:
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -828,8 +828,8 @@ struct brcmf_if *brcmf_add_if(struct brc
+       } else {
+               brcmf_dbg(INFO, "allocate netdev interface\n");
+               /* Allocate netdev, including space for private structure */
+-              ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN,
+-                                  ether_setup);
++              ndev = alloc_netdev(sizeof(*ifp), is_p2pdev ? "p2p%d" : name,
++                                  NET_NAME_UNKNOWN, ether_setup);
+               if (!ndev)
+                       return ERR_PTR(-ENOMEM);
+@@ -1021,12 +1021,7 @@ int brcmf_bus_start(struct device *dev)
+       if (IS_ERR(ifp))
+               return PTR_ERR(ifp);
+-      if (brcmf_p2p_enable)
+-              p2p_ifp = brcmf_add_if(drvr, 1, 0, false, "p2p%d", NULL);
+-      else
+-              p2p_ifp = NULL;
+-      if (IS_ERR(p2p_ifp))
+-              p2p_ifp = NULL;
++      p2p_ifp = NULL;
+       /* signal bus ready */
+       brcmf_bus_change_state(bus_if, BRCMF_BUS_UP);
+@@ -1060,11 +1055,13 @@ int brcmf_bus_start(struct device *dev)
+               goto fail;
+       }
+-      ret = brcmf_fweh_activate_events(ifp);
+-      if (ret < 0)
+-              goto fail;
+-
+       ret = brcmf_net_attach(ifp, false);
++
++      if ((!ret) && (brcmf_p2p_enable)) {
++              p2p_ifp = drvr->iflist[1];
++              if (p2p_ifp)
++                      ret = brcmf_net_p2p_attach(p2p_ifp);
++      }
+ fail:
+       if (ret < 0) {
+               brcmf_err("failed: %d\n", ret);
+@@ -1076,20 +1073,12 @@ fail:
+                       brcmf_fws_del_interface(ifp);
+                       brcmf_fws_deinit(drvr);
+               }
+-              if (drvr->iflist[0]) {
++              if (ifp)
+                       brcmf_net_detach(ifp->ndev);
+-                      drvr->iflist[0] = NULL;
+-              }
+-              if (p2p_ifp) {
++              if (p2p_ifp)
+                       brcmf_net_detach(p2p_ifp->ndev);
+-                      drvr->iflist[1] = NULL;
+-              }
+               return ret;
+       }
+-      if ((brcmf_p2p_enable) && (p2p_ifp))
+-              if (brcmf_net_p2p_attach(p2p_ifp) < 0)
+-                      brcmf_p2p_enable = 0;
+-
+       return 0;
+ }
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+@@ -213,7 +213,8 @@ static void brcmf_fweh_handle_if_event(s
+                                  is_p2pdev, emsg->ifname, emsg->addr);
+               if (IS_ERR(ifp))
+                       return;
+-              brcmf_fws_add_interface(ifp);
++              if (!is_p2pdev)
++                      brcmf_fws_add_interface(ifp);
+               if (!drvr->fweh.evt_handler[BRCMF_E_IF])
+                       if (brcmf_net_attach(ifp, false) < 0)
+                               return;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+@@ -2350,83 +2350,30 @@ void brcmf_p2p_stop_device(struct wiphy
+  * brcmf_p2p_attach() - attach for P2P.
+  *
+  * @cfg: driver private data for cfg80211 interface.
++ * @p2pdev_forced: create p2p device interface at attach.
+  */
+ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced)
+ {
+-      struct brcmf_if *pri_ifp;
+-      struct brcmf_if *p2p_ifp;
+-      struct brcmf_cfg80211_vif *p2p_vif;
+       struct brcmf_p2p_info *p2p;
+-      struct brcmf_pub *drvr;
+-      s32 bssidx;
++      struct brcmf_if *pri_ifp;
+       s32 err = 0;
++      void *err_ptr;
+       p2p = &cfg->p2p;
+       p2p->cfg = cfg;
+-      drvr = cfg->pub;
+-
+-      pri_ifp = brcmf_get_ifp(drvr, 0);
++      pri_ifp = brcmf_get_ifp(cfg->pub, 0);
+       p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
+       if (p2pdev_forced) {
+-              p2p_ifp = drvr->iflist[1];
++              err_ptr = brcmf_p2p_create_p2pdev(p2p, NULL, NULL);
++              if (IS_ERR(err_ptr)) {
++                      brcmf_err("P2P device creation failed.\n");
++                      err = PTR_ERR(err_ptr);
++              }
+       } else {
+-              p2p_ifp = NULL;
+               p2p->p2pdev_dynamically = true;
+       }
+-      if (p2p_ifp) {
+-              p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
+-                                        false);
+-              if (IS_ERR(p2p_vif)) {
+-                      brcmf_err("could not create discovery vif\n");
+-                      err = -ENOMEM;
+-                      goto exit;
+-              }
+-
+-              p2p_vif->ifp = p2p_ifp;
+-              p2p_ifp->vif = p2p_vif;
+-              p2p_vif->wdev.netdev = p2p_ifp->ndev;
+-              p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
+-              SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
+-
+-              p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
+-
+-              brcmf_p2p_generate_bss_mac(p2p, NULL);
+-              memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
+-              brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
+-
+-              brcmf_fweh_p2pdev_setup(pri_ifp, true);
+-
+-              /* Initialize P2P Discovery in the firmware */
+-              err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
+-              if (err < 0) {
+-                      brcmf_err("set p2p_disc error\n");
+-                      brcmf_free_vif(p2p_vif);
+-                      goto exit;
+-              }
+-              /* obtain bsscfg index for P2P discovery */
+-              err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
+-              if (err < 0) {
+-                      brcmf_err("retrieving discover bsscfg index failed\n");
+-                      brcmf_free_vif(p2p_vif);
+-                      goto exit;
+-              }
+-              /* Verify that firmware uses same bssidx as driver !! */
+-              if (p2p_ifp->bssidx != bssidx) {
+-                      brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
+-                                bssidx, p2p_ifp->bssidx);
+-                      brcmf_free_vif(p2p_vif);
+-                      goto exit;
+-              }
+-
+-              init_completion(&p2p->send_af_done);
+-              INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
+-              init_completion(&p2p->afx_hdl.act_frm_scan);
+-              init_completion(&p2p->wait_next_af);
+-exit:
+-              brcmf_fweh_p2pdev_setup(pri_ifp, false);
+-      }
+       return err;
+ }
diff --git a/package/kernel/mac80211/patches/372-0006-brcmfmac-Fix-station-info-rate-information.patch b/package/kernel/mac80211/patches/372-0006-brcmfmac-Fix-station-info-rate-information.patch
new file mode 100644 (file)
index 0000000..0abcf1e
--- /dev/null
@@ -0,0 +1,36 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:16 +0200
+Subject: [PATCH] brcmfmac: Fix station info rate information.
+
+Txrate and rxrate in get_station got assigned first with value
+in kbps and then divided by 100 to get it in 100kbps unit. The
+problem with that is that type of rate is u16 which resulted
+in incorrect values for high data rate values.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -2477,13 +2477,13 @@ brcmf_cfg80211_get_station(struct wiphy
+               sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
+               if (sinfo->tx_packets) {
+                       sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
+-                      sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate);
+-                      sinfo->txrate.legacy /= 100;
++                      sinfo->txrate.legacy =
++                              le32_to_cpu(sta_info_le.tx_rate) / 100;
+               }
+               if (sinfo->rx_packets) {
+                       sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
+-                      sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate);
+-                      sinfo->rxrate.legacy /= 100;
++                      sinfo->rxrate.legacy =
++                              le32_to_cpu(sta_info_le.rx_rate) / 100;
+               }
+               if (le16_to_cpu(sta_info_le.ver) >= 4) {
+                       sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
diff --git a/package/kernel/mac80211/patches/372-0007-brcmfmac-Add-RSSI-information-to-get_station.patch b/package/kernel/mac80211/patches/372-0007-brcmfmac-Add-RSSI-information-to-get_station.patch
new file mode 100644 (file)
index 0000000..bb03d67
--- /dev/null
@@ -0,0 +1,50 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:17 +0200
+Subject: [PATCH] brcmfmac: Add RSSI information to get_station.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -2431,6 +2431,9 @@ brcmf_cfg80211_get_station(struct wiphy
+       struct brcmf_sta_info_le sta_info_le;
+       u32 sta_flags;
+       u32 is_tdls_peer;
++      s32 total_rssi;
++      s32 count_rssi;
++      u32 i;
+       brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
+       if (!check_vif_up(ifp->vif))
+@@ -2491,6 +2494,26 @@ brcmf_cfg80211_get_station(struct wiphy
+                       sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
+                       sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
+               }
++              total_rssi = 0;
++              count_rssi = 0;
++              for (i = 0; i < BRCMF_ANT_MAX; i++) {
++                      if (sta_info_le.rssi[i]) {
++                              sinfo->chain_signal_avg[count_rssi] =
++                                      sta_info_le.rssi[i];
++                              sinfo->chain_signal[count_rssi] =
++                                      sta_info_le.rssi[i];
++                              total_rssi += sta_info_le.rssi[i];
++                              count_rssi++;
++                      }
++              }
++              if (count_rssi) {
++                      sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL);
++                      sinfo->chains = count_rssi;
++
++                      sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
++                      total_rssi /= count_rssi;
++                      sinfo->signal = total_rssi;
++              }
+       }
+ done:
+       brcmf_dbg(TRACE, "Exit\n");
diff --git a/package/kernel/mac80211/patches/372-0008-brcmfmac-Add-dump_station-support-to-cfg80221-ops.patch b/package/kernel/mac80211/patches/372-0008-brcmfmac-Add-dump_station-support-to-cfg80221-ops.patch
new file mode 100644 (file)
index 0000000..a6bafd2
--- /dev/null
@@ -0,0 +1,107 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:18 +0200
+Subject: [PATCH] brcmfmac: Add dump_station support to cfg80221 ops.
+
+With this feature it becomes possible to request a station
+assoc list.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -2520,6 +2520,35 @@ done:
+       return err;
+ }
++static int
++brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
++                          int idx, u8 *mac, struct station_info *sinfo)
++{
++      struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
++      struct brcmf_if *ifp = netdev_priv(ndev);
++      s32 err;
++
++      brcmf_dbg(TRACE, "Enter, idx %d\n", idx);
++
++      if (idx == 0) {
++              cfg->assoclist.count = cpu_to_le32(BRCMF_MAX_ASSOCLIST);
++              err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_ASSOCLIST,
++                                           &cfg->assoclist,
++                                           sizeof(cfg->assoclist));
++              if (err) {
++                      brcmf_err("BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n",
++                                err);
++                      cfg->assoclist.count = 0;
++                      return -EOPNOTSUPP;
++              }
++      }
++      if (idx < le32_to_cpu(cfg->assoclist.count)) {
++              memcpy(mac, cfg->assoclist.mac[idx], ETH_ALEN);
++              return brcmf_cfg80211_get_station(wiphy, ndev, mac, sinfo);
++      }
++      return -ENOENT;
++}
++
+ static s32
+ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
+                          bool enabled, s32 timeout)
+@@ -4619,6 +4648,7 @@ static struct cfg80211_ops wl_cfg80211_o
+       .join_ibss = brcmf_cfg80211_join_ibss,
+       .leave_ibss = brcmf_cfg80211_leave_ibss,
+       .get_station = brcmf_cfg80211_get_station,
++      .dump_station = brcmf_cfg80211_dump_station,
+       .set_tx_power = brcmf_cfg80211_set_tx_power,
+       .get_tx_power = brcmf_cfg80211_get_tx_power,
+       .add_key = brcmf_cfg80211_add_key,
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+@@ -407,6 +407,7 @@ struct brcmf_cfg80211_info {
+       struct brcmu_d11inf d11inf;
+       bool wowl_enabled;
+       u32 pre_wowl_pmmode;
++      struct brcmf_assoclist_le assoclist;
+ };
+ /**
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
+@@ -72,6 +72,7 @@
+ #define BRCMF_C_GET_BSS_INFO                  136
+ #define BRCMF_C_GET_BANDLIST                  140
+ #define BRCMF_C_SET_SCB_TIMEOUT                       158
++#define BRCMF_C_GET_ASSOCLIST                 159
+ #define BRCMF_C_GET_PHYLIST                   180
+ #define BRCMF_C_SET_SCAN_CHANNEL_TIME         185
+ #define BRCMF_C_SET_SCAN_UNASSOC_TIME         187
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+@@ -119,6 +119,8 @@
+ #define BRCMF_COUNTRY_BUF_SZ          4
+ #define BRCMF_ANT_MAX                 4
++#define BRCMF_MAX_ASSOCLIST           128
++
+ /* join preference types for join_pref iovar */
+ enum brcmf_join_pref_types {
+       BRCMF_JOIN_PREF_RSSI = 1,
+@@ -621,4 +623,15 @@ struct brcmf_rev_info_le {
+       __le32 nvramrev;
+ };
++/**
++ * struct brcmf_assoclist_le - request assoc list.
++ *
++ * @count: indicates number of stations.
++ * @mac: MAC addresses of stations.
++ */
++struct brcmf_assoclist_le {
++      __le32 count;
++      u8 mac[BRCMF_MAX_ASSOCLIST][ETH_ALEN];
++};
++
+ #endif /* FWIL_TYPES_H_ */
diff --git a/package/kernel/mac80211/patches/372-0009-brcmfmac-Move-brcmf_c_preinit_dcmds-prototype-to-cor.patch b/package/kernel/mac80211/patches/372-0009-brcmfmac-Move-brcmf_c_preinit_dcmds-prototype-to-cor.patch
new file mode 100644 (file)
index 0000000..dc54904
--- /dev/null
@@ -0,0 +1,42 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:19 +0200
+Subject: [PATCH] brcmfmac: Move brcmf_c_preinit_dcmds prototype to correct
+ file.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/common.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/common.h
+@@ -17,4 +17,7 @@
+ extern const u8 ALLFFMAC[ETH_ALEN];
++/* Sets dongle media info (drv_version, mac address). */
++int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
++
+ #endif /* BRCMFMAC_COMMON_H */
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -33,6 +33,7 @@
+ #include "feature.h"
+ #include "proto.h"
+ #include "pcie.h"
++#include "common.h"
+ MODULE_AUTHOR("Broadcom Corporation");
+ MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+@@ -214,7 +214,4 @@ void brcmf_txflowblock_if(struct brcmf_i
+ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
+ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
+-/* Sets dongle media info (drv_version, mac address). */
+-int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
+-
+ #endif /* BRCMFMAC_CORE_H */
diff --git a/package/kernel/mac80211/patches/372-0010-brcmfmac-Remove-unused-state-AP-creating.patch b/package/kernel/mac80211/patches/372-0010-brcmfmac-Remove-unused-state-AP-creating.patch
new file mode 100644 (file)
index 0000000..c6a7363
--- /dev/null
@@ -0,0 +1,55 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:20 +0200
+Subject: [PATCH] brcmfmac: Remove unused state AP creating.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -839,7 +839,6 @@ brcmf_cfg80211_change_iface(struct wiphy
+                       err = brcmf_p2p_ifchange(cfg, BRCMF_FIL_P2P_IF_GO);
+               }
+               if (!err) {
+-                      set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state);
+                       brcmf_dbg(INFO, "IF Type = AP\n");
+               }
+       } else {
+@@ -4250,7 +4249,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+               brcmf_dbg(TRACE, "GO mode configuration complete\n");
+       }
+-      clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
+       set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
+ exit:
+@@ -4315,7 +4313,6 @@ static int brcmf_cfg80211_stop_ap(struct
+       }
+       brcmf_set_mpc(ifp, 1);
+       brcmf_configure_arp_offload(ifp, true);
+-      set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
+       clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
+       return err;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+@@ -143,7 +143,6 @@ struct brcmf_cfg80211_profile {
+  * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
+  * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
+  * @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
+- * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
+  * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
+  */
+ enum brcmf_vif_status {
+@@ -151,7 +150,6 @@ enum brcmf_vif_status {
+       BRCMF_VIF_STATUS_CONNECTING,
+       BRCMF_VIF_STATUS_CONNECTED,
+       BRCMF_VIF_STATUS_DISCONNECTING,
+-      BRCMF_VIF_STATUS_AP_CREATING,
+       BRCMF_VIF_STATUS_AP_CREATED
+ };
diff --git a/package/kernel/mac80211/patches/372-0011-brcmfmac-Properly-set-carrier-state-of-netdev.patch b/package/kernel/mac80211/patches/372-0011-brcmfmac-Properly-set-carrier-state-of-netdev.patch
new file mode 100644 (file)
index 0000000..c0948de
--- /dev/null
@@ -0,0 +1,122 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 8 Oct 2015 20:33:21 +0200
+Subject: [PATCH] brcmfmac: Properly set carrier state of netdev.
+
+Use the netif_carrier api to correctly set carrier state on the
+different modes.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -4250,6 +4250,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+               brcmf_dbg(TRACE, "GO mode configuration complete\n");
+       }
+       set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
++      brcmf_net_setcarrier(ifp, true);
+ exit:
+       if ((err) && (!mbss)) {
+@@ -4314,6 +4315,7 @@ static int brcmf_cfg80211_stop_ap(struct
+       brcmf_set_mpc(ifp, 1);
+       brcmf_configure_arp_offload(ifp, true);
+       clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
++      brcmf_net_setcarrier(ifp, false);
+       return err;
+ }
+@@ -5023,6 +5025,7 @@ brcmf_notify_connect_status(struct brcmf
+                               &ifp->vif->sme_state);
+               } else
+                       brcmf_bss_connect_done(cfg, ndev, e, true);
++              brcmf_net_setcarrier(ifp, true);
+       } else if (brcmf_is_linkdown(e)) {
+               brcmf_dbg(CONN, "Linkdown\n");
+               if (!brcmf_is_ibssmode(ifp->vif)) {
+@@ -5032,6 +5035,7 @@ brcmf_notify_connect_status(struct brcmf
+               brcmf_init_prof(ndev_to_prof(ndev));
+               if (ndev != cfg_to_ndev(cfg))
+                       complete(&cfg->vif_disabled);
++              brcmf_net_setcarrier(ifp, false);
+       } else if (brcmf_is_nonetwork(cfg, e)) {
+               if (brcmf_is_ibssmode(ifp->vif))
+                       clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -635,8 +635,7 @@ static int brcmf_netdev_stop(struct net_
+       brcmf_cfg80211_down(ndev);
+-      /* Set state and stop OS transmissions */
+-      netif_stop_queue(ndev);
++      brcmf_net_setcarrier(ifp, false);
+       return 0;
+ }
+@@ -670,8 +669,8 @@ static int brcmf_netdev_open(struct net_
+               return -EIO;
+       }
+-      /* Allow transmit calls */
+-      netif_start_queue(ndev);
++      /* Clear, carrier, set when connected or AP mode. */
++      netif_carrier_off(ndev);
+       return 0;
+ }
+@@ -736,6 +735,24 @@ static void brcmf_net_detach(struct net_
+               brcmf_cfg80211_free_netdev(ndev);
+ }
++void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
++{
++      struct net_device *ndev;
++
++      brcmf_dbg(TRACE, "Enter, idx=%d carrier=%d\n", ifp->bssidx, on);
++
++      ndev = ifp->ndev;
++      brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_DISCONNECTED, !on);
++      if (on) {
++              if (!netif_carrier_ok(ndev))
++                      netif_carrier_on(ndev);
++
++      } else {
++              if (netif_carrier_ok(ndev))
++                      netif_carrier_off(ndev);
++      }
++}
++
+ static int brcmf_net_p2p_open(struct net_device *ndev)
+ {
+       brcmf_dbg(TRACE, "Enter\n");
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+@@ -154,10 +154,13 @@ struct brcmf_fws_mac_descriptor;
+  *    netif stopped due to firmware signalling flow control.
+  * @BRCMF_NETIF_STOP_REASON_FLOW:
+  *    netif stopped due to flowring full.
++ * @BRCMF_NETIF_STOP_REASON_DISCONNECTED:
++ *    netif stopped due to not being connected (STA mode).
+  */
+ enum brcmf_netif_stop_reason {
+-      BRCMF_NETIF_STOP_REASON_FWS_FC = 1,
+-      BRCMF_NETIF_STOP_REASON_FLOW = 2
++      BRCMF_NETIF_STOP_REASON_FWS_FC = BIT(0),
++      BRCMF_NETIF_STOP_REASON_FLOW = BIT(1),
++      BRCMF_NETIF_STOP_REASON_DISCONNECTED = BIT(2)
+ };
+ /**
+@@ -213,5 +216,6 @@ void brcmf_txflowblock_if(struct brcmf_i
+                         enum brcmf_netif_stop_reason reason, bool state);
+ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
+ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
++void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
+ #endif /* BRCMFMAC_CORE_H */
index ed37fb6d0e28b4d913eaa4620d9405dae7ae2d75..7bb6bed585951e063637e20e3db551cc3588af23 100644 (file)
@@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 
 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
 +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
-@@ -1229,6 +1229,7 @@ static int __init brcmfmac_module_init(v
+@@ -1236,6 +1236,7 @@ static int __init brcmfmac_module_init(v
  #endif
        if (!schedule_work(&brcmf_driver_work))
                return -EBUSY;