aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2012-12-15 19:41:37 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-01-07 15:16:52 -0500
commit7f878b0d96e6b3bd27d736fb2fb7e3cc94b16b26 (patch)
tree29a67f378d034766d7c7b4ac52a4df4d5f282ac9 /drivers/net
parent5ae994d0984ddc2f1e79c4f8de7189faecfc0af9 (diff)
carl9170: allow P2P_GO interface creation after P2P_CLIENT
Janusz Dziedzic reported that after a change in wpa_supplicant ["nl80211: Automatically use concurrent P2P if possible"], carl9170 was no longer able to host a P2P network. This patch tackles the problem by allowing GO interfaces to be registered, long after the P2P_CLIENT interface is brought up. Reported-by: Janusz Dziedzic <janusz.dziedzic@gmail.com> Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index ce8ae1e6bd3b..95e4bf05e559 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -580,7 +580,7 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
580 struct ieee80211_vif *vif) 580 struct ieee80211_vif *vif)
581{ 581{
582 struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv; 582 struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
583 struct ieee80211_vif *main_vif; 583 struct ieee80211_vif *main_vif, *old_main = NULL;
584 struct ar9170 *ar = hw->priv; 584 struct ar9170 *ar = hw->priv;
585 int vif_id = -1, err = 0; 585 int vif_id = -1, err = 0;
586 586
@@ -602,6 +602,15 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
602 goto init; 602 goto init;
603 } 603 }
604 604
605 /* Because the AR9170 HW's MAC doesn't provide full support for
606 * multiple, independent interfaces [of different operation modes].
607 * We have to select ONE main interface [main mode of HW], but we
608 * can have multiple slaves [AKA: entry in the ACK-table].
609 *
610 * The first (from HEAD/TOP) interface in the ar->vif_list is
611 * always the main intf. All following intfs in this list
612 * are considered to be slave intfs.
613 */
605 main_vif = carl9170_get_main_vif(ar); 614 main_vif = carl9170_get_main_vif(ar);
606 615
607 if (main_vif) { 616 if (main_vif) {
@@ -610,6 +619,18 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
610 if (vif->type == NL80211_IFTYPE_STATION) 619 if (vif->type == NL80211_IFTYPE_STATION)
611 break; 620 break;
612 621
622 /* P2P GO [master] use-case
623 * Because the P2P GO station is selected dynamically
624 * by all participating peers of a WIFI Direct network,
625 * the driver has be able to change the main interface
626 * operating mode on the fly.
627 */
628 if (main_vif->p2p && vif->p2p &&
629 vif->type == NL80211_IFTYPE_AP) {
630 old_main = main_vif;
631 break;
632 }
633
613 err = -EBUSY; 634 err = -EBUSY;
614 rcu_read_unlock(); 635 rcu_read_unlock();
615 636
@@ -648,14 +669,41 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
648 vif_priv->id = vif_id; 669 vif_priv->id = vif_id;
649 vif_priv->enable_beacon = false; 670 vif_priv->enable_beacon = false;
650 ar->vifs++; 671 ar->vifs++;
651 list_add_tail_rcu(&vif_priv->list, &ar->vif_list); 672 if (old_main) {
673 /* We end up in here, if the main interface is being replaced.
674 * Put the new main interface at the HEAD of the list and the
675 * previous inteface will automatically become second in line.
676 */
677 list_add_rcu(&vif_priv->list, &ar->vif_list);
678 } else {
679 /* Add new inteface. If the list is empty, it will become the
680 * main inteface, otherwise it will be slave.
681 */
682 list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
683 }
652 rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif); 684 rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif);
653 685
654init: 686init:
655 if (carl9170_get_main_vif(ar) == vif) { 687 main_vif = carl9170_get_main_vif(ar);
688
689 if (main_vif == vif) {
656 rcu_assign_pointer(ar->beacon_iter, vif_priv); 690 rcu_assign_pointer(ar->beacon_iter, vif_priv);
657 rcu_read_unlock(); 691 rcu_read_unlock();
658 692
693 if (old_main) {
694 struct carl9170_vif_info *old_main_priv =
695 (void *) old_main->drv_priv;
696 /* downgrade old main intf to slave intf.
697 * NOTE: We are no longer under rcu_read_lock.
698 * But we are still holding ar->mutex, so the
699 * vif data [id, addr] is safe.
700 */
701 err = carl9170_mod_virtual_mac(ar, old_main_priv->id,
702 old_main->addr);
703 if (err)
704 goto unlock;
705 }
706
659 err = carl9170_init_interface(ar, vif); 707 err = carl9170_init_interface(ar, vif);
660 if (err) 708 if (err)
661 goto unlock; 709 goto unlock;