p2p.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // SPDX-License-Identifier: BSD-3-Clause-Clear
  2. /*
  3. * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #include "core.h"
  6. #include "wmi.h"
  7. #include "mac.h"
  8. #include "p2p.h"
  9. static void ath11k_p2p_noa_ie_fill(u8 *data, size_t len,
  10. const struct ath11k_wmi_p2p_noa_info *noa)
  11. {
  12. struct ieee80211_p2p_noa_attr *noa_attr;
  13. u8 noa_descriptors, ctwindow;
  14. bool oppps;
  15. __le16 *noa_attr_len;
  16. u16 attr_len;
  17. int i;
  18. ctwindow = u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_CTWIN_TU);
  19. oppps = u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS);
  20. noa_descriptors = u32_get_bits(noa->noa_attr,
  21. WMI_P2P_NOA_INFO_DESC_NUM);
  22. /* P2P IE */
  23. data[0] = WLAN_EID_VENDOR_SPECIFIC;
  24. data[1] = len - 2;
  25. data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
  26. data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
  27. data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
  28. data[5] = WLAN_OUI_TYPE_WFA_P2P;
  29. /* NOA ATTR */
  30. data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
  31. noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */
  32. noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9];
  33. noa_attr->index = u32_get_bits(noa->noa_attr,
  34. WMI_P2P_NOA_INFO_INDEX);
  35. noa_attr->oppps_ctwindow = ctwindow;
  36. if (oppps)
  37. noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT;
  38. for (i = 0; i < noa_descriptors; i++) {
  39. noa_attr->desc[i].count = noa->descriptors[i].type_count;
  40. noa_attr->desc[i].duration =
  41. cpu_to_le32(noa->descriptors[i].duration);
  42. noa_attr->desc[i].interval =
  43. cpu_to_le32(noa->descriptors[i].interval);
  44. noa_attr->desc[i].start_time =
  45. cpu_to_le32(noa->descriptors[i].start_time);
  46. }
  47. attr_len = 2; /* index + oppps_ctwindow */
  48. attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
  49. *noa_attr_len = __cpu_to_le16(attr_len);
  50. }
  51. static size_t
  52. ath11k_p2p_noa_ie_len_compute(const struct ath11k_wmi_p2p_noa_info *noa)
  53. {
  54. size_t len = 0;
  55. u8 noa_descriptors = u32_get_bits(noa->noa_attr,
  56. WMI_P2P_NOA_INFO_DESC_NUM);
  57. if (!(noa_descriptors) &&
  58. !(u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS)))
  59. return 0;
  60. len += 1 + 1 + 4; /* EID + len + OUI */
  61. len += 1 + 2; /* noa attr + attr len */
  62. len += 1 + 1; /* index + oppps_ctwindow */
  63. len += noa_descriptors *
  64. sizeof(struct ieee80211_p2p_noa_desc);
  65. return len;
  66. }
  67. static void ath11k_p2p_noa_ie_assign(struct ath11k_vif *arvif, void *ie,
  68. size_t len)
  69. {
  70. struct ath11k *ar = arvif->ar;
  71. lockdep_assert_held(&ar->data_lock);
  72. kfree(arvif->u.ap.noa_data);
  73. arvif->u.ap.noa_data = ie;
  74. arvif->u.ap.noa_len = len;
  75. }
  76. static void __ath11k_p2p_noa_update(struct ath11k_vif *arvif,
  77. const struct ath11k_wmi_p2p_noa_info *noa)
  78. {
  79. struct ath11k *ar = arvif->ar;
  80. void *ie;
  81. size_t len;
  82. lockdep_assert_held(&ar->data_lock);
  83. ath11k_p2p_noa_ie_assign(arvif, NULL, 0);
  84. len = ath11k_p2p_noa_ie_len_compute(noa);
  85. if (!len)
  86. return;
  87. ie = kmalloc(len, GFP_ATOMIC);
  88. if (!ie)
  89. return;
  90. ath11k_p2p_noa_ie_fill(ie, len, noa);
  91. ath11k_p2p_noa_ie_assign(arvif, ie, len); }
  92. void ath11k_p2p_noa_update(struct ath11k_vif *arvif,
  93. const struct ath11k_wmi_p2p_noa_info *noa)
  94. {
  95. struct ath11k *ar = arvif->ar;
  96. spin_lock_bh(&ar->data_lock);
  97. __ath11k_p2p_noa_update(arvif, noa);
  98. spin_unlock_bh(&ar->data_lock);
  99. }
  100. static void ath11k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
  101. struct ieee80211_vif *vif)
  102. {
  103. struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
  104. struct ath11k_p2p_noa_arg *arg = data;
  105. if (arvif->vdev_id != arg->vdev_id)
  106. return;
  107. ath11k_p2p_noa_update(arvif, arg->noa);
  108. }
  109. void ath11k_p2p_noa_update_by_vdev_id(struct ath11k *ar, u32 vdev_id,
  110. const struct ath11k_wmi_p2p_noa_info *noa)
  111. {
  112. struct ath11k_p2p_noa_arg arg = {
  113. .vdev_id = vdev_id,
  114. .noa = noa,
  115. };
  116. ieee80211_iterate_active_interfaces_atomic(ar->hw,
  117. IEEE80211_IFACE_ITER_NORMAL,
  118. ath11k_p2p_noa_update_vdev_iter,
  119. &arg);
  120. }