@@ -3919,6 +3919,88 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
39193919 return ret ;
39203920}
39213921
3922+ #ifdef CONFIG_NL80211_TESTMODE
3923+
3924+ enum mwifiex_tm_attr {
3925+ __MWIFIEX_TM_ATTR_INVALID = 0 ,
3926+ MWIFIEX_TM_ATTR_CMD = 1 ,
3927+ MWIFIEX_TM_ATTR_DATA = 2 ,
3928+
3929+ /* keep last */
3930+ __MWIFIEX_TM_ATTR_AFTER_LAST ,
3931+ MWIFIEX_TM_ATTR_MAX = __MWIFIEX_TM_ATTR_AFTER_LAST - 1 ,
3932+ };
3933+
3934+ static const struct nla_policy mwifiex_tm_policy [MWIFIEX_TM_ATTR_MAX + 1 ] = {
3935+ [MWIFIEX_TM_ATTR_CMD ] = { .type = NLA_U32 },
3936+ [MWIFIEX_TM_ATTR_DATA ] = { .type = NLA_BINARY ,
3937+ .len = MWIFIEX_SIZE_OF_CMD_BUFFER },
3938+ };
3939+
3940+ enum mwifiex_tm_command {
3941+ MWIFIEX_TM_CMD_HOSTCMD = 0 ,
3942+ };
3943+
3944+ static int mwifiex_tm_cmd (struct wiphy * wiphy , struct wireless_dev * wdev ,
3945+ void * data , int len )
3946+ {
3947+ struct mwifiex_private * priv = mwifiex_netdev_get_priv (wdev -> netdev );
3948+ struct mwifiex_ds_misc_cmd * hostcmd ;
3949+ struct nlattr * tb [MWIFIEX_TM_ATTR_MAX + 1 ];
3950+ struct mwifiex_adapter * adapter ;
3951+ struct sk_buff * skb ;
3952+ int err ;
3953+
3954+ if (!priv )
3955+ return - EINVAL ;
3956+ adapter = priv -> adapter ;
3957+
3958+ err = nla_parse (tb , MWIFIEX_TM_ATTR_MAX , data , len ,
3959+ mwifiex_tm_policy );
3960+ if (err )
3961+ return err ;
3962+
3963+ if (!tb [MWIFIEX_TM_ATTR_CMD ])
3964+ return - EINVAL ;
3965+
3966+ switch (nla_get_u32 (tb [MWIFIEX_TM_ATTR_CMD ])) {
3967+ case MWIFIEX_TM_CMD_HOSTCMD :
3968+ if (!tb [MWIFIEX_TM_ATTR_DATA ])
3969+ return - EINVAL ;
3970+
3971+ hostcmd = kzalloc (sizeof (* hostcmd ), GFP_KERNEL );
3972+ if (!hostcmd )
3973+ return - ENOMEM ;
3974+
3975+ hostcmd -> len = nla_len (tb [MWIFIEX_TM_ATTR_DATA ]);
3976+ memcpy (hostcmd -> cmd , nla_data (tb [MWIFIEX_TM_ATTR_DATA ]),
3977+ hostcmd -> len );
3978+
3979+ if (mwifiex_send_cmd (priv , 0 , 0 , 0 , hostcmd , true)) {
3980+ dev_err (priv -> adapter -> dev , "Failed to process hostcmd\n" );
3981+ return - EFAULT ;
3982+ }
3983+
3984+ /* process hostcmd response*/
3985+ skb = cfg80211_testmode_alloc_reply_skb (wiphy , hostcmd -> len );
3986+ if (!skb )
3987+ return - ENOMEM ;
3988+ err = nla_put (skb , MWIFIEX_TM_ATTR_DATA ,
3989+ hostcmd -> len , hostcmd -> cmd );
3990+ if (err ) {
3991+ kfree_skb (skb );
3992+ return - EMSGSIZE ;
3993+ }
3994+
3995+ err = cfg80211_testmode_reply (skb );
3996+ kfree (hostcmd );
3997+ return err ;
3998+ default :
3999+ return - EOPNOTSUPP ;
4000+ }
4001+ }
4002+ #endif
4003+
39224004static int
39234005mwifiex_cfg80211_start_radar_detection (struct wiphy * wiphy ,
39244006 struct net_device * dev ,
@@ -4031,6 +4113,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
40314113 .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch ,
40324114 .add_station = mwifiex_cfg80211_add_station ,
40334115 .change_station = mwifiex_cfg80211_change_station ,
4116+ CFG80211_TESTMODE_CMD (mwifiex_tm_cmd )
40344117 .get_channel = mwifiex_cfg80211_get_channel ,
40354118 .start_radar_detection = mwifiex_cfg80211_start_radar_detection ,
40364119 .channel_switch = mwifiex_cfg80211_channel_switch ,
0 commit comments