aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2015-01-28 05:12:05 -0500
committerKalle Valo <kvalo@codeaurora.org>2015-01-29 03:20:19 -0500
commit047eaaf64503c2902d1e054d5b944de18d14b28c (patch)
treebd67ef9c96cd132d0d0b6889cb1079e7590e8a95 /drivers/net/wireless/mwifiex
parent76c504ca1e7de8555cbf18a0ef08d29ee462c8eb (diff)
mwifiex: support conversion to any virtual interface type
Currently, we support virtual interface type change from station<=>adhoc or station <=> p2p client/GO. This patch adds support to change virtual interface type to any of the type advertised in interface combinations. Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Cathy Luo <cluo@marvell.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c331
-rw-r--r--drivers/net/wireless/mwifiex/main.c2
-rw-r--r--drivers/net/wireless/mwifiex/main.h2
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c30
4 files changed, 301 insertions, 64 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index a0221b5eff93..30ea94a1767c 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -656,9 +656,6 @@ mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)
656{ 656{
657 u16 mode = P2P_MODE_DISABLE; 657 u16 mode = P2P_MODE_DISABLE;
658 658
659 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA)
660 mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA);
661
662 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, 659 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
663 HostCmd_ACT_GEN_SET, 0, &mode, true)) 660 HostCmd_ACT_GEN_SET, 0, &mode, true))
664 return -1; 661 return -1;
@@ -715,12 +712,249 @@ mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)
715 HostCmd_ACT_GEN_SET, 0, &mode, true)) 712 HostCmd_ACT_GEN_SET, 0, &mode, true))
716 return -1; 713 return -1;
717 714
718 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) 715 return 0;
719 mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_UAP); 716}
717
718static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
719{
720 priv->mgmt_frame_mask = 0;
721 if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
722 HostCmd_ACT_GEN_SET, 0,
723 &priv->mgmt_frame_mask, false)) {
724 dev_warn(priv->adapter->dev,
725 "could not unregister mgmt frame rx\n");
726 return -1;
727 }
728
729 mwifiex_deauthenticate(priv, NULL);
730 mwifiex_free_priv(priv);
731 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
732 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
733 priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
734
735 return 0;
736}
737
738static int
739mwifiex_init_new_priv_params(struct mwifiex_private *priv,
740 struct net_device *dev,
741 enum nl80211_iftype type)
742{
743 mwifiex_init_priv(priv);
744
745 priv->bss_mode = type;
746 priv->wdev.iftype = type;
747
748 mwifiex_init_priv_params(priv, priv->netdev);
749 priv->bss_started = 0;
750
751 switch (type) {
752 case NL80211_IFTYPE_STATION:
753 case NL80211_IFTYPE_ADHOC:
754 priv->bss_role = MWIFIEX_BSS_ROLE_STA;
755 priv->bss_type = MWIFIEX_BSS_TYPE_STA;
756 break;
757 case NL80211_IFTYPE_P2P_CLIENT:
758 case NL80211_IFTYPE_P2P_GO:
759 priv->bss_role = MWIFIEX_BSS_ROLE_STA;
760 priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
761 break;
762 case NL80211_IFTYPE_AP:
763 priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
764 priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
765 break;
766 default:
767 dev_err(priv->adapter->dev,
768 "%s: changing to %d not supported\n",
769 dev->name, type);
770 return -EOPNOTSUPP;
771 }
772
773 return 0;
774}
775
776static int
777mwifiex_change_vif_to_p2p(struct net_device *dev,
778 enum nl80211_iftype curr_iftype,
779 enum nl80211_iftype type, u32 *flags,
780 struct vif_params *params)
781{
782 struct mwifiex_private *priv;
783 struct mwifiex_adapter *adapter;
784
785 priv = mwifiex_netdev_get_priv(dev);
786
787 if (!priv)
788 return -1;
789
790 adapter = priv->adapter;
791
792 if (adapter->curr_iface_comb.p2p_intf ==
793 adapter->iface_limit.p2p_intf) {
794 dev_err(adapter->dev,
795 "cannot create multiple P2P ifaces\n");
796 return -1;
797 }
798
799 dev_dbg(priv->adapter->dev, "%s: changing role to p2p\n", dev->name);
800
801 if (mwifiex_deinit_priv_params(priv))
802 return -1;
803 if (mwifiex_init_new_priv_params(priv, dev, type))
804 return -1;
805
806 switch (type) {
807 case NL80211_IFTYPE_P2P_CLIENT:
808 if (mwifiex_cfg80211_init_p2p_client(priv))
809 return -EFAULT;
810 break;
811 case NL80211_IFTYPE_P2P_GO:
812 if (mwifiex_cfg80211_init_p2p_go(priv))
813 return -EFAULT;
814 break;
815 default:
816 dev_err(priv->adapter->dev,
817 "%s: changing to %d not supported\n",
818 dev->name, type);
819 return -EOPNOTSUPP;
820 }
821
822 if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
823 HostCmd_ACT_GEN_SET, 0, NULL, true))
824 return -1;
825
826 if (mwifiex_sta_init_cmd(priv, false, false))
827 return -1;
828
829 switch (curr_iftype) {
830 case NL80211_IFTYPE_STATION:
831 case NL80211_IFTYPE_ADHOC:
832 adapter->curr_iface_comb.sta_intf--;
833 break;
834 case NL80211_IFTYPE_AP:
835 adapter->curr_iface_comb.uap_intf--;
836 break;
837 default:
838 break;
839 }
840
841 adapter->curr_iface_comb.p2p_intf++;
842 dev->ieee80211_ptr->iftype = type;
720 843
721 return 0; 844 return 0;
722} 845}
723 846
847static int
848mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,
849 enum nl80211_iftype curr_iftype,
850 enum nl80211_iftype type, u32 *flags,
851 struct vif_params *params)
852{
853 struct mwifiex_private *priv;
854 struct mwifiex_adapter *adapter;
855
856 priv = mwifiex_netdev_get_priv(dev);
857
858 if (!priv)
859 return -1;
860
861 adapter = priv->adapter;
862
863 if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT &&
864 curr_iftype != NL80211_IFTYPE_P2P_GO) &&
865 (adapter->curr_iface_comb.sta_intf ==
866 adapter->iface_limit.sta_intf)) {
867 dev_err(adapter->dev,
868 "cannot create multiple station/adhoc ifaces\n");
869 return -1;
870 }
871
872 if (type == NL80211_IFTYPE_STATION)
873 dev_notice(adapter->dev,
874 "%s: changing role to station\n", dev->name);
875 else
876 dev_notice(adapter->dev,
877 "%s: changing role to adhoc\n", dev->name);
878
879 if (mwifiex_deinit_priv_params(priv))
880 return -1;
881 if (mwifiex_init_new_priv_params(priv, dev, type))
882 return -1;
883 if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
884 HostCmd_ACT_GEN_SET, 0, NULL, true))
885 return -1;
886 if (mwifiex_sta_init_cmd(priv, false, false))
887 return -1;
888
889 switch (curr_iftype) {
890 case NL80211_IFTYPE_P2P_CLIENT:
891 case NL80211_IFTYPE_P2P_GO:
892 adapter->curr_iface_comb.p2p_intf--;
893 break;
894 case NL80211_IFTYPE_AP:
895 adapter->curr_iface_comb.uap_intf--;
896 break;
897 default:
898 break;
899 }
900
901 adapter->curr_iface_comb.sta_intf++;
902 dev->ieee80211_ptr->iftype = type;
903 return 0;
904}
905
906static int
907mwifiex_change_vif_to_ap(struct net_device *dev,
908 enum nl80211_iftype curr_iftype,
909 enum nl80211_iftype type, u32 *flags,
910 struct vif_params *params)
911{
912 struct mwifiex_private *priv;
913 struct mwifiex_adapter *adapter;
914
915 priv = mwifiex_netdev_get_priv(dev);
916
917 if (!priv)
918 return -1;
919
920 adapter = priv->adapter;
921
922 if (adapter->curr_iface_comb.uap_intf ==
923 adapter->iface_limit.uap_intf) {
924 dev_err(adapter->dev,
925 "cannot create multiple AP ifaces\n");
926 return -1;
927 }
928
929 dev_notice(adapter->dev, "%s: changing role to AP\n", dev->name);
930
931 if (mwifiex_deinit_priv_params(priv))
932 return -1;
933 if (mwifiex_init_new_priv_params(priv, dev, type))
934 return -1;
935 if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
936 HostCmd_ACT_GEN_SET, 0, NULL, true))
937 return -1;
938 if (mwifiex_sta_init_cmd(priv, false, false))
939 return -1;
940
941 switch (curr_iftype) {
942 case NL80211_IFTYPE_P2P_CLIENT:
943 case NL80211_IFTYPE_P2P_GO:
944 adapter->curr_iface_comb.p2p_intf--;
945 break;
946 case NL80211_IFTYPE_STATION:
947 case NL80211_IFTYPE_ADHOC:
948 adapter->curr_iface_comb.sta_intf--;
949 break;
950 default:
951 break;
952 }
953
954 adapter->curr_iface_comb.uap_intf++;
955 dev->ieee80211_ptr->iftype = type;
956 return 0;
957}
724/* 958/*
725 * CFG802.11 operation handler to change interface type. 959 * CFG802.11 operation handler to change interface type.
726 */ 960 */
@@ -730,19 +964,32 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
730 enum nl80211_iftype type, u32 *flags, 964 enum nl80211_iftype type, u32 *flags,
731 struct vif_params *params) 965 struct vif_params *params)
732{ 966{
733 int ret;
734 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); 967 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
968 enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype;
735 969
736 switch (dev->ieee80211_ptr->iftype) { 970 switch (curr_iftype) {
737 case NL80211_IFTYPE_ADHOC: 971 case NL80211_IFTYPE_ADHOC:
738 switch (type) { 972 switch (type) {
739 case NL80211_IFTYPE_STATION: 973 case NL80211_IFTYPE_STATION:
740 break; 974 priv->bss_mode = type;
975 priv->sec_info.authentication_mode =
976 NL80211_AUTHTYPE_OPEN_SYSTEM;
977 dev->ieee80211_ptr->iftype = type;
978 mwifiex_deauthenticate(priv, NULL);
979 return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
980 HostCmd_ACT_GEN_SET, 0, NULL,
981 true);
982 case NL80211_IFTYPE_P2P_CLIENT:
983 case NL80211_IFTYPE_P2P_GO:
984 return mwifiex_change_vif_to_p2p(dev, curr_iftype,
985 type, flags, params);
986 case NL80211_IFTYPE_AP:
987 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
988 flags, params);
741 case NL80211_IFTYPE_UNSPECIFIED: 989 case NL80211_IFTYPE_UNSPECIFIED:
742 wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name); 990 wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name);
743 case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ 991 case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */
744 return 0; 992 return 0;
745 case NL80211_IFTYPE_AP:
746 default: 993 default:
747 wiphy_err(wiphy, "%s: changing to %d not supported\n", 994 wiphy_err(wiphy, "%s: changing to %d not supported\n",
748 dev->name, type); 995 dev->name, type);
@@ -752,22 +999,25 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
752 case NL80211_IFTYPE_STATION: 999 case NL80211_IFTYPE_STATION:
753 switch (type) { 1000 switch (type) {
754 case NL80211_IFTYPE_ADHOC: 1001 case NL80211_IFTYPE_ADHOC:
755 break; 1002 priv->bss_mode = type;
756 case NL80211_IFTYPE_P2P_CLIENT: 1003 priv->sec_info.authentication_mode =
757 if (mwifiex_cfg80211_init_p2p_client(priv)) 1004 NL80211_AUTHTYPE_OPEN_SYSTEM;
758 return -EFAULT;
759 dev->ieee80211_ptr->iftype = type; 1005 dev->ieee80211_ptr->iftype = type;
760 return 0; 1006 mwifiex_deauthenticate(priv, NULL);
1007 return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
1008 HostCmd_ACT_GEN_SET, 0, NULL,
1009 true);
1010 case NL80211_IFTYPE_P2P_CLIENT:
761 case NL80211_IFTYPE_P2P_GO: 1011 case NL80211_IFTYPE_P2P_GO:
762 if (mwifiex_cfg80211_init_p2p_go(priv)) 1012 return mwifiex_change_vif_to_p2p(dev, curr_iftype,
763 return -EFAULT; 1013 type, flags, params);
764 dev->ieee80211_ptr->iftype = type; 1014 case NL80211_IFTYPE_AP:
765 return 0; 1015 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
1016 flags, params);
766 case NL80211_IFTYPE_UNSPECIFIED: 1017 case NL80211_IFTYPE_UNSPECIFIED:
767 wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); 1018 wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name);
768 case NL80211_IFTYPE_STATION: /* This shouldn't happen */ 1019 case NL80211_IFTYPE_STATION: /* This shouldn't happen */
769 return 0; 1020 return 0;
770 case NL80211_IFTYPE_AP:
771 default: 1021 default:
772 wiphy_err(wiphy, "%s: changing to %d not supported\n", 1022 wiphy_err(wiphy, "%s: changing to %d not supported\n",
773 dev->name, type); 1023 dev->name, type);
@@ -776,12 +1026,20 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
776 break; 1026 break;
777 case NL80211_IFTYPE_AP: 1027 case NL80211_IFTYPE_AP:
778 switch (type) { 1028 switch (type) {
1029 case NL80211_IFTYPE_ADHOC:
1030 case NL80211_IFTYPE_STATION:
1031 return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
1032 type, flags,
1033 params);
1034 break;
1035 case NL80211_IFTYPE_P2P_CLIENT:
1036 case NL80211_IFTYPE_P2P_GO:
1037 return mwifiex_change_vif_to_p2p(dev, curr_iftype,
1038 type, flags, params);
779 case NL80211_IFTYPE_UNSPECIFIED: 1039 case NL80211_IFTYPE_UNSPECIFIED:
780 wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name); 1040 wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name);
781 case NL80211_IFTYPE_AP: /* This shouldn't happen */ 1041 case NL80211_IFTYPE_AP: /* This shouldn't happen */
782 return 0; 1042 return 0;
783 case NL80211_IFTYPE_ADHOC:
784 case NL80211_IFTYPE_STATION:
785 default: 1043 default:
786 wiphy_err(wiphy, "%s: changing to %d not supported\n", 1044 wiphy_err(wiphy, "%s: changing to %d not supported\n",
787 dev->name, type); 1045 dev->name, type);
@@ -792,11 +1050,30 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
792 case NL80211_IFTYPE_P2P_GO: 1050 case NL80211_IFTYPE_P2P_GO:
793 switch (type) { 1051 switch (type) {
794 case NL80211_IFTYPE_STATION: 1052 case NL80211_IFTYPE_STATION:
795 if (mwifiex_cfg80211_deinit_p2p(priv)) 1053 if (mwifiex_cfg80211_init_p2p_client(priv))
796 return -EFAULT; 1054 return -EFAULT;
797 dev->ieee80211_ptr->iftype = type; 1055 dev->ieee80211_ptr->iftype = type;
1056 break;
1057 case NL80211_IFTYPE_ADHOC:
1058 if (mwifiex_cfg80211_deinit_p2p(priv))
1059 return -EFAULT;
1060 return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
1061 type, flags,
1062 params);
1063 break;
1064 case NL80211_IFTYPE_AP:
1065 if (mwifiex_cfg80211_deinit_p2p(priv))
1066 return -EFAULT;
1067 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
1068 flags, params);
1069 case NL80211_IFTYPE_UNSPECIFIED:
1070 wiphy_warn(wiphy, "%s: kept type as P2P\n", dev->name);
1071 case NL80211_IFTYPE_P2P_CLIENT:
1072 case NL80211_IFTYPE_P2P_GO:
798 return 0; 1073 return 0;
799 default: 1074 default:
1075 wiphy_err(wiphy, "%s: changing to %d not supported\n",
1076 dev->name, type);
800 return -EOPNOTSUPP; 1077 return -EOPNOTSUPP;
801 } 1078 }
802 break; 1079 break;
@@ -806,16 +1083,8 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
806 return -EOPNOTSUPP; 1083 return -EOPNOTSUPP;
807 } 1084 }
808 1085
809 dev->ieee80211_ptr->iftype = type;
810 priv->bss_mode = type;
811 mwifiex_deauthenticate(priv, NULL);
812
813 priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
814
815 ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
816 HostCmd_ACT_GEN_SET, 0, NULL, true);
817 1086
818 return ret; 1087 return 0;
819} 1088}
820 1089
821static void 1090static void
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index cb9cab2b0ec0..30e519369ba6 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -961,7 +961,7 @@ static const struct net_device_ops mwifiex_netdev_ops = {
961 * In addition, the CFG80211 work queue is also created. 961 * In addition, the CFG80211 work queue is also created.
962 */ 962 */
963void mwifiex_init_priv_params(struct mwifiex_private *priv, 963void mwifiex_init_priv_params(struct mwifiex_private *priv,
964 struct net_device *dev) 964 struct net_device *dev)
965{ 965{
966 dev->netdev_ops = &mwifiex_netdev_ops; 966 dev->netdev_ops = &mwifiex_netdev_ops;
967 dev->destructor = free_netdev; 967 dev->destructor = free_netdev;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 78304a714512..9e839cd64505 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -1261,8 +1261,6 @@ int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
1261 struct ieee80211_channel *chan, 1261 struct ieee80211_channel *chan,
1262 unsigned int duration); 1262 unsigned int duration);
1263 1263
1264int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role);
1265
1266int mwifiex_get_stats_info(struct mwifiex_private *priv, 1264int mwifiex_get_stats_info(struct mwifiex_private *priv,
1267 struct mwifiex_ds_get_stats *log); 1265 struct mwifiex_ds_get_stats *log);
1268 1266
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 2faa5174fe73..0599e41e253c 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -1135,36 +1135,6 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
1135 return roc_cfg.status; 1135 return roc_cfg.status;
1136} 1136}
1137 1137
1138int
1139mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role)
1140{
1141 if (GET_BSS_ROLE(priv) == bss_role) {
1142 dev_dbg(priv->adapter->dev,
1143 "info: already in the desired role.\n");
1144 return 0;
1145 }
1146
1147 mwifiex_free_priv(priv);
1148 mwifiex_init_priv(priv);
1149
1150 priv->bss_role = bss_role;
1151 switch (bss_role) {
1152 case MWIFIEX_BSS_ROLE_UAP:
1153 priv->bss_mode = NL80211_IFTYPE_AP;
1154 break;
1155 case MWIFIEX_BSS_ROLE_STA:
1156 case MWIFIEX_BSS_ROLE_ANY:
1157 default:
1158 priv->bss_mode = NL80211_IFTYPE_STATION;
1159 break;
1160 }
1161
1162 mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
1163 HostCmd_ACT_GEN_SET, 0, NULL, true);
1164
1165 return mwifiex_sta_init_cmd(priv, false, false);
1166}
1167
1168/* 1138/*
1169 * Sends IOCTL request to get statistics information. 1139 * Sends IOCTL request to get statistics information.
1170 * 1140 *