1 /*
2  * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <qdf_types.h>
18 #include "osif_pre_cac.h"
19 #include "wlan_pre_cac_public_struct.h"
20 #include "wlan_pre_cac_ucfg_api.h"
21 #include "wlan_cfg80211.h"
22 #include "wlan_objmgr_vdev_obj.h"
23 #include "wlan_osif_priv.h"
24 #include "osif_vdev_sync.h"
25 
26 static struct osif_pre_cac_legacy_ops *osif_pre_cac_legacy_ops;
27 
28 static void
osif_pre_cac_complete_legacy_cb(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,QDF_STATUS status)29 osif_pre_cac_complete_legacy_cb(struct wlan_objmgr_psoc *psoc,
30 				uint8_t vdev_id,
31 				QDF_STATUS status)
32 {
33 	osif_pre_cac_complete_status_legacy_cb cb = NULL;
34 
35 	if (osif_pre_cac_legacy_ops)
36 		cb = osif_pre_cac_legacy_ops->pre_cac_complete_legacy_cb;
37 
38 	if (cb)
39 		cb(psoc, vdev_id, status);
40 }
41 
osif_pre_cac_complete_cb(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,QDF_STATUS status)42 static void osif_pre_cac_complete_cb(struct wlan_objmgr_psoc *psoc,
43 				     uint8_t vdev_id,
44 				     QDF_STATUS status)
45 {
46 	struct vdev_osif_priv *osif_priv;
47 	struct osif_vdev_sync *vdev_sync;
48 	int errno;
49 	struct wlan_objmgr_vdev *vdev;
50 
51 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
52 				psoc, vdev_id,
53 				WLAN_PRE_CAC_ID);
54 	if (!vdev) {
55 		osif_err("Invalid vdev for %d", vdev_id);
56 		return;
57 	}
58 	osif_priv = wlan_vdev_get_ospriv(vdev);
59 	errno = osif_vdev_sync_trans_start_wait(osif_priv->wdev->netdev,
60 						&vdev_sync);
61 	wlan_objmgr_vdev_release_ref(vdev, WLAN_PRE_CAC_ID);
62 	if (errno)
63 		return;
64 
65 	osif_pre_cac_complete_legacy_cb(psoc, vdev_id, status);
66 
67 	osif_vdev_sync_trans_stop(vdev_sync);
68 }
69 
70 static void
osif_pre_cac_conditional_csa_ind_legacy_cb(struct wlan_objmgr_vdev * vdev,bool completed)71 osif_pre_cac_conditional_csa_ind_legacy_cb(struct wlan_objmgr_vdev *vdev,
72 					   bool completed)
73 {
74 	osif_conditional_csa_ind_legacy_cb cb = NULL;
75 
76 	if (osif_pre_cac_legacy_ops)
77 		cb = osif_pre_cac_legacy_ops->conditional_csa_ind_legacy_cb;
78 
79 	if (cb)
80 		cb(vdev, completed);
81 }
82 
83 static void
osif_pre_cac_send_conditional_freq_switch_status(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,bool status)84 osif_pre_cac_send_conditional_freq_switch_status(struct wlan_objmgr_psoc *psoc,
85 						 uint8_t vdev_id,
86 						 bool status)
87 {
88 	struct vdev_osif_priv *osif_priv;
89 	struct wlan_objmgr_vdev *vdev;
90 	struct wireless_dev *wdev;
91 	struct sk_buff *event;
92 
93 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
94 						    WLAN_PRE_CAC_ID);
95 	if (!vdev) {
96 		osif_err("vdev is null");
97 		return;
98 	}
99 
100 	osif_priv = wlan_vdev_get_ospriv(vdev);
101 	if (!osif_priv) {
102 		osif_err("osif_priv is null");
103 		goto fail;
104 	}
105 
106 	wdev = osif_priv->wdev;
107 	if (!wdev) {
108 		osif_err("wireless dev is null");
109 		goto fail;
110 	}
111 
112 	event = wlan_cfg80211_vendor_event_alloc(wdev->wiphy,
113 		  wdev, sizeof(uint32_t) + NLMSG_HDRLEN,
114 		  QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX,
115 		  GFP_KERNEL);
116 	if (!event) {
117 		osif_err("wlan_cfg80211_vendor_event_alloc failed");
118 		goto fail;
119 	}
120 
121 	if (nla_put_u32(event,
122 			QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS,
123 			status)) {
124 		osif_err("nla put failed");
125 		wlan_cfg80211_vendor_free_skb(event);
126 		goto fail;
127 	}
128 
129 	wlan_cfg80211_vendor_event(event, GFP_KERNEL);
130 	osif_pre_cac_conditional_csa_ind_legacy_cb(vdev, status);
131 
132 fail:
133 	wlan_objmgr_vdev_release_ref(vdev, WLAN_PRE_CAC_ID);
134 }
135 
osif_pre_cac_set_legacy_cb(struct osif_pre_cac_legacy_ops * osif_legacy_ops)136 void osif_pre_cac_set_legacy_cb(struct osif_pre_cac_legacy_ops *osif_legacy_ops)
137 {
138 	osif_pre_cac_legacy_ops = osif_legacy_ops;
139 }
140 
osif_pre_cac_reset_legacy_cb(void)141 void osif_pre_cac_reset_legacy_cb(void)
142 {
143 	osif_pre_cac_legacy_ops = NULL;
144 }
145 
146 static struct pre_cac_ops pre_cac_ops = {
147 	.pre_cac_conditional_csa_ind_cb =
148 		osif_pre_cac_send_conditional_freq_switch_status,
149 	.pre_cac_complete_cb = osif_pre_cac_complete_cb,
150 };
151 
osif_pre_cac_register_cb(void)152 QDF_STATUS osif_pre_cac_register_cb(void)
153 {
154 	ucfg_pre_cac_set_osif_cb(&pre_cac_ops);
155 
156 	return QDF_STATUS_SUCCESS;
157 }
158