From 79d3eef89190ee0a7ee585e3949873241bc382e3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 10 Nov 2011 06:55:01 -0800 Subject: 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 Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rx.c') 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, return 0; } +static int iwlagn_rx_noa_notification(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb, + struct iwl_device_cmd *cmd) +{ + struct iwl_wipan_noa_data *new_data, *old_data; + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->u.raw; + + /* no condition -- we're in softirq */ + old_data = rcu_dereference_protected(priv->noa_data, true); + + if (noa_notif->noa_active) { + u32 len = le16_to_cpu(noa_notif->noa_attribute.length); + u32 copylen = len; + + /* EID, len, OUI, subtype */ + len += 1 + 1 + 3 + 1; + /* P2P id, P2P length */ + len += 1 + 2; + copylen += 1 + 2; + + new_data = kmalloc(sizeof(*new_data) + len, GFP_ATOMIC); + if (new_data) { + new_data->length = len; + new_data->data[0] = WLAN_EID_VENDOR_SPECIFIC; + new_data->data[1] = len - 2; /* not counting EID, len */ + new_data->data[2] = (WLAN_OUI_WFA >> 16) & 0xff; + new_data->data[3] = (WLAN_OUI_WFA >> 8) & 0xff; + new_data->data[4] = (WLAN_OUI_WFA >> 0) & 0xff; + new_data->data[5] = WLAN_OUI_TYPE_WFA_P2P; + memcpy(&new_data->data[6], &noa_notif->noa_attribute, + copylen); + } + } else + new_data = NULL; + + rcu_assign_pointer(priv->noa_data, new_data); + + if (old_data) + kfree_rcu(old_data, rcu_head); + + return 0; +} + /** * iwl_setup_rx_handlers - Initialize Rx handler callbacks * @@ -1055,6 +1099,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif; handlers[REPLY_ADD_STA] = iwl_add_sta_callback; + handlers[REPLY_WIPAN_NOA_NOTIFICATION] = iwlagn_rx_noa_notification; + /* * The same handler is used for both the REPLY to a discrete * statistics request from the host as well as for the periodic -- cgit v1.2.2