mac80211: brcmfmac: fix getting/setting TX power
authorRafał Miłecki <zajec5@gmail.com>
Sun, 10 Jan 2016 00:19:09 +0000 (00:19 +0000)
committerRafał Miłecki <zajec5@gmail.com>
Sun, 10 Jan 2016 00:19:09 +0000 (00:19 +0000)
This patches also adds BCM4366 support which may be found on some new
routers based on BCM47094 or BCM4709C0. Unfortunately firmware is still
missing for this chipset.

SVN-Revision: 48166

18 files changed:
package/kernel/mac80211/patches/370-0001-brcmfmac-Fix-exception-handling.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0002-brcmfmac-Add-support-for-the-BCM4350-PCIE-device.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0003-brcmfmac-Fix-set-and-get-tx-power-functions.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0004-brcmfmac-Only-assign-primary-netdev-to-if2bss-array.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0005-brcmfmac-Inform-p2p-module-about-p2pon-through-API.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0006-brcmfmac-Fix-bug-in-flowring-management.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0007-brcmfmac-Make-p2pon-module-param-always-available.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0008-brcmfmac-Workaround-in-change-vif-for-wpa_supplicant.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0009-brcmfmac-Deleting-of-p2p-device-is-leaking-memory.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0010-brcmfmac-Only-handle-p2p_stop_device-if-vif-is-valid.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0011-brcmfmac-Fix-p2p-bug-for-older-firmwares.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0012-brcmfmac-Add-module-parameter-to-disable-features.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0013-brcmfmac-Fix-race-condition-bug-when-deleting-p2p-in.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0014-brcmfmac-Add-support-for-the-BCM4365-and-BCM4366-PCI.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0015-brcmfmac-Fix-TDLS-setup-by-properly-handling-p2p-noi.patch [new file with mode: 0644]
package/kernel/mac80211/patches/370-0016-brcmfmac-Accept-events-when-TDLS-is-used-in-combinat.patch [new file with mode: 0644]
package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch
package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch

