5555#define P2P_OUI "\x50\x6F\x9A" /* P2P OUI */
5656#define P2P_OUI_LEN 3 /* P2P OUI length */
5757
58+ /* Action Frame Constants */
59+ #define DOT11_ACTION_HDR_LEN 2 /* action frame category + action */
60+ #define DOT11_ACTION_CAT_OFF 0 /* category offset */
61+ #define DOT11_ACTION_ACT_OFF 1 /* action offset */
62+
63+ #define P2P_AF_DWELL_TIME 200
64+ #define P2P_AF_MIN_DWELL_TIME 100
65+ #define P2P_AF_MED_DWELL_TIME 400
66+ #define P2P_AF_LONG_DWELL_TIME 1000
67+ #define P2P_AF_TX_MAX_RETRY 5
68+ #define P2P_AF_MAX_WAIT_TIME 2000
69+ #define P2P_INVALID_CHANNEL -1
70+ #define P2P_CHANNEL_SYNC_RETRY 5
71+ #define P2P_AF_FRM_SCAN_MAX_WAIT 1500
72+
5873/* WiFi P2P Public Action Frame OUI Subtypes */
5974#define P2P_PAF_GON_REQ 0 /* Group Owner Negotiation Req */
6075#define P2P_PAF_GON_RSP 1 /* Group Owner Negotiation Rsp */
@@ -178,6 +193,17 @@ struct brcmf_p2psd_gas_pub_act_frame {
178193 u8 query_data [1 ];
179194};
180195
196+ /**
197+ * struct brcmf_config_af_params - Action Frame Parameters for tx.
198+ *
199+ * @max_tx_retry: max tx retry count if tx no ack.
200+ * @mpc_onoff: To make sure to send successfully action frame, we have to
201+ * turn off mpc 0: off, 1: on, (-1): do nothing
202+ */
203+ struct brcmf_config_af_params {
204+ s32 max_tx_retry ;
205+ s32 mpc_onoff ;
206+ };
181207
182208/**
183209 * brcmf_p2p_is_pub_action() - true if p2p public type frame.
@@ -590,8 +616,6 @@ static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p)
590616 * brcmf_p2p_enable_discovery() - initialize and configure discovery.
591617 *
592618 * @p2p: P2P specific data.
593- * @ie: buffer containing information elements.
594- * @ie_len: length of @ie buffer.
595619 *
596620 * Initializes the discovery device and configure the virtual interface.
597621 */
@@ -731,7 +755,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
731755 /* Override scan params to find a peer for a connection */
732756 if (num_chans == 1 ) {
733757 active = WL_SCAN_CONNECT_DWELL_TIME_MS ;
734- /* XXX WAR to sync with presence period of VSDB GO.
758+ /* WAR to sync with presence period of VSDB GO.
735759 * send probe request more frequently
736760 */
737761 nprobes = active / WL_SCAN_JOIN_PROBE_INTERVAL_MS ;
@@ -1031,6 +1055,269 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
10311055}
10321056
10331057
1058+ /**
1059+ * brcmf_p2p_notify_action_tx_complete() - transmit action frame complete
1060+ *
1061+ * @ifp: interfac control.
1062+ * @e: event message. Not used, to make it usable for fweh event dispatcher.
1063+ * @data: not used.
1064+ *
1065+ */
1066+ int brcmf_p2p_notify_action_tx_complete (struct brcmf_if * ifp ,
1067+ const struct brcmf_event_msg * e ,
1068+ void * data )
1069+ {
1070+ struct brcmf_cfg80211_info * cfg = ifp -> drvr -> config ;
1071+ struct brcmf_p2p_info * p2p = & cfg -> p2p ;
1072+
1073+ brcmf_dbg (INFO , "Enter: status %d\n" , e -> status );
1074+
1075+ if (e -> status == BRCMF_E_STATUS_SUCCESS )
1076+ set_bit (BRCMF_P2P_STATUS_ACTION_TX_COMPLETED , & p2p -> status );
1077+ else
1078+ set_bit (BRCMF_P2P_STATUS_ACTION_TX_NOACK , & p2p -> status );
1079+ /* for now complete the receiver process here !! */
1080+ complete (& p2p -> send_af_done );
1081+
1082+ return 0 ;
1083+ }
1084+
1085+
1086+ /**
1087+ * brcmf_p2p_tx_action_frame() - send action frame over fil.
1088+ *
1089+ * @p2p: p2p info struct for vif.
1090+ * @af_params: action frame data/info.
1091+ *
1092+ * Send an action frame immediately without doing channel synchronization.
1093+ *
1094+ * This function waits for a completion event before returning.
1095+ * The WLC_E_ACTION_FRAME_COMPLETE event will be received when the action
1096+ * frame is transmitted.
1097+ */
1098+ static s32 brcmf_p2p_tx_action_frame (struct brcmf_p2p_info * p2p ,
1099+ struct brcmf_fil_af_params_le * af_params )
1100+ {
1101+ struct brcmf_cfg80211_vif * vif ;
1102+ s32 err = 0 ;
1103+ s32 timeout = 0 ;
1104+
1105+ brcmf_dbg (TRACE , "Enter\n" );
1106+
1107+ clear_bit (BRCMF_P2P_STATUS_ACTION_TX_COMPLETED , & p2p -> status );
1108+ clear_bit (BRCMF_P2P_STATUS_ACTION_TX_NOACK , & p2p -> status );
1109+
1110+ vif = p2p -> bss_idx [P2PAPI_BSSCFG_DEVICE ].vif ;
1111+ err = brcmf_fil_bsscfg_data_set (vif -> ifp , "actframe" , af_params ,
1112+ sizeof (* af_params ));
1113+ if (err ) {
1114+ brcmf_err (" sending action frame has failed\n" );
1115+ goto exit ;
1116+ }
1117+
1118+ timeout = wait_for_completion_timeout (& p2p -> send_af_done ,
1119+ msecs_to_jiffies (P2P_AF_MAX_WAIT_TIME ));
1120+
1121+ if (test_bit (BRCMF_P2P_STATUS_ACTION_TX_COMPLETED , & p2p -> status )) {
1122+ brcmf_dbg (TRACE , "TX action frame operation is success\n" );
1123+ } else {
1124+ err = - EIO ;
1125+ brcmf_dbg (TRACE , "TX action frame operation has failed\n" );
1126+ }
1127+ /* clear status bit for action tx */
1128+ clear_bit (BRCMF_P2P_STATUS_ACTION_TX_COMPLETED , & p2p -> status );
1129+ clear_bit (BRCMF_P2P_STATUS_ACTION_TX_NOACK , & p2p -> status );
1130+
1131+ exit :
1132+ return err ;
1133+ }
1134+
1135+
1136+ /**
1137+ * brcmf_p2p_pub_af_tx() - public action frame tx routine.
1138+ *
1139+ * @cfg: driver private data for cfg80211 interface.
1140+ * @af_params: action frame data/info.
1141+ * @config_af_params: configuration data for action frame.
1142+ *
1143+ * routine which transmits ation frame public type.
1144+ */
1145+ static s32 brcmf_p2p_pub_af_tx (struct brcmf_cfg80211_info * cfg ,
1146+ struct brcmf_fil_af_params_le * af_params ,
1147+ struct brcmf_config_af_params * config_af_params )
1148+ {
1149+ struct brcmf_p2p_info * p2p = & cfg -> p2p ;
1150+ struct brcmf_fil_action_frame_le * action_frame ;
1151+ struct brcmf_p2p_pub_act_frame * act_frm ;
1152+ s32 err = 0 ;
1153+
1154+ action_frame = & af_params -> action_frame ;
1155+ act_frm = (struct brcmf_p2p_pub_act_frame * )(action_frame -> data );
1156+
1157+ switch (act_frm -> subtype ) {
1158+ case P2P_PAF_GON_REQ :
1159+ brcmf_dbg (TRACE , "P2P: GO_NEG_PHASE status set\n" );
1160+ set_bit (BRCMF_P2P_STATUS_GO_NEG_PHASE , & p2p -> status );
1161+ config_af_params -> mpc_onoff = 0 ;
1162+ p2p -> next_af_subtype = act_frm -> subtype + 1 ;
1163+ /* increase dwell time to wait for RESP frame */
1164+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_MED_DWELL_TIME );
1165+ break ;
1166+ case P2P_PAF_GON_RSP :
1167+ p2p -> next_af_subtype = act_frm -> subtype + 1 ;
1168+ /* increase dwell time to wait for CONF frame */
1169+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_MED_DWELL_TIME );
1170+ break ;
1171+ case P2P_PAF_GON_CONF :
1172+ /* If we reached till GO Neg confirmation reset the filter */
1173+ brcmf_dbg (TRACE , "P2P: GO_NEG_PHASE status cleared\n" );
1174+ clear_bit (BRCMF_P2P_STATUS_GO_NEG_PHASE , & p2p -> status );
1175+ /* turn on mpc again if go nego is done */
1176+ config_af_params -> mpc_onoff = 1 ;
1177+ /* minimize dwell time */
1178+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_MIN_DWELL_TIME );
1179+ break ;
1180+ case P2P_PAF_INVITE_REQ :
1181+ p2p -> next_af_subtype = act_frm -> subtype + 1 ;
1182+ /* increase dwell time */
1183+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_MED_DWELL_TIME );
1184+ break ;
1185+ case P2P_PAF_INVITE_RSP :
1186+ /* minimize dwell time */
1187+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_MIN_DWELL_TIME );
1188+ break ;
1189+ case P2P_PAF_DEVDIS_REQ :
1190+ p2p -> next_af_subtype = act_frm -> subtype + 1 ;
1191+ /* maximize dwell time to wait for RESP frame */
1192+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_LONG_DWELL_TIME );
1193+ break ;
1194+ case P2P_PAF_DEVDIS_RSP :
1195+ /* minimize dwell time */
1196+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_MIN_DWELL_TIME );
1197+ break ;
1198+ case P2P_PAF_PROVDIS_REQ :
1199+ config_af_params -> mpc_onoff = 0 ;
1200+ p2p -> next_af_subtype = act_frm -> subtype + 1 ;
1201+ /* increase dwell time to wait for RESP frame */
1202+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_MED_DWELL_TIME );
1203+ break ;
1204+ case P2P_PAF_PROVDIS_RSP :
1205+ /* wpa_supplicant send go nego req right after prov disc */
1206+ p2p -> next_af_subtype = P2P_PAF_GON_REQ ;
1207+ /* increase dwell time to MED level */
1208+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_MED_DWELL_TIME );
1209+ break ;
1210+ default :
1211+ brcmf_err ("Unknown p2p pub act frame subtype: %d\n" ,
1212+ act_frm -> subtype );
1213+ err = - EINVAL ;
1214+ }
1215+ return err ;
1216+ }
1217+
1218+ /**
1219+ * brcmf_p2p_send_action_frame() - send action frame .
1220+ *
1221+ * @cfg: driver private data for cfg80211 interface.
1222+ * @ndev: net device to transmit on.
1223+ * @af_params: configuration data for action frame.
1224+ */
1225+ bool brcmf_p2p_send_action_frame (struct brcmf_cfg80211_info * cfg ,
1226+ struct net_device * ndev ,
1227+ struct brcmf_fil_af_params_le * af_params )
1228+ {
1229+ struct brcmf_p2p_info * p2p = & cfg -> p2p ;
1230+ struct brcmf_fil_action_frame_le * action_frame ;
1231+ struct brcmf_config_af_params config_af_params ;
1232+ u16 action_frame_len ;
1233+ bool ack = false;
1234+ u8 category ;
1235+ u8 action ;
1236+ s32 tx_retry ;
1237+
1238+ action_frame = & af_params -> action_frame ;
1239+ action_frame_len = le16_to_cpu (action_frame -> len );
1240+
1241+ brcmf_p2p_print_actframe (true, action_frame -> data , action_frame_len );
1242+
1243+ /* Add the default dwell time. Dwell time to stay off-channel */
1244+ /* to wait for a response action frame after transmitting an */
1245+ /* GO Negotiation action frame */
1246+ af_params -> dwell_time = cpu_to_le32 (P2P_AF_DWELL_TIME );
1247+
1248+ category = action_frame -> data [DOT11_ACTION_CAT_OFF ];
1249+ action = action_frame -> data [DOT11_ACTION_ACT_OFF ];
1250+
1251+ /* initialize variables */
1252+ p2p -> next_af_subtype = P2P_PAF_SUBTYPE_INVALID ;
1253+
1254+ /* config parameters */
1255+ config_af_params .max_tx_retry = P2P_AF_TX_MAX_RETRY ;
1256+ config_af_params .mpc_onoff = -1 ;
1257+
1258+ if (brcmf_p2p_is_pub_action (action_frame -> data , action_frame_len )) {
1259+ /* p2p public action frame process */
1260+ if (brcmf_p2p_pub_af_tx (cfg , af_params , & config_af_params )) {
1261+ /* Just send unknown subtype frame with */
1262+ /* default parameters. */
1263+ brcmf_err ("P2P Public action frame, unknown subtype.\n" );
1264+ }
1265+ } else if (brcmf_p2p_is_gas_action (action_frame -> data ,
1266+ action_frame_len )) {
1267+ /* service discovery process */
1268+ if (action == P2PSD_ACTION_ID_GAS_IREQ ||
1269+ action == P2PSD_ACTION_ID_GAS_CREQ ) {
1270+ /* save next af suptype to cancel */
1271+ /* remaining dwell time */
1272+ p2p -> next_af_subtype = action + 1 ;
1273+
1274+ af_params -> dwell_time =
1275+ cpu_to_le32 (P2P_AF_MED_DWELL_TIME );
1276+ } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
1277+ action == P2PSD_ACTION_ID_GAS_CRESP ) {
1278+ /* configure service discovery response frame */
1279+ af_params -> dwell_time =
1280+ cpu_to_le32 (P2P_AF_MIN_DWELL_TIME );
1281+ } else {
1282+ brcmf_err ("Unknown action type: %d\n" , action );
1283+ goto exit ;
1284+ }
1285+ } else if (brcmf_p2p_is_p2p_action (action_frame -> data ,
1286+ action_frame_len )) {
1287+ /* do not configure anything. it will be */
1288+ /* sent with a default configuration */
1289+ } else {
1290+ brcmf_err ("Unknown Frame: category 0x%x, action 0x%x\n" ,
1291+ category , action );
1292+ return false;
1293+ }
1294+
1295+ /* if scan is ongoing, abort current scan. */
1296+ if (test_bit (BRCMF_SCAN_STATUS_BUSY , & cfg -> scan_status ))
1297+ brcmf_abort_scanning (cfg );
1298+
1299+ /* To make sure to send successfully action frame, turn off mpc */
1300+ if (config_af_params .mpc_onoff == 0 )
1301+ brcmf_set_mpc (ndev , 0 );
1302+
1303+ /* if failed, retry it. tx_retry_max value is configure by .... */
1304+ tx_retry = 0 ;
1305+ while ((ack == false) && (tx_retry < config_af_params .max_tx_retry )) {
1306+ ack = !brcmf_p2p_tx_action_frame (p2p , af_params );
1307+ tx_retry ++ ;
1308+ }
1309+ if (ack == false)
1310+ brcmf_err ("Failed to send Action Frame(retry %d)\n" , tx_retry );
1311+
1312+ exit :
1313+ /* if all done, turn mpc on again */
1314+ if (config_af_params .mpc_onoff == 1 )
1315+ brcmf_set_mpc (ndev , 1 );
1316+
1317+ return ack ;
1318+ }
1319+
1320+
10341321/**
10351322 * brcmf_p2p_attach() - attach for P2P.
10361323 *
@@ -1047,6 +1334,7 @@ void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg,
10471334 p2p -> bss_idx [P2PAPI_BSSCFG_PRIMARY ].vif = vif ;
10481335 brcmf_p2p_generate_bss_mac (p2p );
10491336 brcmf_p2p_set_firmware (p2p );
1337+ init_completion (& p2p -> send_af_done );
10501338}
10511339
10521340/**
0 commit comments