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