target_if_spectral_netlink.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*
  2. * Copyright (c) 2011,2017-2018 The Linux Foundation. All rights reserved.
  3. *
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for
  6. * any purpose with or without fee is hereby granted, provided that the
  7. * above copyright notice and this permission notice appear in all
  8. * copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  11. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  12. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  13. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  14. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  15. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  16. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  17. * PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. #include <osdep.h>
  20. #include <wlan_tgt_def_config.h>
  21. #include <hif.h>
  22. #include <hif_hw_version.h>
  23. #include <wmi_unified_api.h>
  24. #include <target_if_spectral.h>
  25. #include <wlan_lmac_if_def.h>
  26. #include <wlan_osif_priv.h>
  27. #include <reg_services_public_struct.h>
  28. #ifdef SPECTRAL_USE_NETLINK_SOCKETS
  29. struct sock *target_if_spectral_nl_sock;
  30. static atomic_t spectral_nl_users = ATOMIC_INIT(0);
  31. #if (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
  32. void
  33. target_if_spectral_nl_data_ready(struct sock *sk, int len)
  34. {
  35. qdf_print("%s %d\n", __func__, __LINE__);
  36. }
  37. #else
  38. void
  39. target_if_spectral_nl_data_ready(struct sk_buff *skb)
  40. {
  41. qdf_print("%s %d\n", __func__, __LINE__);
  42. }
  43. #endif /* VERSION */
  44. /**
  45. * target_if_spectral_init_nl_cfg() - Initialize netlink kernel
  46. * configuration parameters
  47. * @spectral : Pointer to netlink_kernel_cfg
  48. *
  49. * Initialize netlink kernel configuration parameters required
  50. * for spectral module
  51. *
  52. * Return: None
  53. */
  54. #if KERNEL_VERSION(3, 6, 0) <= LINUX_VERSION_CODE
  55. static void
  56. target_if_spectral_init_nl_cfg(struct netlink_kernel_cfg *cfg)
  57. {
  58. cfg->groups = 1;
  59. cfg->input = target_if_spectral_nl_data_ready;
  60. }
  61. #else
  62. static void
  63. target_if_spectral_init_nl_cfg(struct netlink_kernel_cfg *cfg)
  64. {
  65. }
  66. #endif
  67. /**
  68. * target_if_spectral_create_nl_sock() - Create Netlink socket
  69. * @spectral : Pointer to netlink_kernel_cfg
  70. *
  71. * Create Netlink socket required for spectral module
  72. *
  73. * Return: None
  74. */
  75. #if KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE
  76. static void
  77. target_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
  78. {
  79. target_if_spectral_nl_sock =
  80. (struct sock *)netlink_kernel_create(&init_net,
  81. NETLINK_ATHEROS, cfg);
  82. }
  83. #elif KERNEL_VERSION(3, 6, 0) <= LINUX_VERSION_CODE
  84. static void
  85. target_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
  86. {
  87. target_if_spectral_nl_sock =
  88. (struct sock *)netlink_kernel_create(&init_net,
  89. NETLINK_ATHEROS,
  90. THIS_MODULE, cfg);
  91. }
  92. #elif (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
  93. static void
  94. target_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
  95. {
  96. target_if_spectral_nl_sock =
  97. (struct sock *)netlink_kernel_create(
  98. NETLINK_ATHEROS, 1,
  99. &target_if_spectral_nl_data_ready,
  100. THIS_MODULE);
  101. }
  102. #else
  103. #if (KERNEL_VERSION(3, 10, 0) <= LINUX_VERSION_CODE)
  104. static void
  105. target_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
  106. {
  107. memset(cfg, 0, sizeof(*cfg));
  108. cfg->groups = 1;
  109. cfg->input = &target_if_spectral_nl_data_ready;
  110. target_if_spectral_nl_sock =
  111. (struct sock *)netlink_kernel_create(&init_net,
  112. NETLINK_ATHEROS, cfg);
  113. }
  114. #else
  115. static void
  116. target_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
  117. {
  118. target_if_spectral_nl_sock =
  119. (struct sock *)netlink_kernel_create(
  120. &init_net,
  121. NETLINK_ATHEROS, 1,
  122. &target_if_spectral_nl_data_ready,
  123. NULL, THIS_MODULE);
  124. }
  125. #endif
  126. #endif
  127. int
  128. target_if_spectral_init_netlink(struct target_if_spectral *spectral)
  129. {
  130. struct netlink_kernel_cfg cfg;
  131. memset(&cfg, 0, sizeof(cfg));
  132. target_if_spectral_init_nl_cfg(&cfg);
  133. if (!spectral) {
  134. qdf_print("%s: sc_spectral is NULL\n", __func__);
  135. return -EIO;
  136. }
  137. spectral->spectral_sent_msg = 0;
  138. if (!target_if_spectral_nl_sock) {
  139. target_if_spectral_create_nl_sock(&cfg);
  140. if (!target_if_spectral_nl_sock) {
  141. qdf_print("%s NETLINK_KERNEL_CREATE FAILED\n",
  142. __func__);
  143. return -ENODEV;
  144. }
  145. }
  146. atomic_inc(&spectral_nl_users);
  147. spectral->spectral_sock = target_if_spectral_nl_sock;
  148. if ((!spectral) || (!spectral->spectral_sock)) {
  149. qdf_print("%s NULL pointers (spectral=%d) (sock=%d)\n",
  150. __func__, (!spectral), (!spectral->spectral_sock));
  151. return -ENODEV;
  152. }
  153. if (!spectral->spectral_skb)
  154. qdf_print(KERN_ERR "%s %d NULL SKB\n", __func__, __LINE__);
  155. return 0;
  156. }
  157. int
  158. target_if_spectral_destroy_netlink(struct target_if_spectral *spectral)
  159. {
  160. spectral->spectral_sock = NULL;
  161. if (atomic_dec_and_test(&spectral_nl_users)) {
  162. sock_release(target_if_spectral_nl_sock->sk_socket);
  163. target_if_spectral_nl_sock = NULL;
  164. }
  165. return 0;
  166. }
  167. #endif /* SPECTRAL_USE_NETLINK_SOCKETS */
  168. static void
  169. target_if_spectral_process_noise_pwr_report(
  170. struct target_if_spectral *spectral,
  171. const struct spectral_samp_msg *spec_samp_msg)
  172. {
  173. int i, done;
  174. qdf_spin_lock(&spectral->noise_pwr_reports_lock);
  175. if (!spectral->noise_pwr_reports_reqd) {
  176. qdf_spin_unlock(&spectral->noise_pwr_reports_lock);
  177. return;
  178. }
  179. if (spectral->noise_pwr_reports_recv <
  180. spectral->noise_pwr_reports_reqd) {
  181. spectral->noise_pwr_reports_recv++;
  182. for (i = 0; i < HOST_MAX_ANTENNA; i++) {
  183. uint32_t index;
  184. if (spectral->noise_pwr_chain_ctl[i]) {
  185. index =
  186. spectral->noise_pwr_chain_ctl[i]->
  187. rptcount++;
  188. spectral->noise_pwr_chain_ctl[i]->pwr[index] =
  189. spec_samp_msg->samp_data.
  190. spectral_chain_ctl_rssi[i];
  191. }
  192. if (spectral->noise_pwr_chain_ext[i]) {
  193. index =
  194. spectral->noise_pwr_chain_ext[i]->
  195. rptcount++;
  196. spectral->noise_pwr_chain_ext[i]->pwr[index] =
  197. spec_samp_msg->samp_data.
  198. spectral_chain_ext_rssi[i];
  199. }
  200. }
  201. }
  202. done = (spectral->noise_pwr_reports_recv >=
  203. spectral->noise_pwr_reports_reqd);
  204. qdf_spin_unlock(&spectral->noise_pwr_reports_lock);
  205. if (done) {
  206. qdf_spin_lock(&spectral->spectral_lock);
  207. target_if_stop_spectral_scan(spectral->pdev_obj);
  208. spectral->sc_spectral_scan = 0;
  209. qdf_spin_unlock(&spectral->spectral_lock);
  210. }
  211. }
  212. /*
  213. * Function : spectral_create_samp_msg
  214. * Description : create SAMP message and send it host
  215. * Input :
  216. * Output :
  217. *
  218. */
  219. #ifdef SPECTRAL_CLASSIFIER_IN_KERNEL
  220. static void
  221. target_if_spectral_init_interf_list(
  222. struct spectral_samp_data *data,
  223. struct target_if_samp_msg_params *params)
  224. {
  225. if (params->interf_list.count)
  226. OS_MEMCPY(&data->interf_list,
  227. &params->interf_list, sizeof(struct INTERF_SRC_RSP));
  228. else
  229. data->interf_list.count = 0;
  230. }
  231. #else
  232. static void
  233. target_if_spectral_init_interf_list(
  234. struct spectral_samp_data *data,
  235. struct target_if_samp_msg_params *params)
  236. {
  237. data->interf_list.count = 0;
  238. }
  239. #endif
  240. void
  241. target_if_spectral_create_samp_msg(struct target_if_spectral *spectral,
  242. struct target_if_samp_msg_params *params)
  243. {
  244. /*
  245. * XXX : Non-Rentrant. Will be an issue with dual concurrent
  246. * operation on multi-processor system
  247. */
  248. int temp_samp_msg_len = 0;
  249. static struct spectral_samp_msg spec_samp_msg;
  250. struct spectral_samp_msg *msg = NULL;
  251. struct spectral_samp_data *data = NULL;
  252. uint8_t *bin_pwr_data = NULL;
  253. struct spectral_classifier_params *cp = NULL;
  254. struct spectral_classifier_params *pcp = NULL;
  255. struct target_if_spectral_ops *p_sops = NULL;
  256. struct target_if_spectral_skb_event *sp_skb_event = NULL;
  257. #ifdef SPECTRAL_USE_NETLINK_SOCKETS
  258. static int samp_msg_index;
  259. #endif
  260. p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
  261. temp_samp_msg_len = sizeof(struct spectral_samp_msg) -
  262. (MAX_NUM_BINS * sizeof(uint8_t));
  263. temp_samp_msg_len += (params->pwr_count * sizeof(uint8_t));
  264. if (spectral->ch_width == CH_WIDTH_160MHZ)
  265. temp_samp_msg_len +=
  266. (params->pwr_count_sec80 * sizeof(uint8_t));
  267. bin_pwr_data = params->bin_pwr_data;
  268. memset(&spec_samp_msg, 0, sizeof(struct spectral_samp_msg));
  269. data = &spec_samp_msg.samp_data;
  270. spec_samp_msg.signature = SPECTRAL_SIGNATURE;
  271. spec_samp_msg.freq = params->freq;
  272. spec_samp_msg.freq_loading = params->freq_loading;
  273. spec_samp_msg.samp_data.spectral_data_len = params->datalen;
  274. spec_samp_msg.samp_data.spectral_rssi = params->rssi;
  275. spec_samp_msg.samp_data.ch_width = spectral->ch_width;
  276. spec_samp_msg.samp_data.spectral_combined_rssi =
  277. (uint8_t)params->rssi;
  278. spec_samp_msg.samp_data.spectral_upper_rssi = params->upper_rssi;
  279. spec_samp_msg.samp_data.spectral_lower_rssi = params->lower_rssi;
  280. OS_MEMCPY(spec_samp_msg.samp_data.spectral_chain_ctl_rssi,
  281. params->chain_ctl_rssi, sizeof(params->chain_ctl_rssi));
  282. OS_MEMCPY(spec_samp_msg.samp_data.spectral_chain_ext_rssi,
  283. params->chain_ext_rssi, sizeof(params->chain_ext_rssi));
  284. spec_samp_msg.samp_data.spectral_bwinfo = params->bwinfo;
  285. spec_samp_msg.samp_data.spectral_tstamp = params->tstamp;
  286. spec_samp_msg.samp_data.spectral_max_index = params->max_index;
  287. /* Classifier in user space needs access to these */
  288. spec_samp_msg.samp_data.spectral_lower_max_index =
  289. params->max_lower_index;
  290. spec_samp_msg.samp_data.spectral_upper_max_index =
  291. params->max_upper_index;
  292. spec_samp_msg.samp_data.spectral_nb_lower = params->nb_lower;
  293. spec_samp_msg.samp_data.spectral_nb_upper = params->nb_upper;
  294. spec_samp_msg.samp_data.spectral_last_tstamp = params->last_tstamp;
  295. spec_samp_msg.samp_data.spectral_max_mag = params->max_mag;
  296. spec_samp_msg.samp_data.bin_pwr_count = params->pwr_count;
  297. spec_samp_msg.samp_data.lb_edge_extrabins = spectral->lb_edge_extrabins;
  298. spec_samp_msg.samp_data.rb_edge_extrabins = spectral->rb_edge_extrabins;
  299. spec_samp_msg.samp_data.spectral_combined_rssi = params->rssi;
  300. spec_samp_msg.samp_data.spectral_max_scale = params->max_exp;
  301. #ifdef SPECTRAL_USE_NETLINK_SOCKETS
  302. /*
  303. * This is a dirty hack to get the Windows build pass.
  304. * Currently Windows and Linux builds source spectral_data.h
  305. * form two different place. The windows version do not
  306. * have noise_floor member in it.
  307. *
  308. * As a temp workaround this variable is set under the
  309. * SPECTRAL_USE_NETLINK_SOCKETS as this is called only
  310. * under the linux build and this saves the day
  311. *
  312. * The plan to sync of header files in under the way
  313. *
  314. */
  315. spec_samp_msg.samp_data.noise_floor = params->noise_floor;
  316. #endif /* SPECTRAL_USE_NETLINK_SOCKETS */
  317. /* Classifier in user space needs access to these */
  318. cp = &spec_samp_msg.samp_data.classifier_params;
  319. pcp = &params->classifier_params;
  320. OS_MEMCPY(cp, pcp, sizeof(struct spectral_classifier_params));
  321. SPECTRAL_MESSAGE_COPY_CHAR_ARRAY(&data->bin_pwr[0],
  322. bin_pwr_data, params->pwr_count);
  323. #ifdef SPECTRAL_USE_NETLINK_SOCKETS
  324. spec_samp_msg.vhtop_ch_freq_seg1 = params->vhtop_ch_freq_seg1;
  325. spec_samp_msg.vhtop_ch_freq_seg2 = params->vhtop_ch_freq_seg2;
  326. if (spectral->ch_width == CH_WIDTH_160MHZ) {
  327. spec_samp_msg.samp_data.spectral_rssi_sec80 =
  328. params->rssi_sec80;
  329. spec_samp_msg.samp_data.noise_floor_sec80 =
  330. params->noise_floor_sec80;
  331. spec_samp_msg.samp_data.spectral_data_len_sec80 =
  332. params->datalen_sec80;
  333. spec_samp_msg.samp_data.spectral_max_index_sec80 =
  334. params->max_index_sec80;
  335. spec_samp_msg.samp_data.spectral_max_mag_sec80 =
  336. params->max_mag_sec80;
  337. spec_samp_msg.samp_data.bin_pwr_count_sec80 =
  338. params->pwr_count_sec80;
  339. SPECTRAL_MESSAGE_COPY_CHAR_ARRAY(&data->bin_pwr_sec80[0],
  340. (params->bin_pwr_data_sec80),
  341. params->pwr_count_sec80);
  342. /*
  343. * Note: REVERSE_ORDER is not a known use case for
  344. * secondary 80 data at this point.
  345. */
  346. }
  347. #endif /* SPECTRAL_USE_NETLINK_SOCKETS */
  348. target_if_spectral_init_interf_list(data, params);
  349. #ifdef SPECTRAL_USE_NETLINK_SOCKETS
  350. target_if_spectral_prep_skb(spectral);
  351. if (spectral->spectral_skb) {
  352. p_sops->get_mac_address(spectral, spec_samp_msg.macaddr);
  353. spectral->spectral_nlh =
  354. (struct nlmsghdr *)spectral->spectral_skb->data;
  355. memcpy(NLMSG_DATA(spectral->spectral_nlh),
  356. &spec_samp_msg, sizeof(struct spectral_samp_msg));
  357. msg = (struct spectral_samp_msg *)NLMSG_DATA(
  358. spectral->spectral_nlh);
  359. /*
  360. * Broadcast spectral data only
  361. * if it is a edma supported device
  362. */
  363. if (!spectral->sc_spectral_non_edma)
  364. target_if_spectral_bcast_msg(spectral);
  365. samp_msg_index++;
  366. }
  367. /*
  368. * Check if the device is non-edma and follow the required broadcast
  369. * path if true
  370. */
  371. if (spectral->sc_spectral_non_edma) {
  372. /*
  373. * Allocating memory for the queue entity to
  374. * hold the spectral socket buffer
  375. */
  376. sp_skb_event = (struct target_if_spectral_skb_event
  377. *)qdf_mem_malloc(
  378. sizeof(
  379. struct target_if_spectral_skb_event));
  380. if (sp_skb_event) {
  381. OS_MEMZERO(sp_skb_event,
  382. sizeof(struct target_if_spectral_skb_event));
  383. sp_skb_event->sp_skb = spectral->spectral_skb;
  384. sp_skb_event->sp_nlh = spectral->spectral_nlh;
  385. spectral->spectral_skb = NULL;
  386. spectral->spectral_nlh = NULL;
  387. /*
  388. * Queue spectral socket buffers to be broadcasted
  389. * outside irq lock
  390. */
  391. qdf_spin_lock(&spectral->spectral_skbqlock);
  392. STAILQ_INSERT_TAIL(&spectral->spectral_skbq,
  393. sp_skb_event, spectral_skb_list);
  394. qdf_spin_unlock(&spectral->spectral_skbqlock);
  395. }
  396. }
  397. #else
  398. /*
  399. * call the indicate function to pass the data to the net layer
  400. * Windows will pass to a spectral WIN32 service
  401. */
  402. msg = (struct spectral_samp_msg *)qdf_mem_malloc(
  403. sizeof(struct spectral_samp_msg));
  404. if (msg) {
  405. OS_MEMCPY(msg, &spec_samp_msg,
  406. sizeof(struct spectral_samp_msg));
  407. ath_spectral_indicate(params->sc, (void *)msg,
  408. sizeof(struct spectral_samp_msg));
  409. OS_FREE(msg);
  410. msg = NULL;
  411. } else {
  412. qdf_print("No buffer\n");
  413. }
  414. #endif /* SPECTRAL_USE_NETLINK_SOCKETS */
  415. if (spectral->sc_spectral_noise_pwr_cal)
  416. target_if_spectral_process_noise_pwr_report(
  417. spectral, &spec_samp_msg);
  418. }
  419. #ifdef SPECTRAL_USE_NETLINK_SOCKETS
  420. void
  421. target_if_spectral_prep_skb(struct target_if_spectral *spectral)
  422. {
  423. spectral->spectral_skb = dev_alloc_skb(MAX_SPECTRAL_PAYLOAD);
  424. if (spectral->spectral_skb) {
  425. skb_put(spectral->spectral_skb, MAX_SPECTRAL_PAYLOAD);
  426. spectral->spectral_nlh =
  427. (struct nlmsghdr *)spectral->spectral_skb->data;
  428. OS_MEMZERO(spectral->spectral_nlh,
  429. sizeof(*spectral->spectral_nlh));
  430. /*
  431. * Possible bug that size of struct spectral_samp_msg and
  432. * SPECTRAL_MSG differ by 3 bytes so we miss 3 bytes
  433. */
  434. spectral->spectral_nlh->nlmsg_len =
  435. NLMSG_SPACE(sizeof(struct spectral_samp_msg));
  436. spectral->spectral_nlh->nlmsg_pid = 0;
  437. spectral->spectral_nlh->nlmsg_flags = 0;
  438. } else {
  439. spectral->spectral_skb = NULL;
  440. spectral->spectral_nlh = NULL;
  441. }
  442. }
  443. #if (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
  444. static inline void
  445. target_if_init_spectral_skb_dst_pid(
  446. struct target_if_spectral *spectral)
  447. {
  448. NETLINK_CB(spectral->spectral_skb).dst_pid =
  449. spectral->spectral_pid;
  450. }
  451. #else
  452. static inline void
  453. target_if_init_spectral_skb_dst_pid(
  454. struct target_if_spectral *spectral)
  455. {
  456. }
  457. #endif /* VERSION - field depracated by newer kernel */
  458. #if KERNEL_VERSION(3, 7, 0) > LINUX_VERSION_CODE
  459. static inline void
  460. target_if_init_spectral_skb_pid_portid(
  461. struct target_if_spectral *spectral)
  462. {
  463. NETLINK_CB(spectral->spectral_skb).pid = 0; /* from kernel */
  464. }
  465. #else
  466. static inline void
  467. target_if_init_spectral_skb_pid_portid(
  468. struct target_if_spectral *spectral)
  469. {
  470. NETLINK_CB(spectral->spectral_skb).portid = 0; /* from kernel */
  471. }
  472. #endif
  473. void
  474. target_if_spectral_unicast_msg(struct target_if_spectral *spectral)
  475. {
  476. if (!spectral) {
  477. qdf_print("%s Spectral is NULL\n", __func__);
  478. return;
  479. }
  480. if (!spectral->spectral_sock) {
  481. qdf_print("%s Spectral Socket is invalid\n", __func__);
  482. dev_kfree_skb(spectral->spectral_skb);
  483. spectral->spectral_skb = NULL;
  484. return;
  485. }
  486. if (spectral->spectral_skb) {
  487. target_if_init_spectral_skb_dst_pid(spectral);
  488. target_if_init_spectral_skb_pid_portid(spectral);
  489. /* to mcast group 1<<0 */
  490. NETLINK_CB(spectral->spectral_skb).dst_group = 0;
  491. netlink_unicast(spectral->spectral_sock,
  492. spectral->spectral_skb,
  493. spectral->spectral_pid, MSG_DONTWAIT);
  494. }
  495. }
  496. void
  497. target_if_spectral_bcast_msg(struct target_if_spectral *spectral)
  498. {
  499. #if (KERNEL_VERSION(2, 6, 31) >= LINUX_VERSION_CODE)
  500. fd_set write_set;
  501. #endif
  502. struct spectral_samp_msg *msg = NULL;
  503. struct nlmsghdr *nlh = NULL;
  504. int status;
  505. #if (KERNEL_VERSION(2, 6, 31) >= LINUX_VERSION_CODE)
  506. FD_ZERO(&write_set);
  507. #endif
  508. if (!spectral)
  509. return;
  510. if (!spectral->spectral_sock) {
  511. dev_kfree_skb(spectral->spectral_skb);
  512. spectral->spectral_skb = NULL;
  513. return;
  514. }
  515. if (!spectral->spectral_skb)
  516. return;
  517. nlh = (struct nlmsghdr *)spectral->spectral_skb->data;
  518. msg = (struct spectral_samp_msg *)NLMSG_DATA(spectral->spectral_nlh);
  519. status = target_if_send_phydata(spectral->pdev_obj,
  520. spectral->spectral_sock,
  521. spectral->spectral_skb);
  522. if (status == 0)
  523. spectral->spectral_sent_msg++;
  524. /* netlink will have freed the skb */
  525. if (spectral->spectral_skb)
  526. spectral->spectral_skb = NULL;
  527. }
  528. void
  529. target_if_spectral_skb_dequeue(void *data)
  530. {
  531. struct target_if_spectral *spectral = (struct target_if_spectral *)data;
  532. struct target_if_spectral_skb_event *sp_skb_event = NULL;
  533. qdf_spin_lock(&spectral->spectral_skbqlock);
  534. /* Deque all the spectral socket buffers queued */
  535. while (!STAILQ_EMPTY(&spectral->spectral_skbq)) {
  536. sp_skb_event = STAILQ_FIRST(&spectral->spectral_skbq);
  537. if (sp_skb_event) {
  538. spectral->spectral_skb = sp_skb_event->sp_skb;
  539. spectral->spectral_nlh = sp_skb_event->sp_nlh;
  540. STAILQ_REMOVE_HEAD(&spectral->spectral_skbq,
  541. spectral_skb_list);
  542. qdf_spin_unlock(&spectral->spectral_skbqlock);
  543. OS_FREE(sp_skb_event);
  544. /* Broadcast spectral data after dequeing */
  545. target_if_spectral_bcast_msg(spectral);
  546. qdf_spin_lock(&spectral->spectral_skbqlock);
  547. }
  548. }
  549. qdf_spin_unlock(&spectral->spectral_skbqlock);
  550. }
  551. #endif /* SPECTRAL_USE_NETLINK_SOCKETS */