aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-10 09:55:01 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-11-11 12:32:52 -0500
commit79d3eef89190ee0a7ee585e3949873241bc382e3 (patch)
tree69da0c1b02fd45dea359624c5d876412d22dd40d /drivers/net/wireless/iwlwifi/iwl-agn-rx.c
parent868a5f719d730866564d9bd73a8f4a8d89bdc71a (diff)
iwlagn: add P2P NoA to probe responses
Whether to use NoA or not is entire controlled by the uCode right now, and it also adds the attribute to beacons. We do need to add it to probe responses in the driver though. Keep track of the NoA notification from the uCode and add the data to probe responses when such are transmitted. Use RCU to manage the lifetime. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 5af9e6258a1..f0d6d9429be 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -1032,6 +1032,50 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
1032 return 0; 1032 return 0;
1033} 1033}
1034 1034
1035static int iwlagn_rx_noa_notification(struct iwl_priv *priv,
1036 struct iwl_rx_mem_buffer *rxb,
1037 struct iwl_device_cmd *cmd)
1038{
1039 struct iwl_wipan_noa_data *new_data, *old_data;
1040 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1041 struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->u.raw;
1042
1043 /* no condition -- we're in softirq */
1044 old_data = rcu_dereference_protected(priv->noa_data, true);
1045
1046 if (noa_notif->noa_active) {
1047 u32 len = le16_to_cpu(noa_notif->noa_attribute.length);
1048 u32 copylen = len;
1049
1050 /* EID, len, OUI, subtype */
1051 len += 1 + 1 + 3 + 1;
1052 /* P2P id, P2P length */
1053 len += 1 + 2;
1054 copylen += 1 + 2;
1055
1056 new_data = kmalloc(sizeof(*new_data) + len, GFP_ATOMIC);
1057 if (new_data) {
1058 new_data->length = len;
1059 new_data->data[0] = WLAN_EID_VENDOR_SPECIFIC;
1060 new_data->data[1] = len - 2; /* not counting EID, len */
1061 new_data->data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
1062 new_data->data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
1063 new_data->data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
1064 new_data->data[5] = WLAN_OUI_TYPE_WFA_P2P;
1065 memcpy(&new_data->data[6], &noa_notif->noa_attribute,
1066 copylen);
1067 }
1068 } else
1069 new_data = NULL;
1070
1071 rcu_assign_pointer(priv->noa_data, new_data);
1072
1073 if (old_data)
1074 kfree_rcu(old_data, rcu_head);
1075
1076 return 0;
1077}
1078
1035/** 1079/**
1036 * iwl_setup_rx_handlers - Initialize Rx handler callbacks 1080 * iwl_setup_rx_handlers - Initialize Rx handler callbacks
1037 * 1081 *
@@ -1055,6 +1099,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
1055 handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif; 1099 handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif;
1056 handlers[REPLY_ADD_STA] = iwl_add_sta_callback; 1100 handlers[REPLY_ADD_STA] = iwl_add_sta_callback;
1057 1101
1102 handlers[REPLY_WIPAN_NOA_NOTIFICATION] = iwlagn_rx_noa_notification;
1103
1058 /* 1104 /*
1059 * The same handler is used for both the REPLY to a discrete 1105 * The same handler is used for both the REPLY to a discrete
1060 * statistics request from the host as well as for the periodic 1106 * statistics request from the host as well as for the periodic