diff options
author | Amitkumar Karwar <akarwar@marvell.com> | 2013-03-04 19:27:59 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-03-06 16:29:17 -0500 |
commit | 7da060c1c01b103d181dba39bce9bd141a945f99 (patch) | |
tree | 17eff88bff5c5a61a930430684fa0a5a98cdb0a6 /drivers/net/wireless/mwifiex | |
parent | 0d7f53e34d3f5f82c0f4941356a02285a78807a4 (diff) |
mwifiex: add WOWLAN support
Currently 'magic-packet' and 'patterns' options in 'iw wowlan'
command are supported.
Appropriate packet filters for wowlan are configured in firmware
based on provided patterns and/or magic-packet option.
For examples,
wake-on ARP request for 192.168.0.100:
iw phy0 wowlan enable patterns ff:ff:ff:ff:ff:ff 20+08:06
46+c0:a8:00:64
wake-on RX packets sent from IP address 192.168.0.88:
iw phy0 wowlan enable patterns 34+c0:a8:00:58
wake-on RX packets with TCP destination port 80
iw phy0 wowlan enable patterns 44+50
wake-on MagicPacket:
iw phy0 wowlan enable magic-packet
wake-on MagicPacket or patterns:
iw phy0 wowlan enable magic-packet patterns 12+00:11:22:33:44:55
18+00:50:43:21
wake-on IPv4 multicast packets:
iw phy0 wowlan enable patterns 01:00:5e
wake-on IPv6 multicast packets:
iw phy0 wowlan enable patterns 33:33
disable all wowlan options
iw phy0 wowlan disable
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 156 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/fw.h | 32 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/ioctl.h | 23 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmd.c | 77 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmdresp.c | 2 |
6 files changed, 292 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 45790faf6ebb..df30107225f8 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -2294,6 +2294,149 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2294 | } | 2294 | } |
2295 | EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); | 2295 | EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); |
2296 | 2296 | ||
2297 | #ifdef CONFIG_PM | ||
2298 | static bool | ||
2299 | mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat, | ||
2300 | s8 *byte_seq) | ||
2301 | { | ||
2302 | int j, k, valid_byte_cnt = 0; | ||
2303 | bool dont_care_byte = false; | ||
2304 | |||
2305 | for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) { | ||
2306 | for (k = 0; k < 8; k++) { | ||
2307 | if (pat->mask[j] & 1 << k) { | ||
2308 | memcpy(byte_seq + valid_byte_cnt, | ||
2309 | &pat->pattern[j * 8 + k], 1); | ||
2310 | valid_byte_cnt++; | ||
2311 | if (dont_care_byte) | ||
2312 | return false; | ||
2313 | } else { | ||
2314 | if (valid_byte_cnt) | ||
2315 | dont_care_byte = true; | ||
2316 | } | ||
2317 | |||
2318 | if (valid_byte_cnt > MAX_BYTESEQ) | ||
2319 | return false; | ||
2320 | } | ||
2321 | } | ||
2322 | |||
2323 | byte_seq[MAX_BYTESEQ] = valid_byte_cnt; | ||
2324 | |||
2325 | return true; | ||
2326 | } | ||
2327 | |||
2328 | static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, | ||
2329 | struct cfg80211_wowlan *wowlan) | ||
2330 | { | ||
2331 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | ||
2332 | struct mwifiex_ds_mef_cfg mef_cfg; | ||
2333 | struct mwifiex_mef_entry *mef_entry; | ||
2334 | int i, filt_num = 0, ret; | ||
2335 | bool first_pat = true; | ||
2336 | u8 byte_seq[MAX_BYTESEQ + 1]; | ||
2337 | const u8 ipv4_mc_mac[] = {0x33, 0x33}; | ||
2338 | const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; | ||
2339 | struct mwifiex_private *priv = | ||
2340 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
2341 | |||
2342 | if (!wowlan) { | ||
2343 | dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); | ||
2344 | return 0; | ||
2345 | } | ||
2346 | |||
2347 | if (!priv->media_connected) { | ||
2348 | dev_warn(adapter->dev, | ||
2349 | "Can not configure WOWLAN in disconnected state\n"); | ||
2350 | return 0; | ||
2351 | } | ||
2352 | |||
2353 | memset(&mef_cfg, 0, sizeof(mef_cfg)); | ||
2354 | mef_cfg.num_entries = 1; | ||
2355 | mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL); | ||
2356 | mef_cfg.mef_entry = mef_entry; | ||
2357 | mef_entry->mode = MEF_MODE_HOST_SLEEP; | ||
2358 | mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; | ||
2359 | |||
2360 | for (i = 0; i < wowlan->n_patterns; i++) { | ||
2361 | memset(byte_seq, 0, sizeof(byte_seq)); | ||
2362 | if (!mwifiex_is_pattern_supported(&wowlan->patterns[i], | ||
2363 | byte_seq)) { | ||
2364 | wiphy_err(wiphy, "Pattern not supported\n"); | ||
2365 | kfree(mef_entry); | ||
2366 | return -EOPNOTSUPP; | ||
2367 | } | ||
2368 | |||
2369 | if (!wowlan->patterns[i].pkt_offset) { | ||
2370 | if (!(byte_seq[0] & 0x01) && | ||
2371 | (byte_seq[MAX_BYTESEQ] == 1)) { | ||
2372 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | ||
2373 | continue; | ||
2374 | } else if (is_broadcast_ether_addr(byte_seq)) { | ||
2375 | mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST; | ||
2376 | continue; | ||
2377 | } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && | ||
2378 | (byte_seq[MAX_BYTESEQ] == 2)) || | ||
2379 | (!memcmp(byte_seq, ipv6_mc_mac, 3) && | ||
2380 | (byte_seq[MAX_BYTESEQ] == 3))) { | ||
2381 | mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST; | ||
2382 | continue; | ||
2383 | } | ||
2384 | } | ||
2385 | |||
2386 | mef_entry->filter[filt_num].repeat = 1; | ||
2387 | mef_entry->filter[filt_num].offset = | ||
2388 | wowlan->patterns[i].pkt_offset; | ||
2389 | memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq, | ||
2390 | sizeof(byte_seq)); | ||
2391 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2392 | |||
2393 | if (first_pat) | ||
2394 | first_pat = false; | ||
2395 | else | ||
2396 | mef_entry->filter[filt_num].filt_action = TYPE_AND; | ||
2397 | |||
2398 | filt_num++; | ||
2399 | } | ||
2400 | |||
2401 | if (wowlan->magic_pkt) { | ||
2402 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | ||
2403 | mef_entry->filter[filt_num].repeat = 16; | ||
2404 | memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, | ||
2405 | ETH_ALEN); | ||
2406 | mef_entry->filter[filt_num].byte_seq[MAX_BYTESEQ] = ETH_ALEN; | ||
2407 | mef_entry->filter[filt_num].offset = 14; | ||
2408 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2409 | if (filt_num) | ||
2410 | mef_entry->filter[filt_num].filt_action = TYPE_OR; | ||
2411 | } | ||
2412 | |||
2413 | if (!mef_cfg.criteria) | ||
2414 | mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | | ||
2415 | MWIFIEX_CRITERIA_UNICAST | | ||
2416 | MWIFIEX_CRITERIA_MULTICAST; | ||
2417 | |||
2418 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MEF_CFG, | ||
2419 | HostCmd_ACT_GEN_SET, 0, | ||
2420 | &mef_cfg); | ||
2421 | |||
2422 | kfree(mef_entry); | ||
2423 | return ret; | ||
2424 | } | ||
2425 | |||
2426 | static int mwifiex_cfg80211_resume(struct wiphy *wiphy) | ||
2427 | { | ||
2428 | return 0; | ||
2429 | } | ||
2430 | |||
2431 | static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy, | ||
2432 | bool enabled) | ||
2433 | { | ||
2434 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | ||
2435 | |||
2436 | device_set_wakeup_enable(adapter->dev, enabled); | ||
2437 | } | ||
2438 | #endif | ||
2439 | |||
2297 | /* station cfg80211 operations */ | 2440 | /* station cfg80211 operations */ |
2298 | static struct cfg80211_ops mwifiex_cfg80211_ops = { | 2441 | static struct cfg80211_ops mwifiex_cfg80211_ops = { |
2299 | .add_virtual_intf = mwifiex_add_virtual_intf, | 2442 | .add_virtual_intf = mwifiex_add_virtual_intf, |
@@ -2322,6 +2465,11 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
2322 | .change_beacon = mwifiex_cfg80211_change_beacon, | 2465 | .change_beacon = mwifiex_cfg80211_change_beacon, |
2323 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, | 2466 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, |
2324 | .set_antenna = mwifiex_cfg80211_set_antenna, | 2467 | .set_antenna = mwifiex_cfg80211_set_antenna, |
2468 | #ifdef CONFIG_PM | ||
2469 | .suspend = mwifiex_cfg80211_suspend, | ||
2470 | .resume = mwifiex_cfg80211_resume, | ||
2471 | .set_wakeup = mwifiex_cfg80211_set_wakeup, | ||
2472 | #endif | ||
2325 | }; | 2473 | }; |
2326 | 2474 | ||
2327 | /* | 2475 | /* |
@@ -2380,6 +2528,14 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2380 | 2528 | ||
2381 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); | 2529 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); |
2382 | 2530 | ||
2531 | #ifdef CONFIG_PM | ||
2532 | wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; | ||
2533 | wiphy->wowlan.n_patterns = MWIFIEX_MAX_FILTERS; | ||
2534 | wiphy->wowlan.pattern_min_len = 1; | ||
2535 | wiphy->wowlan.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN; | ||
2536 | wiphy->wowlan.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN; | ||
2537 | #endif | ||
2538 | |||
2383 | wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | 2539 | wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | |
2384 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 2540 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
2385 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | 2541 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 5a5d06659d57..6d6e5ae71eaa 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -300,6 +300,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
300 | #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f | 300 | #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f |
301 | #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 | 301 | #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 |
302 | #define HostCmd_CMD_VERSION_EXT 0x0097 | 302 | #define HostCmd_CMD_VERSION_EXT 0x0097 |
303 | #define HostCmd_CMD_MEF_CFG 0x009a | ||
303 | #define HostCmd_CMD_RSSI_INFO 0x00a4 | 304 | #define HostCmd_CMD_RSSI_INFO 0x00a4 |
304 | #define HostCmd_CMD_FUNC_INIT 0x00a9 | 305 | #define HostCmd_CMD_FUNC_INIT 0x00a9 |
305 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa | 306 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa |
@@ -473,6 +474,23 @@ enum P2P_MODES { | |||
473 | #define EVENT_GET_BSS_TYPE(event_cause) \ | 474 | #define EVENT_GET_BSS_TYPE(event_cause) \ |
474 | (((event_cause) >> 24) & 0x00ff) | 475 | (((event_cause) >> 24) & 0x00ff) |
475 | 476 | ||
477 | #define MWIFIEX_MAX_PATTERN_LEN 20 | ||
478 | #define MWIFIEX_MAX_OFFSET_LEN 50 | ||
479 | #define STACK_NBYTES 100 | ||
480 | #define TYPE_DNUM 1 | ||
481 | #define TYPE_BYTESEQ 2 | ||
482 | #define MAX_OPERAND 0x40 | ||
483 | #define TYPE_EQ (MAX_OPERAND+1) | ||
484 | #define TYPE_EQ_DNUM (MAX_OPERAND+2) | ||
485 | #define TYPE_EQ_BIT (MAX_OPERAND+3) | ||
486 | #define TYPE_AND (MAX_OPERAND+4) | ||
487 | #define TYPE_OR (MAX_OPERAND+5) | ||
488 | #define MEF_MODE_HOST_SLEEP 1 | ||
489 | #define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 | ||
490 | #define MWIFIEX_CRITERIA_BROADCAST BIT(0) | ||
491 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) | ||
492 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) | ||
493 | |||
476 | struct mwifiex_ie_types_header { | 494 | struct mwifiex_ie_types_header { |
477 | __le16 type; | 495 | __le16 type; |
478 | __le16 len; | 496 | __le16 len; |
@@ -1503,6 +1521,19 @@ struct host_cmd_ds_802_11_ibss_status { | |||
1503 | __le16 use_g_rate_protect; | 1521 | __le16 use_g_rate_protect; |
1504 | } __packed; | 1522 | } __packed; |
1505 | 1523 | ||
1524 | struct mwifiex_fw_mef_entry { | ||
1525 | u8 mode; | ||
1526 | u8 action; | ||
1527 | __le16 exprsize; | ||
1528 | u8 expr[0]; | ||
1529 | } __packed; | ||
1530 | |||
1531 | struct host_cmd_ds_mef_cfg { | ||
1532 | __le32 criteria; | ||
1533 | __le16 num_entries; | ||
1534 | struct mwifiex_fw_mef_entry mef_entry[0]; | ||
1535 | } __packed; | ||
1536 | |||
1506 | #define CONNECTION_TYPE_INFRA 0 | 1537 | #define CONNECTION_TYPE_INFRA 0 |
1507 | #define CONNECTION_TYPE_ADHOC 1 | 1538 | #define CONNECTION_TYPE_ADHOC 1 |
1508 | #define CONNECTION_TYPE_AP 2 | 1539 | #define CONNECTION_TYPE_AP 2 |
@@ -1607,6 +1638,7 @@ struct host_cmd_ds_command { | |||
1607 | struct host_cmd_ds_remain_on_chan roc_cfg; | 1638 | struct host_cmd_ds_remain_on_chan roc_cfg; |
1608 | struct host_cmd_ds_p2p_mode_cfg mode_cfg; | 1639 | struct host_cmd_ds_p2p_mode_cfg mode_cfg; |
1609 | struct host_cmd_ds_802_11_ibss_status ibss_coalescing; | 1640 | struct host_cmd_ds_802_11_ibss_status ibss_coalescing; |
1641 | struct host_cmd_ds_mef_cfg mef_cfg; | ||
1610 | struct host_cmd_ds_mac_reg_access mac_reg; | 1642 | struct host_cmd_ds_mac_reg_access mac_reg; |
1611 | struct host_cmd_ds_bbp_reg_access bbp_reg; | 1643 | struct host_cmd_ds_bbp_reg_access bbp_reg; |
1612 | struct host_cmd_ds_rf_reg_access rf_reg; | 1644 | struct host_cmd_ds_rf_reg_access rf_reg; |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index d85e6eb1f58a..91d522c746ed 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -354,6 +354,29 @@ struct mwifiex_ds_misc_subsc_evt { | |||
354 | struct subsc_evt_cfg bcn_h_rssi_cfg; | 354 | struct subsc_evt_cfg bcn_h_rssi_cfg; |
355 | }; | 355 | }; |
356 | 356 | ||
357 | #define MAX_BYTESEQ 6 /* non-adjustable */ | ||
358 | #define MWIFIEX_MAX_FILTERS 10 | ||
359 | |||
360 | struct mwifiex_mef_filter { | ||
361 | u16 repeat; | ||
362 | u16 offset; | ||
363 | s8 byte_seq[MAX_BYTESEQ + 1]; | ||
364 | u8 filt_type; | ||
365 | u8 filt_action; | ||
366 | }; | ||
367 | |||
368 | struct mwifiex_mef_entry { | ||
369 | u8 mode; | ||
370 | u8 action; | ||
371 | struct mwifiex_mef_filter filter[MWIFIEX_MAX_FILTERS]; | ||
372 | }; | ||
373 | |||
374 | struct mwifiex_ds_mef_cfg { | ||
375 | u32 criteria; | ||
376 | u16 num_entries; | ||
377 | struct mwifiex_mef_entry *mef_entry; | ||
378 | }; | ||
379 | |||
357 | #define MWIFIEX_MAX_VSIE_LEN (256) | 380 | #define MWIFIEX_MAX_VSIE_LEN (256) |
358 | #define MWIFIEX_MAX_VSIE_NUM (8) | 381 | #define MWIFIEX_MAX_VSIE_NUM (8) |
359 | #define MWIFIEX_VSIE_MASK_CLEAR 0x00 | 382 | #define MWIFIEX_VSIE_MASK_CLEAR 0x00 |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 989e05e3d81c..560cf7312d08 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -1098,6 +1098,8 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev); | |||
1098 | 1098 | ||
1099 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); | 1099 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); |
1100 | 1100 | ||
1101 | int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter); | ||
1102 | |||
1101 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | 1103 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, |
1102 | struct cfg80211_beacon_data *data); | 1104 | struct cfg80211_beacon_data *data); |
1103 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); | 1105 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 3d51721af2eb..a2ae690a0a67 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -1059,6 +1059,80 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv, | |||
1059 | return 0; | 1059 | return 0; |
1060 | } | 1060 | } |
1061 | 1061 | ||
1062 | static int | ||
1063 | mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv, | ||
1064 | struct mwifiex_mef_entry *mef_entry, | ||
1065 | u8 **buffer) | ||
1066 | { | ||
1067 | struct mwifiex_mef_filter *filter = mef_entry->filter; | ||
1068 | int i, byte_len; | ||
1069 | u8 *stack_ptr = *buffer; | ||
1070 | |||
1071 | for (i = 0; i < MWIFIEX_MAX_FILTERS; i++) { | ||
1072 | filter = &mef_entry->filter[i]; | ||
1073 | if (!filter->filt_type) | ||
1074 | break; | ||
1075 | *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat); | ||
1076 | stack_ptr += 4; | ||
1077 | *stack_ptr = TYPE_DNUM; | ||
1078 | stack_ptr += 1; | ||
1079 | |||
1080 | byte_len = filter->byte_seq[MAX_BYTESEQ]; | ||
1081 | memcpy(stack_ptr, filter->byte_seq, byte_len); | ||
1082 | stack_ptr += byte_len; | ||
1083 | *stack_ptr = byte_len; | ||
1084 | stack_ptr += 1; | ||
1085 | *stack_ptr = TYPE_BYTESEQ; | ||
1086 | stack_ptr += 1; | ||
1087 | |||
1088 | *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset); | ||
1089 | stack_ptr += 4; | ||
1090 | *stack_ptr = TYPE_DNUM; | ||
1091 | stack_ptr += 1; | ||
1092 | |||
1093 | *stack_ptr = filter->filt_type; | ||
1094 | stack_ptr += 1; | ||
1095 | |||
1096 | if (filter->filt_action) { | ||
1097 | *stack_ptr = filter->filt_action; | ||
1098 | stack_ptr += 1; | ||
1099 | } | ||
1100 | |||
1101 | if (stack_ptr - *buffer > STACK_NBYTES) | ||
1102 | return -1; | ||
1103 | } | ||
1104 | |||
1105 | *buffer = stack_ptr; | ||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | static int | ||
1110 | mwifiex_cmd_mef_cfg(struct mwifiex_private *priv, | ||
1111 | struct host_cmd_ds_command *cmd, | ||
1112 | struct mwifiex_ds_mef_cfg *mef) | ||
1113 | { | ||
1114 | struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; | ||
1115 | u8 *pos = (u8 *)mef_cfg; | ||
1116 | |||
1117 | cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); | ||
1118 | |||
1119 | mef_cfg->criteria = cpu_to_le32(mef->criteria); | ||
1120 | mef_cfg->num_entries = cpu_to_le16(mef->num_entries); | ||
1121 | pos += sizeof(*mef_cfg); | ||
1122 | mef_cfg->mef_entry->mode = mef->mef_entry->mode; | ||
1123 | mef_cfg->mef_entry->action = mef->mef_entry->action; | ||
1124 | pos += sizeof(*(mef_cfg->mef_entry)); | ||
1125 | |||
1126 | if (mwifiex_cmd_append_rpn_expression(priv, mef->mef_entry, &pos)) | ||
1127 | return -1; | ||
1128 | |||
1129 | mef_cfg->mef_entry->exprsize = | ||
1130 | cpu_to_le16(pos - mef_cfg->mef_entry->expr); | ||
1131 | cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); | ||
1132 | |||
1133 | return 0; | ||
1134 | } | ||
1135 | |||
1062 | /* | 1136 | /* |
1063 | * This function prepares the commands before sending them to the firmware. | 1137 | * This function prepares the commands before sending them to the firmware. |
1064 | * | 1138 | * |
@@ -1273,6 +1347,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1273 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: | 1347 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: |
1274 | ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); | 1348 | ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); |
1275 | break; | 1349 | break; |
1350 | case HostCmd_CMD_MEF_CFG: | ||
1351 | ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf); | ||
1352 | break; | ||
1276 | default: | 1353 | default: |
1277 | dev_err(priv->adapter->dev, | 1354 | dev_err(priv->adapter->dev, |
1278 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1355 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 4669f8d9389f..80b9f2238001 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -976,6 +976,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
976 | case HostCmd_CMD_UAP_BSS_STOP: | 976 | case HostCmd_CMD_UAP_BSS_STOP: |
977 | priv->bss_started = 0; | 977 | priv->bss_started = 0; |
978 | break; | 978 | break; |
979 | case HostCmd_CMD_MEF_CFG: | ||
980 | break; | ||
979 | default: | 981 | default: |
980 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 982 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
981 | resp->command); | 983 | resp->command); |