diff --git a/package/kernel/mac80211/patches/370-0001-brcmfmac-Fix-exception-handling.patch b/package/kernel/mac80211/patches/370-0001-brcmfmac-Fix-exception-handling.patch
new file mode 100644 (file)
index 0000000..bcd1031
--- /dev/null
@@ -0,0 +1,24 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:04 +0200
+Subject: [PATCH] brcmfmac: Fix exception handling.
+
+In some exception situations the ifp->vif was not properly assigned
+which could result in crash.
+
+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
+@@ -6331,6 +6331,7 @@ wiphy_unreg_out:
+ priv_out:
+       wl_deinit_priv(cfg);
+       brcmf_free_vif(vif);
++      ifp->vif = NULL;
+ wiphy_out:
+       brcmf_free_wiphy(wiphy);
+       return NULL;
diff --git a/package/kernel/mac80211/patches/370-0002-brcmfmac-Add-support-for-the-BCM4350-PCIE-device.patch b/package/kernel/mac80211/patches/370-0002-brcmfmac-Add-support-for-the-BCM4350-PCIE-device.patch
new file mode 100644 (file)
index 0000000..f4ab77b
--- /dev/null
@@ -0,0 +1,81 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:05 +0200
+Subject: [PATCH] brcmfmac: Add support for the BCM4350 PCIE device.
+
+This patch adds support fo the BRCM4350 2x2 11ac PCIE device.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@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/chip.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+@@ -647,6 +647,7 @@ static u32 brcmf_chip_tcm_rambase(struct
+               return 0x198000;
+       case BRCM_CC_4335_CHIP_ID:
+       case BRCM_CC_4339_CHIP_ID:
++      case BRCM_CC_4350_CHIP_ID:
+       case BRCM_CC_4354_CHIP_ID:
+       case BRCM_CC_4356_CHIP_ID:
+       case BRCM_CC_43567_CHIP_ID:
+--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+@@ -47,6 +47,8 @@ enum brcmf_pcie_state {
+ #define BRCMF_PCIE_43602_FW_NAME              "brcm/brcmfmac43602-pcie.bin"
+ #define BRCMF_PCIE_43602_NVRAM_NAME           "brcm/brcmfmac43602-pcie.txt"
++#define BRCMF_PCIE_4350_FW_NAME                       "brcm/brcmfmac4350-pcie.bin"
++#define BRCMF_PCIE_4350_NVRAM_NAME            "brcm/brcmfmac4350-pcie.txt"
+ #define BRCMF_PCIE_4356_FW_NAME                       "brcm/brcmfmac4356-pcie.bin"
+ #define BRCMF_PCIE_4356_NVRAM_NAME            "brcm/brcmfmac4356-pcie.txt"
+ #define BRCMF_PCIE_43570_FW_NAME              "brcm/brcmfmac43570-pcie.bin"
+@@ -194,6 +196,8 @@ enum brcmf_pcie_state {
+ MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4350_FW_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4350_NVRAM_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME);
+@@ -1418,6 +1422,10 @@ static int brcmf_pcie_get_fwnames(struct
+               fw_name = BRCMF_PCIE_43602_FW_NAME;
+               nvram_name = BRCMF_PCIE_43602_NVRAM_NAME;
+               break;
++      case BRCM_CC_4350_CHIP_ID:
++              fw_name = BRCMF_PCIE_4350_FW_NAME;
++              nvram_name = BRCMF_PCIE_4350_NVRAM_NAME;
++              break;
+       case BRCM_CC_4356_CHIP_ID:
+               fw_name = BRCMF_PCIE_4356_FW_NAME;
+               nvram_name = BRCMF_PCIE_4356_NVRAM_NAME;
+@@ -1956,6 +1964,7 @@ cleanup:
+       PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
+ static struct pci_device_id brcmf_pcie_devid_table[] = {
++      BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
+--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
++++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+@@ -39,6 +39,7 @@
+ #define BRCM_CC_4339_CHIP_ID          0x4339
+ #define BRCM_CC_43430_CHIP_ID         43430
+ #define BRCM_CC_4345_CHIP_ID          0x4345
++#define BRCM_CC_4350_CHIP_ID          0x4350
+ #define BRCM_CC_4354_CHIP_ID          0x4354
+ #define BRCM_CC_4356_CHIP_ID          0x4356
+ #define BRCM_CC_43566_CHIP_ID         43566
+@@ -56,6 +57,7 @@
+ #define BRCM_USB_BCMFW_DEVICE_ID      0x0bdc
+ /* PCIE Device IDs */
++#define BRCM_PCIE_4350_DEVICE_ID      0x43a3
+ #define BRCM_PCIE_4354_DEVICE_ID      0x43df
+ #define BRCM_PCIE_4356_DEVICE_ID      0x43ec
+ #define BRCM_PCIE_43567_DEVICE_ID     0x43d3
diff --git a/package/kernel/mac80211/patches/370-0003-brcmfmac-Fix-set-and-get-tx-power-functions.patch b/package/kernel/mac80211/patches/370-0003-brcmfmac-Fix-set-and-get-tx-power-functions.patch
new file mode 100644 (file)
index 0000000..62fdd8d
--- /dev/null
@@ -0,0 +1,218 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:06 +0200
+Subject: [PATCH] brcmfmac: Fix set and get tx-power functions.
+
+Implementation of tx-power (get and set) related functions are
+still assuming mW interface. This is wrong as functions use dbm
+(or mbm) nowadays. As a result a tx power configuration could
+result in wrong power configuration.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@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
+@@ -236,89 +236,6 @@ static int brcmf_roamoff;
+ module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
+ MODULE_PARM_DESC(roamoff, "do not use internal roaming engine");
+-/* Quarter dBm units to mW
+- * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+- * Table is offset so the last entry is largest mW value that fits in
+- * a u16.
+- */
+-
+-#define QDBM_OFFSET 153               /* Offset for first entry */
+-#define QDBM_TABLE_LEN 40     /* Table size */
+-
+-/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+- * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+- */
+-#define QDBM_TABLE_LOW_BOUND 6493     /* Low bound */
+-
+-/* Largest mW value that will round down to the last table entry,
+- * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+- * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
+- * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+- */
+-#define QDBM_TABLE_HIGH_BOUND 64938   /* High bound */
+-
+-static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+-/* qdBm:      +0      +1      +2      +3      +4      +5      +6      +7 */
+-/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
+-/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
+-/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
+-/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
+-/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
+-};
+-
+-static u16 brcmf_qdbm_to_mw(u8 qdbm)
+-{
+-      uint factor = 1;
+-      int idx = qdbm - QDBM_OFFSET;
+-
+-      if (idx >= QDBM_TABLE_LEN)
+-              /* clamp to max u16 mW value */
+-              return 0xFFFF;
+-
+-      /* scale the qdBm index up to the range of the table 0-40
+-       * where an offset of 40 qdBm equals a factor of 10 mW.
+-       */
+-      while (idx < 0) {
+-              idx += 40;
+-              factor *= 10;
+-      }
+-
+-      /* return the mW value scaled down to the correct factor of 10,
+-       * adding in factor/2 to get proper rounding.
+-       */
+-      return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
+-}
+-
+-static u8 brcmf_mw_to_qdbm(u16 mw)
+-{
+-      u8 qdbm;
+-      int offset;
+-      uint mw_uint = mw;
+-      uint boundary;
+-
+-      /* handle boundary case */
+-      if (mw_uint <= 1)
+-              return 0;
+-
+-      offset = QDBM_OFFSET;
+-
+-      /* move mw into the range of the table */
+-      while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+-              mw_uint *= 10;
+-              offset -= 40;
+-      }
+-
+-      for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
+-              boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
+-                                                  nqdBm_to_mW_map[qdbm]) / 2;
+-              if (mw_uint < boundary)
+-                      break;
+-      }
+-
+-      qdbm += (u8) offset;
+-
+-      return qdbm;
+-}
+ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
+                              struct cfg80211_chan_def *ch)
+@@ -2016,16 +1933,14 @@ static s32
+ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+                           enum nl80211_tx_power_setting type, s32 mbm)
+ {
+-
+       struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+       struct net_device *ndev = cfg_to_ndev(cfg);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+-      u16 txpwrmw;
+-      s32 err = 0;
+-      s32 disable = 0;
+-      s32 dbm = MBM_TO_DBM(mbm);
++      s32 err;
++      s32 disable;
++      u32 qdbm = 127;
+-      brcmf_dbg(TRACE, "Enter\n");
++      brcmf_dbg(TRACE, "Enter %d %d\n", type, mbm);
+       if (!check_vif_up(ifp->vif))
+               return -EIO;
+@@ -2034,12 +1949,20 @@ brcmf_cfg80211_set_tx_power(struct wiphy
+               break;
+       case NL80211_TX_POWER_LIMITED:
+       case NL80211_TX_POWER_FIXED:
+-              if (dbm < 0) {
++              if (mbm < 0) {
+                       brcmf_err("TX_POWER_FIXED - dbm is negative\n");
+                       err = -EINVAL;
+                       goto done;
+               }
++              qdbm =  MBM_TO_DBM(4 * mbm);
++              if (qdbm > 127)
++                      qdbm = 127;
++              qdbm |= WL_TXPWR_OVERRIDE;
+               break;
++      default:
++              brcmf_err("Unsupported type %d\n", type);
++              err = -EINVAL;
++              goto done;
+       }
+       /* Make sure radio is off or on as far as software is concerned */
+       disable = WL_RADIO_SW_DISABLE << 16;
+@@ -2047,52 +1970,44 @@ brcmf_cfg80211_set_tx_power(struct wiphy
+       if (err)
+               brcmf_err("WLC_SET_RADIO error (%d)\n", err);
+-      if (dbm > 0xffff)
+-              txpwrmw = 0xffff;
+-      else
+-              txpwrmw = (u16) dbm;
+-      err = brcmf_fil_iovar_int_set(ifp, "qtxpower",
+-                                    (s32)brcmf_mw_to_qdbm(txpwrmw));
++      err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm);
+       if (err)
+               brcmf_err("qtxpower error (%d)\n", err);
+-      cfg->conf->tx_power = dbm;
+ done:
+-      brcmf_dbg(TRACE, "Exit\n");
++      brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE);
+       return err;
+ }
+-static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy,
+-                                     struct wireless_dev *wdev,
+-                                     s32 *dbm)
++static s32
++brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
++                          s32 *dbm)
+ {
+       struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+-      struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+-      s32 txpwrdbm;
+-      u8 result;
+-      s32 err = 0;
++      struct net_device *ndev = cfg_to_ndev(cfg);
++      struct brcmf_if *ifp = netdev_priv(ndev);
++      s32 qdbm = 0;
++      s32 err;
+       brcmf_dbg(TRACE, "Enter\n");
+       if (!check_vif_up(ifp->vif))
+               return -EIO;
+-      err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm);
++      err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &qdbm);
+       if (err) {
+               brcmf_err("error (%d)\n", err);
+               goto done;
+       }
+-
+-      result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
+-      *dbm = (s32) brcmf_qdbm_to_mw(result);
++      *dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4;
+ done:
+-      brcmf_dbg(TRACE, "Exit\n");
++      brcmf_dbg(TRACE, "Exit (0x%x %d)\n", qdbm, *dbm);
+       return err;
+ }
+ static s32
+ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
+-                             u8 key_idx, bool unicast, bool multicast)
++                                u8 key_idx, bool unicast, bool multicast)
+ {
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       u32 index;
diff --git a/package/kernel/mac80211/patches/370-0004-brcmfmac-Only-assign-primary-netdev-to-if2bss-array.patch b/package/kernel/mac80211/patches/370-0004-brcmfmac-Only-assign-primary-netdev-to-if2bss-array.patch
new file mode 100644 (file)
index 0000000..c51365f
--- /dev/null
@@ -0,0 +1,73 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:07 +0200
+Subject: [PATCH] brcmfmac: Only assign primary netdev to if2bss array.
+
+The if2bss allows for translation of ifidx to bssidx which has a 1:n
+relation. Therefor only the first (primary) netdev should be
+assigned in this array. This fixes the p2pon=1 module param usage.
+
+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/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -53,6 +53,8 @@ MODULE_LICENSE("Dual BSD/GPL");
+ #define BRCMF_RXREORDER_EXPIDX_VALID          0x08
+ #define BRCMF_RXREORDER_NEW_HOLE              0x10
++#define BRCMF_BSSIDX_INVALID                  -1
++
+ /* Error bits */
+ int brcmf_msg_level;
+ module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
+@@ -837,7 +839,8 @@ struct brcmf_if *brcmf_add_if(struct brc
+               ifp = netdev_priv(ndev);
+               ifp->ndev = ndev;
+               /* store mapping ifidx to bssidx */
+-              drvr->if2bss[ifidx] = bssidx;
++              if (drvr->if2bss[ifidx] == BRCMF_BSSIDX_INVALID)
++                      drvr->if2bss[ifidx] = bssidx;
+       }
+       ifp->drvr = drvr;
+@@ -862,15 +865,15 @@ static void brcmf_del_if(struct brcmf_pu
+       struct brcmf_if *ifp;
+       ifp = drvr->iflist[bssidx];
+-      drvr->if2bss[ifp->ifidx] = -1;
+       drvr->iflist[bssidx] = NULL;
+       if (!ifp) {
+               brcmf_err("Null interface, idx=%d\n", bssidx);
+               return;
+       }
+       brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
++      if (drvr->if2bss[ifp->ifidx] == bssidx)
++              drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID;
+       if (ifp->ndev) {
+-              drvr->if2bss[ifp->ifidx] = -1;
+               if (bssidx == 0) {
+                       if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+                               rtnl_lock();
+@@ -926,6 +929,7 @@ int brcmf_attach(struct device *dev)
+ {
+       struct brcmf_pub *drvr = NULL;
+       int ret = 0;
++      int i;
+       brcmf_dbg(TRACE, "Enter\n");
+@@ -934,7 +938,9 @@ int brcmf_attach(struct device *dev)
+       if (!drvr)
+               return -ENOMEM;
+-      memset(drvr->if2bss, 0xFF, sizeof(drvr->if2bss));
++      for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
++              drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
++
+       mutex_init(&drvr->proto_block);
+       /* Link to bus module */
diff --git a/package/kernel/mac80211/patches/370-0005-brcmfmac-Inform-p2p-module-about-p2pon-through-API.patch b/package/kernel/mac80211/patches/370-0005-brcmfmac-Inform-p2p-module-about-p2pon-through-API.patch
new file mode 100644 (file)
index 0000000..3c1058d
--- /dev/null
@@ -0,0 +1,113 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:08 +0200
+Subject: [PATCH] brcmfmac: Inform p2p module about p2pon through API
+
+When the p2pon module param is used then p2p attach will initialize
+p2p device iface in the firmware, but it is doing that by checking
+data. It is cleaner to pass the p2pon information to p2p by API.
+This information is also needed for other patch.
+
+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
+@@ -6126,7 +6126,8 @@ static void brcmf_free_wiphy(struct wiph
+ }
+ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+-                                                struct device *busdev)
++                                                struct device *busdev,
++                                                bool p2pdev_forced)
+ {
+       struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
+       struct brcmf_cfg80211_info *cfg;
+@@ -6218,7 +6219,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+                       *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+       }
+-      err = brcmf_p2p_attach(cfg);
++      err = brcmf_p2p_attach(cfg, p2pdev_forced);
+       if (err) {
+               brcmf_err("P2P initilisation failed (%d)\n", err);
+               goto wiphy_unreg_out;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+@@ -469,7 +469,8 @@ brcmf_cfg80211_connect_info *cfg_to_conn
+ }
+ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+-                                                struct device *busdev);
++                                                struct device *busdev,
++                                                bool p2pdev_forced);
+ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
+ s32 brcmf_cfg80211_up(struct net_device *ndev);
+ s32 brcmf_cfg80211_down(struct net_device *ndev);
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -1044,7 +1044,8 @@ int brcmf_bus_start(struct device *dev)
+       brcmf_fws_add_interface(ifp);
+-      drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
++      drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev,
++                                           brcmf_p2p_enable);
+       if (drvr->config == NULL) {
+               ret = -ENOMEM;
+               goto fail;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+@@ -2333,7 +2333,7 @@ void brcmf_p2p_stop_device(struct wiphy
+  *
+  * @cfg: driver private data for cfg80211 interface.
+  */
+-s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
++s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced)
+ {
+       struct brcmf_if *pri_ifp;
+       struct brcmf_if *p2p_ifp;
+@@ -2348,11 +2348,15 @@ s32 brcmf_p2p_attach(struct brcmf_cfg802
+       drvr = cfg->pub;
+-      pri_ifp = drvr->iflist[0];
+-      p2p_ifp = drvr->iflist[1];
+-
++      pri_ifp = brcmf_get_ifp(drvr, 0);
+       p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
++      if (p2pdev_forced) {
++              p2p_ifp = drvr->iflist[1];
++      } else {
++              p2p_ifp = NULL;
++              p2p->p2pdev_dynamically = true;
++      }
+       if (p2p_ifp) {
+               p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
+                                         false);
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
+@@ -124,6 +124,7 @@ struct afx_hdl {
+  * @wait_next_af: thread synchronizing struct.
+  * @gon_req_action: about to send go negotiation requets frame.
+  * @block_gon_req_tx: drop tx go negotiation requets frame.
++ * @p2pdev_dynamically: is p2p device if created by module param or supplicant.
+  */
+ struct brcmf_p2p_info {
+       struct brcmf_cfg80211_info *cfg;
+@@ -144,9 +145,10 @@ struct brcmf_p2p_info {
+       struct completion wait_next_af;
+       bool gon_req_action;
+       bool block_gon_req_tx;
++      bool p2pdev_dynamically;
+ };
+-s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg);
++s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced);
+ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p);
+ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
+                                      enum nl80211_iftype type, u32 *flags,
diff --git a/package/kernel/mac80211/patches/370-0006-brcmfmac-Fix-bug-in-flowring-management.patch b/package/kernel/mac80211/patches/370-0006-brcmfmac-Fix-bug-in-flowring-management.patch
new file mode 100644 (file)
index 0000000..66b2117
--- /dev/null
@@ -0,0 +1,26 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:09 +0200
+Subject: [PATCH] brcmfmac: Fix bug in flowring management.
+
+The hash index stored in the flowrings is of type u16 but gets
+stored in u8. This can result in incorrect indexing and possibly
+result in crashes. This patch fixes the type.
+
+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/flowring.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
+@@ -34,7 +34,7 @@ enum ring_status {
+ };
+ struct brcmf_flowring_ring {
+-      u8 hash_id;
++      u16 hash_id;
+       bool blocked;
+       enum ring_status status;
+       struct sk_buff_head skblist;
diff --git a/package/kernel/mac80211/patches/370-0007-brcmfmac-Make-p2pon-module-param-always-available.patch b/package/kernel/mac80211/patches/370-0007-brcmfmac-Make-p2pon-module-param-always-available.patch
new file mode 100644 (file)
index 0000000..c143c3b
--- /dev/null
@@ -0,0 +1,29 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:10 +0200
+Subject: [PATCH] brcmfmac: Make p2pon module param always available.
+
+p2pon module param is currently under define BRCMDBG. Though it is
+a needed option for older versions of the wpa_supplicant which do not
+support the P2P_DEVICE interface.
+
+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/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -62,10 +62,8 @@ MODULE_PARM_DESC(debug, "level of debug
+ /* P2P0 enable */
+ static int brcmf_p2p_enable;
+-#ifdef CPTCFG_BRCMDBG
+ module_param_named(p2pon, brcmf_p2p_enable, int, 0);
+-MODULE_PARM_DESC(p2pon, "enable p2p management functionality");
+-#endif
++MODULE_PARM_DESC(p2pon, "enable legacy p2p management functionality");
+ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
+ {
diff --git a/package/kernel/mac80211/patches/370-0008-brcmfmac-Workaround-in-change-vif-for-wpa_supplicant.patch b/package/kernel/mac80211/patches/370-0008-brcmfmac-Workaround-in-change-vif-for-wpa_supplicant.patch
new file mode 100644 (file)
index 0000000..15ac2d9
--- /dev/null
@@ -0,0 +1,76 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:11 +0200
+Subject: [PATCH] brcmfmac: Workaround in change vif for wpa_supplicant
+ support.
+
+Different wpa_supplicants have different behavior and expectations
+regarding the change_virtual_intf behavior. This patch implements
+a workaround for the different versions and possible brcmfmac
+configuration.
+
+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
+@@ -776,6 +776,37 @@ brcmf_cfg80211_change_iface(struct wiphy
+       s32 err = 0;
+       brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type);
++
++      /* WAR: There are a number of p2p interface related problems which
++       * need to be handled initially (before doing the validate).
++       * wpa_supplicant tends to do iface changes on p2p device/client/go
++       * which are not always possible/allowed. However we need to return
++       * OK otherwise the wpa_supplicant wont start. The situation differs
++       * on configuration and setup (p2pon=1 module param). The first check
++       * is to see if the request is a change to station for p2p iface.
++       */
++      if ((type == NL80211_IFTYPE_STATION) &&
++          ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ||
++           (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ||
++           (vif->wdev.iftype == NL80211_IFTYPE_P2P_DEVICE))) {
++              brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n");
++              /* Now depending on whether module param p2pon=1 was used the
++               * response needs to be either 0 or EOPNOTSUPP. The reason is
++               * that if p2pon=1 is used, but a newer supplicant is used then
++               * we should return an error, as this combination wont work.
++               * In other situations 0 is returned and supplicant will start
++               * normally. It will give a trace in cfg80211, but it is the
++               * only way to get it working. Unfortunately this will result
++               * in situation where we wont support new supplicant in
++               * combination with module param p2pon=1, but that is the way
++               * it is. If the user tries this then unloading of driver might
++               * fail/lock.
++               */
++              if (cfg->p2p.p2pdev_dynamically)
++                      return -EOPNOTSUPP;
++              else
++                      return 0;
++      }
+       err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type);
+       if (err) {
+               brcmf_err("iface validation failed: err=%d\n", err);
+@@ -791,18 +822,6 @@ brcmf_cfg80211_change_iface(struct wiphy
+               infra = 0;
+               break;
+       case NL80211_IFTYPE_STATION:
+-              /* Ignore change for p2p IF. Unclear why supplicant does this */
+-              if ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ||
+-                  (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) {
+-                      brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n");
+-                      /* WAR: It is unexpected to get a change of VIF for P2P
+-                       * IF, but it happens. The request can not be handled
+-                       * but returning EPERM causes a crash. Returning 0
+-                       * without setting ieee80211_ptr->iftype causes trace
+-                       * (WARN_ON) but it works with wpa_supplicant
+-                       */
+-                      return 0;
+-              }
+               infra = 1;
+               break;
+       case NL80211_IFTYPE_AP:
diff --git a/package/kernel/mac80211/patches/370-0009-brcmfmac-Deleting-of-p2p-device-is-leaking-memory.patch b/package/kernel/mac80211/patches/370-0009-brcmfmac-Deleting-of-p2p-device-is-leaking-memory.patch
new file mode 100644 (file)
index 0000000..1988b5c
--- /dev/null
@@ -0,0 +1,124 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:12 +0200
+Subject: [PATCH] brcmfmac: Deleting of p2p device is leaking memory.
+
+When a p2p device gets deleted, the memory for the vif is not being
+released. This is solved by reorganizing the cleanup path and
+properly freeing the memory.
+
+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/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -887,6 +887,16 @@ static void brcmf_del_if(struct brcmf_pu
+                       cancel_work_sync(&ifp->multicast_work);
+               }
+               brcmf_net_detach(ifp->ndev);
++      } else {
++              /* Only p2p device interfaces which get dynamically created
++               * end up here. In this case the p2p module should be informed
++               * about the removal of the interface within the firmware. If
++               * not then p2p commands towards the firmware will cause some
++               * serious troublesome side effects. The p2p module will clean
++               * up the ifp if needed.
++               */
++              brcmf_p2p_ifp_removed(ifp);
++              kfree(ifp);
+       }
+ }
+@@ -894,7 +904,8 @@ void brcmf_remove_interface(struct brcmf
+ {
+       if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp))
+               return;
+-
++      brcmf_dbg(TRACE, "Enter, bssidx=%d, ifidx=%d\n", ifp->bssidx,
++                ifp->ifidx);
+       brcmf_fws_del_interface(ifp);
+       brcmf_del_if(ifp->drvr, ifp->bssidx);
+ }
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+@@ -2131,20 +2131,6 @@ fail:
+ }
+ /**
+- * brcmf_p2p_delete_p2pdev() - delete P2P_DEVICE virtual interface.
+- *
+- * @vif: virtual interface object to delete.
+- */
+-static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p,
+-                                  struct brcmf_cfg80211_vif *vif)
+-{
+-      cfg80211_unregister_wdev(&vif->wdev);
+-      p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+-      brcmf_remove_interface(vif->ifp);
+-      brcmf_free_vif(vif);
+-}
+-
+-/**
+  * brcmf_p2p_add_vif() - create a new P2P virtual interface.
+  *
+  * @wiphy: wiphy device of new interface.
+@@ -2264,9 +2250,11 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+               break;
+       case NL80211_IFTYPE_P2P_DEVICE:
++              if (!p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
++                      return 0;
+               brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+               brcmf_p2p_deinit_discovery(p2p);
+-              brcmf_p2p_delete_p2pdev(p2p, vif);
++              brcmf_remove_interface(vif->ifp);
+               return 0;
+       default:
+               return -ENOTSUPP;
+@@ -2298,6 +2286,21 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+       return err;
+ }
++void brcmf_p2p_ifp_removed(struct brcmf_if *ifp)
++{
++      struct brcmf_cfg80211_info *cfg;
++      struct brcmf_cfg80211_vif *vif;
++
++      brcmf_dbg(INFO, "P2P: device interface removed\n");
++      vif = ifp->vif;
++      cfg = wdev_to_cfg(&vif->wdev);
++      cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
++      rtnl_lock();
++      cfg80211_unregister_wdev(&vif->wdev);
++      rtnl_unlock();
++      brcmf_free_vif(vif);
++}
++
+ int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev)
+ {
+       struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+@@ -2422,10 +2425,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_i
+       if (vif != NULL) {
+               brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+               brcmf_p2p_deinit_discovery(p2p);
+-              /* remove discovery interface */
+-              rtnl_lock();
+-              brcmf_p2p_delete_p2pdev(p2p, vif);
+-              rtnl_unlock();
++              brcmf_remove_interface(vif->ifp);
+       }
+       /* just set it all to zero */
+       memset(p2p, 0, sizeof(*p2p));
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
+@@ -156,6 +156,7 @@ struct wireless_dev *brcmf_p2p_add_vif(s
+ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev);
+ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
+                      enum brcmf_fil_p2p_if_types if_type);
++void brcmf_p2p_ifp_removed(struct brcmf_if *ifp);
+ int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
diff --git a/package/kernel/mac80211/patches/370-0010-brcmfmac-Only-handle-p2p_stop_device-if-vif-is-valid.patch b/package/kernel/mac80211/patches/370-0010-brcmfmac-Only-handle-p2p_stop_device-if-vif-is-valid.patch
new file mode 100644 (file)
index 0000000..5225c9e
--- /dev/null
@@ -0,0 +1,40 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:13 +0200
+Subject: [PATCH] brcmfmac: Only handle p2p_stop_device if vif is valid
+
+In some situations it is possible that vif has been removed while
+cfg80211 invokes the p2p_stop_device handler. This will result in
+crash.
+
+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/p2p.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+@@ -2324,11 +2324,17 @@ void brcmf_p2p_stop_device(struct wiphy
+       struct brcmf_cfg80211_vif *vif;
+       vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+-      mutex_lock(&cfg->usr_sync);
+-      (void)brcmf_p2p_deinit_discovery(p2p);
+-      brcmf_abort_scanning(cfg);
+-      clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
+-      mutex_unlock(&cfg->usr_sync);
++      /* This call can be result of the unregister_wdev call. In that case
++       * we dont want to do anything anymore. Just return. The config vif
++       * will have been cleared at this point.
++       */
++      if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif == vif) {
++              mutex_lock(&cfg->usr_sync);
++              (void)brcmf_p2p_deinit_discovery(p2p);
++              brcmf_abort_scanning(cfg);
++              clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
++              mutex_unlock(&cfg->usr_sync);
++      }
+ }
+ /**
diff --git a/package/kernel/mac80211/patches/370-0011-brcmfmac-Fix-p2p-bug-for-older-firmwares.patch b/package/kernel/mac80211/patches/370-0011-brcmfmac-Fix-p2p-bug-for-older-firmwares.patch
new file mode 100644 (file)
index 0000000..e2f24e8
--- /dev/null
@@ -0,0 +1,35 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:14 +0200
+Subject: [PATCH] brcmfmac: Fix p2p bug for older firmwares.
+
+Some devices with older firmwares are reporting new p2p device
+interface with the wrong type. Accept this type to get p2p
+working for these devices.
+
+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/fweh.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+@@ -186,11 +186,13 @@ static void brcmf_fweh_handle_if_event(s
+                 ifevent->action, ifevent->ifidx, ifevent->bssidx,
+                 ifevent->flags, ifevent->role);
+-      /* The P2P Device interface event must not be ignored
+-       * contrary to what firmware tells us.
++      /* The P2P Device interface event must not be ignored contrary to what
++       * firmware tells us. Older firmware uses p2p noif, with sta role.
++       * This should be accepted.
+        */
+-      is_p2pdev = (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) &&
+-                  ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT;
++      is_p2pdev = ((ifevent->flags & BRCMF_E_IF_FLAG_NOIF) &&
++                   (ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT ||
++                    ifevent->role == BRCMF_E_IF_ROLE_STA));
+       if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
+               brcmf_dbg(EVENT, "event can be ignored\n");
+               return;
diff --git a/package/kernel/mac80211/patches/370-0012-brcmfmac-Add-module-parameter-to-disable-features.patch b/package/kernel/mac80211/patches/370-0012-brcmfmac-Add-module-parameter-to-disable-features.patch
new file mode 100644 (file)
index 0000000..52c787f
--- /dev/null
@@ -0,0 +1,54 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:15 +0200
+Subject: [PATCH] brcmfmac: Add module parameter to disable features.
+
+For debugging purpose it is very handy to be able to disable
+features. It has happened a few times that new features turned
+out not always being properly detected for all devices/firmwares.
+Making it possible to disable the feature with a module parameter
+will make testing/debugging easier.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@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/feature.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+@@ -15,6 +15,7 @@
+  */
+ #include <linux/netdevice.h>
++#include <linux/module.h>
+ #include <brcm_hw_ids.h>
+ #include "core.h"
+@@ -23,6 +24,12 @@
+ #include "fwil.h"
+ #include "feature.h"
++
++/* Module param feature_disable (global for all devices) */
++static int brcmf_feature_disable;
++module_param_named(feature_disable, brcmf_feature_disable, int, 0);
++MODULE_PARM_DESC(feature_disable, "Disable features");
++
+ /*
+  * expand feature list to array of feature strings.
+  */
+@@ -131,6 +138,12 @@ void brcmf_feat_attach(struct brcmf_pub
+               brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
+       brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
++      if (brcmf_feature_disable) {
++              brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
++                        ifp->drvr->feat_flags, brcmf_feature_disable);
++              ifp->drvr->feat_flags &= ~brcmf_feature_disable;
++      }
++
+       /* set chip related quirks */
+       switch (drvr->bus_if->chip) {
+       case BRCM_CC_43236_CHIP_ID:
diff --git a/package/kernel/mac80211/patches/370-0013-brcmfmac-Fix-race-condition-bug-when-deleting-p2p-in.patch b/package/kernel/mac80211/patches/370-0013-brcmfmac-Fix-race-condition-bug-when-deleting-p2p-in.patch
new file mode 100644 (file)
index 0000000..58a638a
--- /dev/null
@@ -0,0 +1,80 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:16 +0200
+Subject: [PATCH] brcmfmac: Fix race condition bug when deleting p2p interface.
+
+When p2p device interface gets deleted by deinitialising discovery
+it will result in an event which removes the interface, but that is
+also done by delete p2p interface code. This results in race
+condition which sometimes results in lockup/crash. With this patch
+the delete device interface will wait for the event (with timeout)
+removing the possible race condition. Also on the stop device call
+from cfg80211 the deinitialisation of the discovery device should
+be avoided as it can result in a similar situation.
+
+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/p2p.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+@@ -2238,6 +2238,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+       brcmf_dbg(TRACE, "delete P2P vif\n");
+       vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
++      brcmf_cfg80211_arm_vif_event(cfg, vif);
+       switch (vif->wdev.iftype) {
+       case NL80211_IFTYPE_P2P_CLIENT:
+               if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state))
+@@ -2254,8 +2255,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+                       return 0;
+               brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+               brcmf_p2p_deinit_discovery(p2p);
+-              brcmf_remove_interface(vif->ifp);
+-              return 0;
+       default:
+               return -ENOTSUPP;
+       }
+@@ -2267,10 +2266,11 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+               wait_for_completion_timeout(&cfg->vif_disabled,
+                                           msecs_to_jiffies(500));
+-      brcmf_vif_clear_mgmt_ies(vif);
+-
+-      brcmf_cfg80211_arm_vif_event(cfg, vif);
+-      err = brcmf_p2p_release_p2p_if(vif);
++      err = 0;
++      if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) {
++              brcmf_vif_clear_mgmt_ies(vif);
++              err = brcmf_p2p_release_p2p_if(vif);
++      }
+       if (!err) {
+               /* wait for firmware event */
+               err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL,
+@@ -2280,8 +2280,12 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+               else
+                       err = 0;
+       }
++      if (err)
++              brcmf_remove_interface(vif->ifp);
++
+       brcmf_cfg80211_arm_vif_event(cfg, NULL);
+-      p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
++      if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
++              p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
+       return err;
+ }
+@@ -2330,7 +2334,9 @@ void brcmf_p2p_stop_device(struct wiphy
+        */
+       if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif == vif) {
+               mutex_lock(&cfg->usr_sync);
+-              (void)brcmf_p2p_deinit_discovery(p2p);
++              /* Set the discovery state to SCAN */
++              (void)brcmf_p2p_set_discover_state(vif->ifp,
++                                                 WL_P2P_DISC_ST_SCAN, 0, 0);
+               brcmf_abort_scanning(cfg);
+               clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
+               mutex_unlock(&cfg->usr_sync);
diff --git a/package/kernel/mac80211/patches/370-0014-brcmfmac-Add-support-for-the-BCM4365-and-BCM4366-PCI.patch b/package/kernel/mac80211/patches/370-0014-brcmfmac-Add-support-for-the-BCM4365-and-BCM4366-PCI.patch
new file mode 100644 (file)
index 0000000..d0bbf2a
--- /dev/null
@@ -0,0 +1,277 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:17 +0200
+Subject: [PATCH] brcmfmac: Add support for the BCM4365 and BCM4366 PCIE
+ devices.
+
+This patch adds support for the BCM4365 and BCM4366 11ac Wave2
+PCIE devices.
+
+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/chip.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+@@ -208,6 +208,7 @@ struct sbsocramregs {
+ };
+ #define SOCRAMREGOFFS(_f)     offsetof(struct sbsocramregs, _f)
++#define SYSMEMREGOFFS(_f)     offsetof(struct sbsocramregs, _f)
+ #define ARMCR4_CAP            (0x04)
+ #define ARMCR4_BANKIDX                (0x40)
+@@ -516,6 +517,9 @@ static int brcmf_chip_cores_check(struct
+               case BCMA_CORE_ARM_CR4:
+                       cpu_found = true;
+                       break;
++              case BCMA_CORE_ARM_CA7:
++                      cpu_found = true;
++                      break;
+               default:
+                       break;
+               }
+@@ -614,6 +618,29 @@ static void brcmf_chip_socram_ramsize(st
+       }
+ }
++/** Return the SYS MEM size */
++static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem)
++{
++      u32 memsize = 0;
++      u32 coreinfo;
++      u32 idx;
++      u32 nb;
++      u32 banksize;
++
++      if (!brcmf_chip_iscoreup(&sysmem->pub))
++              brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0);
++
++      coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo));
++      nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
++
++      for (idx = 0; idx < nb; idx++) {
++              brcmf_chip_socram_banksize(sysmem, idx, &banksize);
++              memsize += banksize;
++      }
++
++      return memsize;
++}
++
+ /** Return the TCM-RAM size of the ARMCR4 core. */
+ static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
+ {
+@@ -656,6 +683,9 @@ static u32 brcmf_chip_tcm_rambase(struct
+       case BRCM_CC_4358_CHIP_ID:
+       case BRCM_CC_43602_CHIP_ID:
+               return 0x180000;
++      case BRCM_CC_4365_CHIP_ID:
++      case BRCM_CC_4366_CHIP_ID:
++              return 0x200000;
+       default:
+               brcmf_err("unknown chip: %s\n", ci->pub.name);
+               break;
+@@ -678,10 +708,28 @@ static int brcmf_chip_get_raminfo(struct
+                       return -EINVAL;
+               }
+       } else {
+-              mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_INTERNAL_MEM);
+-              mem_core = container_of(mem, struct brcmf_core_priv, pub);
+-              brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize,
+-                                        &ci->pub.srsize);
++              mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_SYS_MEM);
++              if (mem) {
++                      mem_core = container_of(mem, struct brcmf_core_priv,
++                                              pub);
++                      ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core);
++                      ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
++                      if (!ci->pub.rambase) {
++                              brcmf_err("RAM base not provided with ARM CA7 core\n");
++                              return -EINVAL;
++                      }
++              } else {
++                      mem = brcmf_chip_get_core(&ci->pub,
++                                                BCMA_CORE_INTERNAL_MEM);
++                      if (!mem) {
++                              brcmf_err("No memory cores found\n");
++                              return -ENOMEM;
++                      }
++                      mem_core = container_of(mem, struct brcmf_core_priv,
++                                              pub);
++                      brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize,
++                                                &ci->pub.srsize);
++              }
+       }
+       brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n",
+                 ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize,
+@@ -924,7 +972,7 @@ static int brcmf_chip_recognition(struct
+ static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
+ {
+       struct brcmf_core *core;
+-      struct brcmf_core_priv *cr4;
++      struct brcmf_core_priv *cpu;
+       u32 val;
+@@ -937,10 +985,11 @@ static void brcmf_chip_disable_arm(struc
+               brcmf_chip_coredisable(core, 0, 0);
+               break;
+       case BCMA_CORE_ARM_CR4:
+-              cr4 = container_of(core, struct brcmf_core_priv, pub);
++      case BCMA_CORE_ARM_CA7:
++              cpu = container_of(core, struct brcmf_core_priv, pub);
+               /* clear all IOCTL bits except HALT bit */
+-              val = chip->ops->read32(chip->ctx, cr4->wrapbase + BCMA_IOCTL);
++              val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL);
+               val &= ARMCR4_BCMA_IOCTL_CPUHALT;
+               brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT,
+                                    ARMCR4_BCMA_IOCTL_CPUHALT);
+@@ -1162,6 +1211,33 @@ static bool brcmf_chip_cr4_set_active(st
+       return true;
+ }
++static inline void
++brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip)
++{
++      struct brcmf_core *core;
++
++      brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7);
++
++      core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
++      brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
++                                 D11_BCMA_IOCTL_PHYCLOCKEN,
++                           D11_BCMA_IOCTL_PHYCLOCKEN,
++                           D11_BCMA_IOCTL_PHYCLOCKEN);
++}
++
++static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
++{
++      struct brcmf_core *core;
++
++      chip->ops->activate(chip->ctx, &chip->pub, rstvec);
++
++      /* restore ARM */
++      core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CA7);
++      brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);
++
++      return true;
++}
++
+ void brcmf_chip_set_passive(struct brcmf_chip *pub)
+ {
+       struct brcmf_chip_priv *chip;
+@@ -1175,8 +1251,16 @@ void brcmf_chip_set_passive(struct brcmf
+               brcmf_chip_cr4_set_passive(chip);
+               return;
+       }
+-
+-      brcmf_chip_cm3_set_passive(chip);
++      arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);
++      if (arm) {
++              brcmf_chip_ca7_set_passive(chip);
++              return;
++      }
++      arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);
++      if (arm) {
++              brcmf_chip_cm3_set_passive(chip);
++              return;
++      }
+ }
+ bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec)
+@@ -1190,8 +1274,14 @@ bool brcmf_chip_set_active(struct brcmf_
+       arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
+       if (arm)
+               return brcmf_chip_cr4_set_active(chip, rstvec);
++      arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);
++      if (arm)
++              return brcmf_chip_ca7_set_active(chip, rstvec);
++      arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);
++      if (arm)
++              return brcmf_chip_cm3_set_active(chip);
+-      return brcmf_chip_cm3_set_active(chip);
++      return false;
+ }
+ bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
+--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+@@ -55,6 +55,10 @@ enum brcmf_pcie_state {
+ #define BRCMF_PCIE_43570_NVRAM_NAME           "brcm/brcmfmac43570-pcie.txt"
+ #define BRCMF_PCIE_4358_FW_NAME                       "brcm/brcmfmac4358-pcie.bin"
+ #define BRCMF_PCIE_4358_NVRAM_NAME            "brcm/brcmfmac4358-pcie.txt"
++#define BRCMF_PCIE_4365_FW_NAME                       "brcm/brcmfmac4365b-pcie.bin"
++#define BRCMF_PCIE_4365_NVRAM_NAME            "brcm/brcmfmac4365b-pcie.txt"
++#define BRCMF_PCIE_4366_FW_NAME                       "brcm/brcmfmac4366b-pcie.bin"
++#define BRCMF_PCIE_4366_NVRAM_NAME            "brcm/brcmfmac4366b-pcie.txt"
+ #define BRCMF_PCIE_FW_UP_TIMEOUT              2000 /* msec */
+@@ -204,6 +208,10 @@ MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME
+ MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4358_FW_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4358_NVRAM_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4365_FW_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4365_NVRAM_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4366_FW_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4366_NVRAM_NAME);
+ struct brcmf_pcie_console {
+@@ -1440,6 +1448,14 @@ static int brcmf_pcie_get_fwnames(struct
+               fw_name = BRCMF_PCIE_4358_FW_NAME;
+               nvram_name = BRCMF_PCIE_4358_NVRAM_NAME;
+               break;
++      case BRCM_CC_4365_CHIP_ID:
++              fw_name = BRCMF_PCIE_4365_FW_NAME;
++              nvram_name = BRCMF_PCIE_4365_NVRAM_NAME;
++              break;
++      case BRCM_CC_4366_CHIP_ID:
++              fw_name = BRCMF_PCIE_4366_FW_NAME;
++              nvram_name = BRCMF_PCIE_4366_NVRAM_NAME;
++              break;
+       default:
+               brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip);
+               return -ENODEV;
+@@ -1973,6 +1989,12 @@ static struct pci_device_id brcmf_pcie_d
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID),
++      BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID),
++      BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID),
++      BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID),
++      BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID),
++      BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
++      BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),
+       { /* end: all zeroes */ }
+ };
+--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
++++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+@@ -48,6 +48,8 @@
+ #define BRCM_CC_43570_CHIP_ID         43570
+ #define BRCM_CC_4358_CHIP_ID          0x4358
+ #define BRCM_CC_43602_CHIP_ID         43602
++#define BRCM_CC_4365_CHIP_ID          0x4365
++#define BRCM_CC_4366_CHIP_ID          0x4366
+ /* USB Device IDs */
+ #define BRCM_USB_43143_DEVICE_ID      0xbd1e
+@@ -67,6 +69,13 @@
+ #define BRCM_PCIE_43602_2G_DEVICE_ID  0x43bb
+ #define BRCM_PCIE_43602_5G_DEVICE_ID  0x43bc
+ #define BRCM_PCIE_43602_RAW_DEVICE_ID 43602
++#define BRCM_PCIE_4365_DEVICE_ID      0x43ca
++#define BRCM_PCIE_4365_2G_DEVICE_ID   0x43cb
++#define BRCM_PCIE_4365_5G_DEVICE_ID   0x43cc
++#define BRCM_PCIE_4366_DEVICE_ID      0x43c3
++#define BRCM_PCIE_4366_2G_DEVICE_ID   0x43c4
++#define BRCM_PCIE_4366_5G_DEVICE_ID   0x43c5
++
+ /* brcmsmac IDs */
+ #define BCM4313_D11N2G_ID     0x4727  /* 4313 802.11n 2.4G device */
diff --git a/package/kernel/mac80211/patches/370-0015-brcmfmac-Fix-TDLS-setup-by-properly-handling-p2p-noi.patch b/package/kernel/mac80211/patches/370-0015-brcmfmac-Fix-TDLS-setup-by-properly-handling-p2p-noi.patch
new file mode 100644 (file)
index 0000000..d33c803
--- /dev/null
@@ -0,0 +1,120 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:18 +0200
+Subject: [PATCH] brcmfmac: Fix TDLS setup by properly handling p2p noif.
+
+There is a workaround needed for p2p device setup which breaks tdls
+functionality. This patch fixes that by properly signalling fweh that
+p2p device setup is ongoing.
+
+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/fweh.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+@@ -188,11 +188,13 @@ static void brcmf_fweh_handle_if_event(s
+       /* The P2P Device interface event must not be ignored contrary to what
+        * firmware tells us. Older firmware uses p2p noif, with sta role.
+-       * This should be accepted.
++       * This should be accepted when p2pdev_setup is ongoing. TDLS setup will
++       * use the same ifevent and should be ignored.
+        */
+       is_p2pdev = ((ifevent->flags & BRCMF_E_IF_FLAG_NOIF) &&
+                    (ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT ||
+-                    ifevent->role == BRCMF_E_IF_ROLE_STA));
++                    ((ifevent->role == BRCMF_E_IF_ROLE_STA) &&
++                     (drvr->fweh.p2pdev_setup_ongoing))));
+       if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
+               brcmf_dbg(EVENT, "event can be ignored\n");
+               return;
+@@ -316,6 +318,17 @@ event_free:
+ }
+ /**
++ * brcmf_fweh_p2pdev_setup() - P2P device setup ongoing (or not).
++ *
++ * @ifp: ifp on which setup is taking place or finished.
++ * @ongoing: p2p device setup in progress (or not).
++ */
++void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing)
++{
++      ifp->drvr->fweh.p2pdev_setup_ongoing = ongoing;
++}
++
++/**
+  * brcmf_fweh_attach() - initialize firmware event handling.
+  *
+  * @drvr: driver information object.
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
+@@ -230,12 +230,14 @@ typedef int (*brcmf_fweh_handler_t)(stru
+ /**
+  * struct brcmf_fweh_info - firmware event handling information.
+  *
++ * @p2pdev_setup_ongoing: P2P device creation in progress.
+  * @event_work: event worker.
+  * @evt_q_lock: lock for event queue protection.
+  * @event_q: event queue.
+  * @evt_handler: registered event handlers.
+  */
+ struct brcmf_fweh_info {
++      bool p2pdev_setup_ongoing;
+       struct work_struct event_work;
+       spinlock_t evt_q_lock;
+       struct list_head event_q;
+@@ -255,6 +257,7 @@ void brcmf_fweh_unregister(struct brcmf_
+ int brcmf_fweh_activate_events(struct brcmf_if *ifp);
+ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
+                             struct brcmf_event *event_packet);
++void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing);
+ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
+                                         struct sk_buff *skb)
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+@@ -2084,11 +2084,13 @@ static struct wireless_dev *brcmf_p2p_cr
+       brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
+       brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif);
++      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_fweh_p2pdev_setup(pri_ifp, false);
+               brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
+               goto fail;
+       }
+@@ -2097,6 +2099,7 @@ static struct wireless_dev *brcmf_p2p_cr
+       err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD,
+                                                   msecs_to_jiffies(1500));
+       brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
++      brcmf_fweh_p2pdev_setup(pri_ifp, false);
+       if (!err) {
+               brcmf_err("timeout occurred\n");
+               err = -EIO;
+@@ -2393,6 +2396,8 @@ s32 brcmf_p2p_attach(struct brcmf_cfg802
+               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) {
+@@ -2419,8 +2424,9 @@ s32 brcmf_p2p_attach(struct brcmf_cfg802
+               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/370-0016-brcmfmac-Accept-events-when-TDLS-is-used-in-combinat.patch b/package/kernel/mac80211/patches/370-0016-brcmfmac-Accept-events-when-TDLS-is-used-in-combinat.patch
new file mode 100644 (file)
index 0000000..b880078
--- /dev/null
@@ -0,0 +1,29 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Fri, 18 Sep 2015 22:08:19 +0200
+Subject: [PATCH] brcmfmac: Accept events when TDLS is used in combination with
+ p2p.
+
+TDLS events are mapped back to primary interface but when p2p is in
+use then this fails because the check was incorrect by checking
+bsscfg number. Which can be different when a p2p device has been
+created.
+
+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/fweh.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+@@ -300,8 +300,7 @@ static void brcmf_fweh_event_worker(stru
+                       goto event_free;
+               }
+-              if ((event->code == BRCMF_E_TDLS_PEER_EVENT) &&
+-                  (emsg.bsscfgidx == 1))
++              if (event->code == BRCMF_E_TDLS_PEER_EVENT)
+                       ifp = drvr->iflist[0];
+               else
+                       ifp = drvr->iflist[emsg.bsscfgidx];
index 685a5f90c2a64ced7b687eda47871b23290f992d..ed37fb6d0e28b4d913eaa4620d9405dae7ae2d75 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
-@@ -1213,6 +1213,7 @@ static int __init brcmfmac_module_init(v
+@@ -1229,6 +1229,7 @@ static int __init brcmfmac_module_init(v
  #endif
        if (!schedule_work(&brcmf_driver_work))
                return -EBUSY;
index 1cba2b39e80d47c52fd0002346149f99c277e890..32c4a6f9e7b9eebed9e00dee2acefbc90d5def9d 100644 (file)
@@ -10,7 +10,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 
 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
 +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
-@@ -691,9 +691,37 @@ static struct wireless_dev *brcmf_cfg802
+@@ -608,9 +608,37 @@ static struct wireless_dev *brcmf_cfg802
                                                     u32 *flags,
                                                     struct vif_params *params)
  {