|
@@ -1032,6 +1032,50 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
|
|
return 0;
|
|
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
|
|
* 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[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif;
|
|
handlers[REPLY_ADD_STA] = iwl_add_sta_callback;
|
|
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
|
|
* The same handler is used for both the REPLY to a discrete
|
|
* statistics request from the host as well as for the periodic
|
|
* statistics request from the host as well as for the periodic
|