ath6kl: Fix target assert in p2p bringup with multi vif
authorVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Fri, 6 Apr 2012 14:54:30 +0000 (20:24 +0530)
committerKalle Valo <kvalo@qca.qualcomm.com>
Mon, 9 Apr 2012 14:49:43 +0000 (17:49 +0300)
Using interface 0 for p2p causes target assert. This is because
interface 0 is always initialized to non-p2p operations. Fix this
issue by initializing all the interfaces for p2p when fw is capable
of dynamic interface switching. When fw is not capable of dynamic
switching, make sure p2p is not brought up on interface which is
not initialized for this purpose.

Reported-by: Naveen Singh navesing@qca.qualcomm.com
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/init.c

index 1272508513f75bf2899586e41534318cd9bf6c62..06f12da554e10c244620c3888fb0d8cd36f6378a 100644 (file)
@@ -1451,9 +1451,38 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
                                        struct vif_params *params)
 {
        struct ath6kl_vif *vif = netdev_priv(ndev);
+       int i;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
 
+       /*
+        * Don't bring up p2p on an interface which is not initialized
+        * for p2p operation where fw does not have capability to switch
+        * dynamically between non-p2p and p2p type interface.
+        */
+       if (!test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
+                     vif->ar->fw_capabilities) &&
+           (type == NL80211_IFTYPE_P2P_CLIENT ||
+            type == NL80211_IFTYPE_P2P_GO)) {
+               if (vif->ar->vif_max == 1) {
+                       if (vif->fw_vif_idx != 0)
+                               return -EINVAL;
+                       else
+                               goto set_iface_type;
+               }
+
+               for (i = vif->ar->max_norm_iface; i < vif->ar->vif_max; i++) {
+                       if (i == vif->fw_vif_idx)
+                               break;
+               }
+
+               if (i == vif->ar->vif_max) {
+                       ath6kl_err("Invalid interface to bring up P2P\n");
+                       return -EINVAL;
+               }
+       }
+
+set_iface_type:
        switch (type) {
        case NL80211_IFTYPE_STATION:
                vif->next_mode = INFRA_NETWORK;
index 5949ab5357fd92fe3134f7b5d2d000d3f4ea6fa7..edd778888aa0b04531462736a4be7b98349bb55f 100644 (file)
@@ -488,22 +488,31 @@ int ath6kl_configure_target(struct ath6kl *ar)
                fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS);
 
        /*
-        * By default, submodes :
+        * Submodes when fw does not support dynamic interface
+        * switching:
         *              vif[0] - AP/STA/IBSS
         *              vif[1] - "P2P dev"/"P2P GO"/"P2P Client"
         *              vif[2] - "P2P dev"/"P2P GO"/"P2P Client"
+        * Otherwise, All the interface are initialized to p2p dev.
         */
 
-       for (i = 0; i < ar->max_norm_iface; i++)
-               fw_submode |= HI_OPTION_FW_SUBMODE_NONE <<
-                             (i * HI_OPTION_FW_SUBMODE_BITS);
+       if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
+                    ar->fw_capabilities)) {
+               for (i = 0; i < ar->vif_max; i++)
+                       fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV <<
+                               (i * HI_OPTION_FW_SUBMODE_BITS);
+       } else {
+               for (i = 0; i < ar->max_norm_iface; i++)
+                       fw_submode |= HI_OPTION_FW_SUBMODE_NONE <<
+                               (i * HI_OPTION_FW_SUBMODE_BITS);
 
-       for (i = ar->max_norm_iface; i < ar->vif_max; i++)
-               fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV <<
-                             (i * HI_OPTION_FW_SUBMODE_BITS);
+               for (i = ar->max_norm_iface; i < ar->vif_max; i++)
+                       fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV <<
+                               (i * HI_OPTION_FW_SUBMODE_BITS);
 
-       if (ar->p2p && ar->vif_max == 1)
-               fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV;
+               if (ar->p2p && ar->vif_max == 1)
+                       fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV;
+       }
 
        if (ath6kl_bmi_write_hi32(ar, hi_app_host_interest,
                                  HTC_PROTOCOL_VERSION) != 0) {