xref: /wlan-driver/qca-wifi-host-cmn/utils/nlink/src/wlan_nlink_srv.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /******************************************************************************
21*5113495bSYour Name * wlan_nlink_srv.c
22*5113495bSYour Name *
23*5113495bSYour Name * This file contains the definitions specific to the wlan_nlink_srv
24*5113495bSYour Name *
25*5113495bSYour Name ******************************************************************************/
26*5113495bSYour Name 
27*5113495bSYour Name #include <linux/version.h>
28*5113495bSYour Name #include <linux/kernel.h>
29*5113495bSYour Name #include <linux/module.h>
30*5113495bSYour Name #include <linux/init.h>
31*5113495bSYour Name #include <linux/netdevice.h>
32*5113495bSYour Name #include <linux/netlink.h>
33*5113495bSYour Name #include <linux/skbuff.h>
34*5113495bSYour Name #include <net/sock.h>
35*5113495bSYour Name #include <wlan_nlink_srv.h>
36*5113495bSYour Name #include <qdf_trace.h>
37*5113495bSYour Name #include <qdf_module.h>
38*5113495bSYour Name 
39*5113495bSYour Name #define WLAN_CLD80211_MAX_SIZE (SKB_WITH_OVERHEAD(8192UL) - NLMSG_HDRLEN)
40*5113495bSYour Name 
41*5113495bSYour Name #if defined(CONFIG_CNSS_LOGGER)
42*5113495bSYour Name 
43*5113495bSYour Name #include <net/cnss_logger.h>
44*5113495bSYour Name 
45*5113495bSYour Name static int radio_idx = -EINVAL;
46*5113495bSYour Name static void *wiphy_ptr;
47*5113495bSYour Name static bool logger_initialized;
48*5113495bSYour Name 
49*5113495bSYour Name /**
50*5113495bSYour Name  * nl_srv_init() - wrapper function to register to cnss_logger
51*5113495bSYour Name  * @wiphy:	the pointer to the wiphy structure
52*5113495bSYour Name  * @proto:	the host log netlink protocol
53*5113495bSYour Name  *
54*5113495bSYour Name  * The netlink socket is no longer initialized in the driver itself, instead
55*5113495bSYour Name  * will be initialized in the cnss_logger module, the driver should register
56*5113495bSYour Name  * itself to cnss_logger module to get the radio_index for all the netlink
57*5113495bSYour Name  * operation. (cfg80211 vendor command is using different netlink socket).
58*5113495bSYour Name  *
59*5113495bSYour Name  * The cnss_logger_device_register() use to register the driver with the
60*5113495bSYour Name  * wiphy structure and the module name (debug purpose) and then return the
61*5113495bSYour Name  * radio_index depending on the availability.
62*5113495bSYour Name  *
63*5113495bSYour Name  * Return: radio index for success and -EINVAL for failure
64*5113495bSYour Name  */
nl_srv_init(void * wiphy,int proto)65*5113495bSYour Name int nl_srv_init(void *wiphy, int proto)
66*5113495bSYour Name {
67*5113495bSYour Name 	if (logger_initialized)
68*5113495bSYour Name 		goto initialized;
69*5113495bSYour Name 
70*5113495bSYour Name 	wiphy_ptr = wiphy;
71*5113495bSYour Name 	radio_idx = cnss_logger_device_register(wiphy, THIS_MODULE->name);
72*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
73*5113495bSYour Name 		  "%s: radio_index: %d, wiphy_ptr: %pK",
74*5113495bSYour Name 		  __func__, radio_idx, wiphy_ptr);
75*5113495bSYour Name 
76*5113495bSYour Name 	if (radio_idx >= 0)
77*5113495bSYour Name 		logger_initialized = true;
78*5113495bSYour Name 
79*5113495bSYour Name initialized:
80*5113495bSYour Name 	return radio_idx;
81*5113495bSYour Name }
82*5113495bSYour Name 
83*5113495bSYour Name /**
84*5113495bSYour Name  * nl_srv_exit() - wrapper function to unregister from cnss_logger
85*5113495bSYour Name  *
86*5113495bSYour Name  * The cnss_logger_device_unregister() use to unregister the driver with
87*5113495bSYour Name  * the radio_index assigned and wiphy structure from cnss_logger.
88*5113495bSYour Name  *
89*5113495bSYour Name  * Return: None
90*5113495bSYour Name  */
nl_srv_exit(void)91*5113495bSYour Name void nl_srv_exit(void)
92*5113495bSYour Name {
93*5113495bSYour Name 	if (logger_initialized) {
94*5113495bSYour Name 		cnss_logger_device_unregister(radio_idx, wiphy_ptr);
95*5113495bSYour Name 		radio_idx = -EINVAL;
96*5113495bSYour Name 		wiphy_ptr = NULL;
97*5113495bSYour Name 		logger_initialized = false;
98*5113495bSYour Name 	}
99*5113495bSYour Name }
100*5113495bSYour Name 
101*5113495bSYour Name /**
102*5113495bSYour Name  * nl_srv_ucast() - wrapper function to do unicast tx through cnss_logger
103*5113495bSYour Name  * @skb:	the socket buffer to send
104*5113495bSYour Name  * @dst_pid:	the port id
105*5113495bSYour Name  * @flag:	the blocking or nonblocking flag
106*5113495bSYour Name  *
107*5113495bSYour Name  * The nl_srv_is_initialized() is used to do sanity check if the netlink
108*5113495bSYour Name  * service is ready, e.g if the radio_index is assigned properly, if not
109*5113495bSYour Name  * the driver should take the responsibility to free the skb.
110*5113495bSYour Name  *
111*5113495bSYour Name  * The cnss_logger_nl_ucast() use the same parameters to send the socket
112*5113495bSYour Name  * buffers.
113*5113495bSYour Name  *
114*5113495bSYour Name  * Return: the error of the transmission status
115*5113495bSYour Name  */
nl_srv_ucast(struct sk_buff * skb,int dst_pid,int flag)116*5113495bSYour Name int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
117*5113495bSYour Name {
118*5113495bSYour Name 	int err = -EINVAL;
119*5113495bSYour Name 
120*5113495bSYour Name 	/* sender's pid */
121*5113495bSYour Name #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
122*5113495bSYour Name 	NETLINK_CB(skb).pid = 0;
123*5113495bSYour Name #else
124*5113495bSYour Name 	NETLINK_CB(skb).portid = 0;
125*5113495bSYour Name #endif
126*5113495bSYour Name 	/* not multicast */
127*5113495bSYour Name 	NETLINK_CB(skb).dst_group = 0;
128*5113495bSYour Name 
129*5113495bSYour Name 	if (nl_srv_is_initialized() == 0) {
130*5113495bSYour Name 		err = cnss_logger_nl_ucast(skb, dst_pid, flag);
131*5113495bSYour Name 		if (err < 0)
132*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
133*5113495bSYour Name 				  "NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
134*5113495bSYour Name 				  dst_pid, err);
135*5113495bSYour Name 	} else {
136*5113495bSYour Name 		dev_kfree_skb(skb);
137*5113495bSYour Name 	}
138*5113495bSYour Name 
139*5113495bSYour Name 	return err;
140*5113495bSYour Name }
141*5113495bSYour Name 
142*5113495bSYour Name /**
143*5113495bSYour Name  * nl_srv_bcast() - wrapper function to do broadcast tx through cnss_logger
144*5113495bSYour Name  * @skb:	the socket buffer to send
145*5113495bSYour Name  *
146*5113495bSYour Name  * The cnss_logger_nl_bcast() is used to transmit the socket buffer.
147*5113495bSYour Name  *
148*5113495bSYour Name  * Return: status of transmission
149*5113495bSYour Name  */
nl_srv_bcast(struct sk_buff * skb)150*5113495bSYour Name int nl_srv_bcast(struct sk_buff *skb)
151*5113495bSYour Name {
152*5113495bSYour Name 	int err = -EINVAL;
153*5113495bSYour Name 	int flags = GFP_KERNEL;
154*5113495bSYour Name 
155*5113495bSYour Name 	if (in_interrupt() || irqs_disabled() || in_atomic())
156*5113495bSYour Name 		flags = GFP_ATOMIC;
157*5113495bSYour Name 
158*5113495bSYour Name 	/* sender's pid */
159*5113495bSYour Name #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
160*5113495bSYour Name 	NETLINK_CB(skb).pid = 0;
161*5113495bSYour Name #else
162*5113495bSYour Name 	NETLINK_CB(skb).portid = 0;
163*5113495bSYour Name #endif
164*5113495bSYour Name 	 /* destination group */
165*5113495bSYour Name 	NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
166*5113495bSYour Name 
167*5113495bSYour Name 	if (nl_srv_is_initialized() == 0) {
168*5113495bSYour Name 		err = cnss_logger_nl_bcast(skb, WLAN_NLINK_MCAST_GRP_ID, flags);
169*5113495bSYour Name 		if ((err < 0) && (err != -ESRCH)) {
170*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
171*5113495bSYour Name 				  "NLINK: netlink_broadcast failed err = %d",
172*5113495bSYour Name 				   err);
173*5113495bSYour Name 			dev_kfree_skb(skb);
174*5113495bSYour Name 		}
175*5113495bSYour Name 	}
176*5113495bSYour Name 	else
177*5113495bSYour Name 		dev_kfree_skb(skb);
178*5113495bSYour Name 	return err;
179*5113495bSYour Name }
180*5113495bSYour Name qdf_export_symbol(nl_srv_bcast);
181*5113495bSYour Name 
182*5113495bSYour Name /**
183*5113495bSYour Name  * nl_srv_unregister() - wrapper function to unregister event to cnss_logger
184*5113495bSYour Name  * @msg_type:		the message to unregister
185*5113495bSYour Name  * @msg_handler:	the message handler
186*5113495bSYour Name  *
187*5113495bSYour Name  * The cnss_logger_event_unregister() is used to unregister the message and
188*5113495bSYour Name  * message handler.
189*5113495bSYour Name  *
190*5113495bSYour Name  * Return: 0 if successfully unregister, otherwise proper error code
191*5113495bSYour Name  */
nl_srv_unregister(tWlanNlModTypes msg_type,nl_srv_msg_callback msg_handler)192*5113495bSYour Name int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
193*5113495bSYour Name {
194*5113495bSYour Name 	int ret = -EINVAL;
195*5113495bSYour Name 
196*5113495bSYour Name 	if (nl_srv_is_initialized() != 0)
197*5113495bSYour Name 		return ret;
198*5113495bSYour Name 
199*5113495bSYour Name 	if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
200*5113495bSYour Name 	    msg_handler) {
201*5113495bSYour Name 		ret = cnss_logger_event_unregister(radio_idx, msg_type,
202*5113495bSYour Name 						   msg_handler);
203*5113495bSYour Name 	} else {
204*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
205*5113495bSYour Name 			  "NLINK: nl_srv_unregister failed for msg_type %d",
206*5113495bSYour Name 			  msg_type);
207*5113495bSYour Name 		ret = -EINVAL;
208*5113495bSYour Name 	}
209*5113495bSYour Name 
210*5113495bSYour Name 	return ret;
211*5113495bSYour Name }
212*5113495bSYour Name 
213*5113495bSYour Name /**
214*5113495bSYour Name  * nl_srv_register() - wrapper function to register event to cnss_logger
215*5113495bSYour Name  * @msg_type:		the message to register
216*5113495bSYour Name  * @msg_handler:	the message handler
217*5113495bSYour Name  *
218*5113495bSYour Name  * The cnss_logger_event_register() is used to register the message and
219*5113495bSYour Name  * message handler.
220*5113495bSYour Name  *
221*5113495bSYour Name  * Return: 0 if successfully register, otherwise proper error code
222*5113495bSYour Name  */
nl_srv_register(tWlanNlModTypes msg_type,nl_srv_msg_callback msg_handler)223*5113495bSYour Name int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
224*5113495bSYour Name {
225*5113495bSYour Name 	int ret = -EINVAL;
226*5113495bSYour Name 
227*5113495bSYour Name 	if (nl_srv_is_initialized() != 0)
228*5113495bSYour Name 		return ret;
229*5113495bSYour Name 
230*5113495bSYour Name 	if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
231*5113495bSYour Name 	    msg_handler) {
232*5113495bSYour Name 		ret = cnss_logger_event_register(radio_idx, msg_type,
233*5113495bSYour Name 						 msg_handler);
234*5113495bSYour Name 	} else {
235*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
236*5113495bSYour Name 			  "NLINK: nl_srv_register failed for msg_type %d",
237*5113495bSYour Name 			  msg_type);
238*5113495bSYour Name 		ret = -EINVAL;
239*5113495bSYour Name 	}
240*5113495bSYour Name 
241*5113495bSYour Name 	return ret;
242*5113495bSYour Name }
243*5113495bSYour Name 
244*5113495bSYour Name /**
245*5113495bSYour Name  * nl_srv_is_initialized() - check if netlink service is initialized
246*5113495bSYour Name  *
247*5113495bSYour Name  * Return: 0 if it is initialized, otherwise error code
248*5113495bSYour Name  */
nl_srv_is_initialized(void)249*5113495bSYour Name inline int nl_srv_is_initialized(void)
250*5113495bSYour Name {
251*5113495bSYour Name 	if (logger_initialized)
252*5113495bSYour Name 		return 0;
253*5113495bSYour Name 	else
254*5113495bSYour Name 		return -EPERM;
255*5113495bSYour Name }
256*5113495bSYour Name qdf_export_symbol(nl_srv_is_initialized);
257*5113495bSYour Name 
258*5113495bSYour Name /*
259*5113495bSYour Name  * If MULTI_IF_NAME is not defined, then this is the primary instance of the
260*5113495bSYour Name  * driver and the diagnostics netlink socket will be available. If
261*5113495bSYour Name  * MULTI_IF_NAME is defined then this is not the primary instance of the driver
262*5113495bSYour Name  * and the diagnostics netlink socket will not be available since this
263*5113495bSYour Name  * diagnostics netlink socket can only be exposed by one instance of the driver.
264*5113495bSYour Name  */
265*5113495bSYour Name #elif defined(CNSS_GENL)
266*5113495bSYour Name #include <qdf_mem.h>
267*5113495bSYour Name #include <wlan_nlink_common.h>
268*5113495bSYour Name #include <net/genetlink.h>
269*5113495bSYour Name #ifdef CONFIG_CNSS_OUT_OF_TREE
270*5113495bSYour Name #include "cnss_nl.h"
271*5113495bSYour Name #else
272*5113495bSYour Name #include <net/cnss_nl.h>
273*5113495bSYour Name #endif
274*5113495bSYour Name 
cld80211_oem_send_reply(struct sk_buff * msg,void * hdr,struct nlattr * nest,int flags)275*5113495bSYour Name void cld80211_oem_send_reply(struct sk_buff *msg, void *hdr,
276*5113495bSYour Name 				    struct nlattr *nest, int flags)
277*5113495bSYour Name {
278*5113495bSYour Name 	struct genl_family *cld80211_fam = cld80211_get_genl_family();
279*5113495bSYour Name 
280*5113495bSYour Name 	nla_nest_end(msg, nest);
281*5113495bSYour Name 	genlmsg_end(msg, hdr);
282*5113495bSYour Name 
283*5113495bSYour Name 	genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
284*5113495bSYour Name 				CLD80211_MCGRP_OEM_MSGS, flags);
285*5113495bSYour Name }
286*5113495bSYour Name 
287*5113495bSYour Name struct sk_buff *
cld80211_oem_rsp_alloc_skb(uint32_t portid,void ** hdr,struct nlattr ** nest,int * flags)288*5113495bSYour Name cld80211_oem_rsp_alloc_skb(uint32_t portid, void **hdr, struct nlattr **nest,
289*5113495bSYour Name 			   int *flags)
290*5113495bSYour Name {
291*5113495bSYour Name 	struct sk_buff *msg;
292*5113495bSYour Name 
293*5113495bSYour Name 	if (in_interrupt() || irqs_disabled() || in_atomic())
294*5113495bSYour Name 		*flags = GFP_ATOMIC;
295*5113495bSYour Name 
296*5113495bSYour Name 	msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, *flags);
297*5113495bSYour Name 	if (!msg) {
298*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
299*5113495bSYour Name 					"nlmsg malloc fails");
300*5113495bSYour Name 		return NULL;
301*5113495bSYour Name 	}
302*5113495bSYour Name 
303*5113495bSYour Name 	*hdr = nl80211hdr_put(msg, portid, 0, *flags, WLAN_NL_MSG_OEM);
304*5113495bSYour Name 	if (*hdr == NULL) {
305*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
306*5113495bSYour Name 					"nl80211 hdr put failed");
307*5113495bSYour Name 		goto nla_put_failure;
308*5113495bSYour Name 	}
309*5113495bSYour Name 
310*5113495bSYour Name 	*nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
311*5113495bSYour Name 	if (*nest == NULL) {
312*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
313*5113495bSYour Name 					"nla_nest_start failed");
314*5113495bSYour Name 		goto nla_put_failure;
315*5113495bSYour Name 	}
316*5113495bSYour Name 	return msg;
317*5113495bSYour Name nla_put_failure:
318*5113495bSYour Name 	genlmsg_cancel(msg, *hdr);
319*5113495bSYour Name 	nlmsg_free(msg);
320*5113495bSYour Name 	return NULL;
321*5113495bSYour Name }
322*5113495bSYour Name 
323*5113495bSYour Name /* For CNSS_GENL netlink sockets will be initialized by CNSS Kernel Module */
nl_srv_init(void * wiphy,int proto)324*5113495bSYour Name int nl_srv_init(void *wiphy, int proto)
325*5113495bSYour Name {
326*5113495bSYour Name 	return 0;
327*5113495bSYour Name }
328*5113495bSYour Name 
nl_srv_exit(void)329*5113495bSYour Name void nl_srv_exit(void)
330*5113495bSYour Name {
331*5113495bSYour Name }
332*5113495bSYour Name 
nl_srv_is_initialized(void)333*5113495bSYour Name int nl_srv_is_initialized(void)
334*5113495bSYour Name {
335*5113495bSYour Name 	return 0;
336*5113495bSYour Name }
337*5113495bSYour Name 
338*5113495bSYour Name /* Not implemented by CNSS kernel module */
nl_srv_register(tWlanNlModTypes msg_type,nl_srv_msg_callback msg_handler)339*5113495bSYour Name int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
340*5113495bSYour Name {
341*5113495bSYour Name 	return 0;
342*5113495bSYour Name }
343*5113495bSYour Name 
nl_srv_unregister(tWlanNlModTypes msg_type,nl_srv_msg_callback msg_handler)344*5113495bSYour Name int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
345*5113495bSYour Name {
346*5113495bSYour Name 	return 0;
347*5113495bSYour Name }
348*5113495bSYour Name 
nl80211hdr_put(struct sk_buff * skb,uint32_t portid,uint32_t seq,int flags,uint8_t cmd)349*5113495bSYour Name void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
350*5113495bSYour Name 		     uint32_t seq, int flags, uint8_t cmd)
351*5113495bSYour Name {
352*5113495bSYour Name 	struct genl_family *cld80211_fam = cld80211_get_genl_family();
353*5113495bSYour Name 
354*5113495bSYour Name 	return genlmsg_put(skb, portid, seq, cld80211_fam, flags, cmd);
355*5113495bSYour Name }
356*5113495bSYour Name 
357*5113495bSYour Name /**
358*5113495bSYour Name  * cld80211_fill_data() - API to fill payload to nl message
359*5113495bSYour Name  * @msg: Sk buffer
360*5113495bSYour Name  * @portid: Port ID
361*5113495bSYour Name  * @seq: Sequence number
362*5113495bSYour Name  * @flags: Flags
363*5113495bSYour Name  * @cmd: Command ID
364*5113495bSYour Name  * @buf: data buffer/payload to be filled
365*5113495bSYour Name  * @len: length of the payload ie. @buf
366*5113495bSYour Name  *
367*5113495bSYour Name  * API to fill the payload/data of the nl message to be sent
368*5113495bSYour Name  *
369*5113495bSYour Name  * Return: zero on success
370*5113495bSYour Name  */
cld80211_fill_data(struct sk_buff * msg,uint32_t portid,uint32_t seq,int flags,uint8_t cmd,uint8_t * buf,int len)371*5113495bSYour Name static int cld80211_fill_data(struct sk_buff *msg, uint32_t portid,
372*5113495bSYour Name 					uint32_t seq, int flags, uint8_t cmd,
373*5113495bSYour Name 					uint8_t *buf, int len)
374*5113495bSYour Name {
375*5113495bSYour Name 	void *hdr;
376*5113495bSYour Name 	struct nlattr *nest;
377*5113495bSYour Name 
378*5113495bSYour Name 	hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
379*5113495bSYour Name 	if (!hdr) {
380*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
381*5113495bSYour Name 						"nl80211 hdr put failed");
382*5113495bSYour Name 		return -EPERM;
383*5113495bSYour Name 	}
384*5113495bSYour Name 
385*5113495bSYour Name 	nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
386*5113495bSYour Name 	if (!nest) {
387*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
388*5113495bSYour Name 						"nla_nest_start failed");
389*5113495bSYour Name 		goto nla_put_failure;
390*5113495bSYour Name 	}
391*5113495bSYour Name 
392*5113495bSYour Name 	if (nla_put(msg, CLD80211_ATTR_DATA, len, buf)) {
393*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
394*5113495bSYour Name 							"nla_put failed");
395*5113495bSYour Name 		goto nla_put_failure;
396*5113495bSYour Name 	}
397*5113495bSYour Name 
398*5113495bSYour Name 	nla_nest_end(msg, nest);
399*5113495bSYour Name 	genlmsg_end(msg, hdr);
400*5113495bSYour Name 
401*5113495bSYour Name 	return 0;
402*5113495bSYour Name nla_put_failure:
403*5113495bSYour Name 	genlmsg_cancel(msg, hdr);
404*5113495bSYour Name 	return -EPERM;
405*5113495bSYour Name }
406*5113495bSYour Name 
407*5113495bSYour Name /**
408*5113495bSYour Name  * send_msg_to_cld80211() - API to send message to user space Application
409*5113495bSYour Name  * @mcgroup_id: Multicast group ID
410*5113495bSYour Name  * @pid: Port ID
411*5113495bSYour Name  * @app_id: Application ID
412*5113495bSYour Name  * @buf: Data/payload buffer to be sent
413*5113495bSYour Name  * @len: Length of the data ie. @buf
414*5113495bSYour Name  *
415*5113495bSYour Name  * API to send the nl message to user space application.
416*5113495bSYour Name  *
417*5113495bSYour Name  * Return: zero on success
418*5113495bSYour Name  */
send_msg_to_cld80211(int mcgroup_id,int pid,int app_id,uint8_t * buf,int len)419*5113495bSYour Name static int send_msg_to_cld80211(int mcgroup_id, int pid, int app_id,
420*5113495bSYour Name 						uint8_t *buf, int len)
421*5113495bSYour Name {
422*5113495bSYour Name 	struct sk_buff *msg;
423*5113495bSYour Name 	struct genl_family *cld80211_fam = cld80211_get_genl_family();
424*5113495bSYour Name 	int status;
425*5113495bSYour Name 	int flags = GFP_KERNEL;
426*5113495bSYour Name 
427*5113495bSYour Name 	if (in_interrupt() || irqs_disabled() || in_atomic())
428*5113495bSYour Name 		flags = GFP_ATOMIC;
429*5113495bSYour Name 
430*5113495bSYour Name 	if (len > NLMSG_DEFAULT_SIZE) {
431*5113495bSYour Name 		if (len > WLAN_CLD80211_MAX_SIZE) {
432*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
433*5113495bSYour Name 				"buf size:%d if more than max size: %d",
434*5113495bSYour Name 				len, (int) WLAN_CLD80211_MAX_SIZE);
435*5113495bSYour Name 			return -ENOMEM;
436*5113495bSYour Name 		}
437*5113495bSYour Name 		msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, flags);
438*5113495bSYour Name 	} else {
439*5113495bSYour Name 		msg = nlmsg_new(NLMSG_DEFAULT_SIZE, flags);
440*5113495bSYour Name 	}
441*5113495bSYour Name 	if (!msg) {
442*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
443*5113495bSYour Name 						"nlmsg malloc fails");
444*5113495bSYour Name 		return -EPERM;
445*5113495bSYour Name 	}
446*5113495bSYour Name 
447*5113495bSYour Name 	status = cld80211_fill_data(msg, pid, 0, 0, app_id, buf, len);
448*5113495bSYour Name 	if (status) {
449*5113495bSYour Name 		nlmsg_free(msg);
450*5113495bSYour Name 		return -EPERM;
451*5113495bSYour Name 	}
452*5113495bSYour Name 
453*5113495bSYour Name 	genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
454*5113495bSYour Name 						mcgroup_id, flags);
455*5113495bSYour Name 	return 0;
456*5113495bSYour Name }
457*5113495bSYour Name 
458*5113495bSYour Name /**
459*5113495bSYour Name  * nl_srv_bcast() - wrapper function to do broadcast events to user space apps
460*5113495bSYour Name  * @skb: the socket buffer to send
461*5113495bSYour Name  * @mcgroup_id: multicast group id
462*5113495bSYour Name  * @app_id: application id
463*5113495bSYour Name  *
464*5113495bSYour Name  * This function is common wrapper to send broadcast events to different
465*5113495bSYour Name  * user space applications.
466*5113495bSYour Name  *
467*5113495bSYour Name  * return: none
468*5113495bSYour Name  */
nl_srv_bcast(struct sk_buff * skb,int mcgroup_id,int app_id)469*5113495bSYour Name int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id)
470*5113495bSYour Name {
471*5113495bSYour Name 	struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
472*5113495bSYour Name 	void *msg = NLMSG_DATA(nlh);
473*5113495bSYour Name 	uint32_t msg_len = nlmsg_len(nlh);
474*5113495bSYour Name 	int status;
475*5113495bSYour Name 
476*5113495bSYour Name 	status = send_msg_to_cld80211(mcgroup_id, 0, app_id, msg, msg_len);
477*5113495bSYour Name 	if (status) {
478*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
479*5113495bSYour Name 			"send msg to cld80211 fails for app id %d", app_id);
480*5113495bSYour Name 		dev_kfree_skb(skb);
481*5113495bSYour Name 		return -EPERM;
482*5113495bSYour Name 	}
483*5113495bSYour Name 
484*5113495bSYour Name 	dev_kfree_skb(skb);
485*5113495bSYour Name 	return 0;
486*5113495bSYour Name }
487*5113495bSYour Name qdf_export_symbol(nl_srv_bcast);
488*5113495bSYour Name 
489*5113495bSYour Name /**
490*5113495bSYour Name  * nl_srv_ucast() - wrapper function to do unicast events to user space apps
491*5113495bSYour Name  * @skb: the socket buffer to send
492*5113495bSYour Name  * @dst_pid: destination process IF
493*5113495bSYour Name  * @flag: flags
494*5113495bSYour Name  * @app_id: application id
495*5113495bSYour Name  * @mcgroup_id: Multicast group ID
496*5113495bSYour Name  *
497*5113495bSYour Name  * This function is common wrapper to send unicast events to different
498*5113495bSYour Name  * user space applications. This internally used broadcast API with multicast
499*5113495bSYour Name  * group mcgrp_id. This wrapper serves as a common API in both
500*5113495bSYour Name  * new generic netlink infra and legacy implementation.
501*5113495bSYour Name  *
502*5113495bSYour Name  * return: zero on success, error code otherwise
503*5113495bSYour Name  */
nl_srv_ucast(struct sk_buff * skb,int dst_pid,int flag,int app_id,int mcgroup_id)504*5113495bSYour Name int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
505*5113495bSYour Name 					int app_id, int mcgroup_id)
506*5113495bSYour Name {
507*5113495bSYour Name 	struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
508*5113495bSYour Name 	void *msg = NLMSG_DATA(nlh);
509*5113495bSYour Name 	uint32_t msg_len = nlmsg_len(nlh);
510*5113495bSYour Name 	int status;
511*5113495bSYour Name 
512*5113495bSYour Name 	status = send_msg_to_cld80211(mcgroup_id, dst_pid, app_id,
513*5113495bSYour Name 					msg, msg_len);
514*5113495bSYour Name 	if (status) {
515*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
516*5113495bSYour Name 			"send msg to cld80211 fails for app id %d", app_id);
517*5113495bSYour Name 		dev_kfree_skb(skb);
518*5113495bSYour Name 		return -EPERM;
519*5113495bSYour Name 	}
520*5113495bSYour Name 
521*5113495bSYour Name 	dev_kfree_skb(skb);
522*5113495bSYour Name 	return 0;
523*5113495bSYour Name }
524*5113495bSYour Name 
525*5113495bSYour Name #elif !defined(MULTI_IF_NAME) || defined(MULTI_IF_LOG)
526*5113495bSYour Name 
527*5113495bSYour Name /* Global variables */
528*5113495bSYour Name static DEFINE_MUTEX(nl_srv_sem);
529*5113495bSYour Name static struct sock *nl_srv_sock;
530*5113495bSYour Name static nl_srv_msg_callback nl_srv_msg_handler[NLINK_MAX_CALLBACKS];
531*5113495bSYour Name 
532*5113495bSYour Name /* Forward declaration */
533*5113495bSYour Name static void nl_srv_rcv(struct sk_buff *sk);
534*5113495bSYour Name static void nl_srv_rcv_skb(struct sk_buff *skb);
535*5113495bSYour Name static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh);
536*5113495bSYour Name 
537*5113495bSYour Name /*
538*5113495bSYour Name  * Initialize the netlink service.
539*5113495bSYour Name  * Netlink service is usable after this.
540*5113495bSYour Name  */
nl_srv_init(void * wiphy,int proto)541*5113495bSYour Name int nl_srv_init(void *wiphy, int proto)
542*5113495bSYour Name {
543*5113495bSYour Name 	int retcode = 0;
544*5113495bSYour Name 	struct netlink_kernel_cfg cfg = {
545*5113495bSYour Name 		.groups = WLAN_NLINK_MCAST_GRP_ID,
546*5113495bSYour Name 		.input = nl_srv_rcv
547*5113495bSYour Name 	};
548*5113495bSYour Name 
549*5113495bSYour Name 	nl_srv_sock = netlink_kernel_create(&init_net, proto,
550*5113495bSYour Name 					    &cfg);
551*5113495bSYour Name 
552*5113495bSYour Name 	if (nl_srv_sock) {
553*5113495bSYour Name 		memset(nl_srv_msg_handler, 0, sizeof(nl_srv_msg_handler));
554*5113495bSYour Name 	} else {
555*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
556*5113495bSYour Name 			  "NLINK: netlink_kernel_create failed");
557*5113495bSYour Name 		retcode = -ECONNREFUSED;
558*5113495bSYour Name 	}
559*5113495bSYour Name 	return retcode;
560*5113495bSYour Name }
561*5113495bSYour Name 
562*5113495bSYour Name /*
563*5113495bSYour Name  * Deinit the netlink service.
564*5113495bSYour Name  * Netlink service is unusable after this.
565*5113495bSYour Name  */
nl_srv_exit(void)566*5113495bSYour Name void nl_srv_exit(void)
567*5113495bSYour Name {
568*5113495bSYour Name 	if (nl_srv_is_initialized() == 0)
569*5113495bSYour Name 		netlink_kernel_release(nl_srv_sock);
570*5113495bSYour Name 
571*5113495bSYour Name 	nl_srv_sock = NULL;
572*5113495bSYour Name }
573*5113495bSYour Name 
574*5113495bSYour Name /*
575*5113495bSYour Name  * Register a message handler for a specified module.
576*5113495bSYour Name  * Each module (e.g. WLAN_NL_MSG_BTC )will register a
577*5113495bSYour Name  * handler to handle messages addressed to it.
578*5113495bSYour Name  */
nl_srv_register(tWlanNlModTypes msg_type,nl_srv_msg_callback msg_handler)579*5113495bSYour Name int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
580*5113495bSYour Name {
581*5113495bSYour Name 	int retcode = 0;
582*5113495bSYour Name 
583*5113495bSYour Name 	if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
584*5113495bSYour Name 	    msg_handler) {
585*5113495bSYour Name 		nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = msg_handler;
586*5113495bSYour Name 	} else {
587*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
588*5113495bSYour Name 			  "NLINK: nl_srv_register failed for msg_type %d",
589*5113495bSYour Name 			  msg_type);
590*5113495bSYour Name 		retcode = -EINVAL;
591*5113495bSYour Name 	}
592*5113495bSYour Name 
593*5113495bSYour Name 	return retcode;
594*5113495bSYour Name }
595*5113495bSYour Name 
596*5113495bSYour Name qdf_export_symbol(nl_srv_register);
597*5113495bSYour Name 
598*5113495bSYour Name /*
599*5113495bSYour Name  * Unregister the message handler for a specified module.
600*5113495bSYour Name  */
nl_srv_unregister(tWlanNlModTypes msg_type,nl_srv_msg_callback msg_handler)601*5113495bSYour Name int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
602*5113495bSYour Name {
603*5113495bSYour Name 	int retcode = 0;
604*5113495bSYour Name 
605*5113495bSYour Name 	if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
606*5113495bSYour Name 	    (nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] == msg_handler)) {
607*5113495bSYour Name 		nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = NULL;
608*5113495bSYour Name 	} else {
609*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
610*5113495bSYour Name 			  "NLINK: nl_srv_unregister failed for msg_type %d",
611*5113495bSYour Name 			  msg_type);
612*5113495bSYour Name 		retcode = -EINVAL;
613*5113495bSYour Name 	}
614*5113495bSYour Name 
615*5113495bSYour Name 	return retcode;
616*5113495bSYour Name }
617*5113495bSYour Name 
618*5113495bSYour Name /*
619*5113495bSYour Name  * Unicast the message to the process in user space identfied
620*5113495bSYour Name  * by the dst-pid
621*5113495bSYour Name  */
nl_srv_ucast(struct sk_buff * skb,int dst_pid,int flag)622*5113495bSYour Name int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
623*5113495bSYour Name {
624*5113495bSYour Name 	int err = -EINVAL;
625*5113495bSYour Name 
626*5113495bSYour Name 	NETLINK_CB(skb).portid = 0;     /* sender's pid */
627*5113495bSYour Name 	NETLINK_CB(skb).dst_group = 0;  /* not multicast */
628*5113495bSYour Name 
629*5113495bSYour Name 	if (nl_srv_sock) {
630*5113495bSYour Name 		err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag);
631*5113495bSYour Name 		if (err < 0)
632*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
633*5113495bSYour Name 				  "NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
634*5113495bSYour Name 				  dst_pid, err);
635*5113495bSYour Name 	} else {
636*5113495bSYour Name 		dev_kfree_skb(skb);
637*5113495bSYour Name 	}
638*5113495bSYour Name 
639*5113495bSYour Name 	return err;
640*5113495bSYour Name }
641*5113495bSYour Name 
642*5113495bSYour Name /*
643*5113495bSYour Name  *  Broadcast the message. Broadcast will return an error if
644*5113495bSYour Name  *  there are no listeners
645*5113495bSYour Name  */
nl_srv_bcast(struct sk_buff * skb)646*5113495bSYour Name int nl_srv_bcast(struct sk_buff *skb)
647*5113495bSYour Name {
648*5113495bSYour Name 	int err = -EINVAL;
649*5113495bSYour Name 	int flags = GFP_KERNEL;
650*5113495bSYour Name 
651*5113495bSYour Name 	if (in_interrupt() || irqs_disabled() || in_atomic())
652*5113495bSYour Name 		flags = GFP_ATOMIC;
653*5113495bSYour Name 
654*5113495bSYour Name 	NETLINK_CB(skb).portid = 0;     /* sender's pid */
655*5113495bSYour Name 	NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;    /* destination group */
656*5113495bSYour Name 
657*5113495bSYour Name 	if (nl_srv_sock) {
658*5113495bSYour Name 		err = netlink_broadcast(nl_srv_sock, skb, 0,
659*5113495bSYour Name 					WLAN_NLINK_MCAST_GRP_ID, flags);
660*5113495bSYour Name 		if ((err < 0) && (err != -ESRCH)) {
661*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
662*5113495bSYour Name 				  "NLINK: netlink_broadcast failed err = %d",
663*5113495bSYour Name 				   err);
664*5113495bSYour Name 			dev_kfree_skb(skb);
665*5113495bSYour Name 		}
666*5113495bSYour Name 	} else
667*5113495bSYour Name 		dev_kfree_skb(skb);
668*5113495bSYour Name 	return err;
669*5113495bSYour Name }
670*5113495bSYour Name qdf_export_symbol(nl_srv_bcast);
671*5113495bSYour Name 
672*5113495bSYour Name /*
673*5113495bSYour Name  *  Processes the Netlink socket input queue.
674*5113495bSYour Name  *  Dequeue skb's from the socket input queue and process
675*5113495bSYour Name  *  all the netlink messages in that skb, before moving
676*5113495bSYour Name  *  to the next skb.
677*5113495bSYour Name  */
nl_srv_rcv(struct sk_buff * sk)678*5113495bSYour Name static void nl_srv_rcv(struct sk_buff *sk)
679*5113495bSYour Name {
680*5113495bSYour Name 	mutex_lock(&nl_srv_sem);
681*5113495bSYour Name 	nl_srv_rcv_skb(sk);
682*5113495bSYour Name 	mutex_unlock(&nl_srv_sem);
683*5113495bSYour Name }
684*5113495bSYour Name 
685*5113495bSYour Name /*
686*5113495bSYour Name  * Each skb could contain multiple Netlink messages. Process all the
687*5113495bSYour Name  * messages in one skb and discard malformed skb's silently.
688*5113495bSYour Name  */
nl_srv_rcv_skb(struct sk_buff * skb)689*5113495bSYour Name static void nl_srv_rcv_skb(struct sk_buff *skb)
690*5113495bSYour Name {
691*5113495bSYour Name 	struct nlmsghdr *nlh;
692*5113495bSYour Name 
693*5113495bSYour Name 	while (skb->len >= NLMSG_SPACE(0)) {
694*5113495bSYour Name 		u32 rlen;
695*5113495bSYour Name 
696*5113495bSYour Name 		nlh = (struct nlmsghdr *)skb->data;
697*5113495bSYour Name 
698*5113495bSYour Name 		if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) {
699*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
700*5113495bSYour Name 				  "NLINK: Invalid "
701*5113495bSYour Name 				  "Netlink message: skb[%pK], len[%d], nlhdr[%pK], nlmsg_len[%d]",
702*5113495bSYour Name 				  skb, skb->len, nlh, nlh->nlmsg_len);
703*5113495bSYour Name 			return;
704*5113495bSYour Name 		}
705*5113495bSYour Name 
706*5113495bSYour Name 		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
707*5113495bSYour Name 		if (rlen > skb->len)
708*5113495bSYour Name 			rlen = skb->len;
709*5113495bSYour Name 		nl_srv_rcv_msg(skb, nlh);
710*5113495bSYour Name 		skb_pull(skb, rlen);
711*5113495bSYour Name 	}
712*5113495bSYour Name }
713*5113495bSYour Name 
714*5113495bSYour Name /*
715*5113495bSYour Name  * Process a netlink message.
716*5113495bSYour Name  * Each netlink message will have a message of type tAniMsgHdr inside.
717*5113495bSYour Name  */
nl_srv_rcv_msg(struct sk_buff * skb,struct nlmsghdr * nlh)718*5113495bSYour Name static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
719*5113495bSYour Name {
720*5113495bSYour Name 	int type;
721*5113495bSYour Name 
722*5113495bSYour Name 	/* Only requests are handled by kernel now */
723*5113495bSYour Name 	if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
724*5113495bSYour Name 		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD,
725*5113495bSYour Name 				   "NLINK: Received Invalid NL Req type [%x]",
726*5113495bSYour Name 				   nlh->nlmsg_flags);
727*5113495bSYour Name 		return;
728*5113495bSYour Name 	}
729*5113495bSYour Name 
730*5113495bSYour Name 	type = nlh->nlmsg_type;
731*5113495bSYour Name 
732*5113495bSYour Name 	/* Unknown message */
733*5113495bSYour Name 	if (type < WLAN_NL_MSG_BASE || type >= WLAN_NL_MSG_MAX) {
734*5113495bSYour Name 		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD,
735*5113495bSYour Name 				   "NLINK: Received Invalid NL Msg type [%x]",
736*5113495bSYour Name 				   type);
737*5113495bSYour Name 		return;
738*5113495bSYour Name 	}
739*5113495bSYour Name 
740*5113495bSYour Name 	/*
741*5113495bSYour Name 	 * All the messages must at least carry the tAniMsgHdr
742*5113495bSYour Name 	 * Drop any message with invalid length
743*5113495bSYour Name 	 */
744*5113495bSYour Name 	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(tAniMsgHdr))) {
745*5113495bSYour Name 		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD,
746*5113495bSYour Name 				   "NLINK: Received NL Msg with invalid len[%x]",
747*5113495bSYour Name 				   nlh->nlmsg_len);
748*5113495bSYour Name 		return;
749*5113495bSYour Name 	}
750*5113495bSYour Name 
751*5113495bSYour Name 	/* turn type into dispatch table offset */
752*5113495bSYour Name 	type -= WLAN_NL_MSG_BASE;
753*5113495bSYour Name 
754*5113495bSYour Name 	/* dispatch to handler */
755*5113495bSYour Name 	if (nl_srv_msg_handler[type]) {
756*5113495bSYour Name 		(nl_srv_msg_handler[type])(skb);
757*5113495bSYour Name 	} else {
758*5113495bSYour Name 		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD,
759*5113495bSYour Name 				   "NLINK: No handler for msg [0x%X]", type);
760*5113495bSYour Name 	}
761*5113495bSYour Name }
762*5113495bSYour Name 
763*5113495bSYour Name /**
764*5113495bSYour Name  * nl_srv_is_initialized() - This function is used check if the netlink
765*5113495bSYour Name  * service is initialized
766*5113495bSYour Name  *
767*5113495bSYour Name  * This function is used check if the netlink service is initialized
768*5113495bSYour Name  *
769*5113495bSYour Name  * Return: Return -EPERM if the service is not initialized
770*5113495bSYour Name  *
771*5113495bSYour Name  */
nl_srv_is_initialized(void)772*5113495bSYour Name int nl_srv_is_initialized(void)
773*5113495bSYour Name {
774*5113495bSYour Name 	if (nl_srv_sock)
775*5113495bSYour Name 		return 0;
776*5113495bSYour Name 
777*5113495bSYour Name 	return -EPERM;
778*5113495bSYour Name }
779*5113495bSYour Name qdf_export_symbol(nl_srv_is_initialized);
780*5113495bSYour Name 
781*5113495bSYour Name #else
782*5113495bSYour Name 
nl_srv_init(void * wiphy,int proto)783*5113495bSYour Name int nl_srv_init(void *wiphy, int proto)
784*5113495bSYour Name {
785*5113495bSYour Name 	return 0;
786*5113495bSYour Name }
787*5113495bSYour Name 
nl_srv_exit(void)788*5113495bSYour Name void nl_srv_exit(void)
789*5113495bSYour Name {
790*5113495bSYour Name }
791*5113495bSYour Name 
nl_srv_register(tWlanNlModTypes msg_type,nl_srv_msg_callback msg_handler)792*5113495bSYour Name int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
793*5113495bSYour Name {
794*5113495bSYour Name 	return 0;
795*5113495bSYour Name }
796*5113495bSYour Name 
nl_srv_unregister(tWlanNlModTypes msg_type,nl_srv_msg_callback msg_handler)797*5113495bSYour Name int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
798*5113495bSYour Name {
799*5113495bSYour Name 	return 0;
800*5113495bSYour Name }
801*5113495bSYour Name 
nl_srv_ucast(struct sk_buff * skb,int dst_pid,int flag)802*5113495bSYour Name int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
803*5113495bSYour Name {
804*5113495bSYour Name 	dev_kfree_skb(skb);
805*5113495bSYour Name 	return 0;
806*5113495bSYour Name }
807*5113495bSYour Name 
nl_srv_bcast(struct sk_buff * skb)808*5113495bSYour Name int nl_srv_bcast(struct sk_buff *skb)
809*5113495bSYour Name {
810*5113495bSYour Name 	dev_kfree_skb(skb);
811*5113495bSYour Name 	return 0;
812*5113495bSYour Name }
813*5113495bSYour Name qdf_export_symbol(nl_srv_bcast);
814*5113495bSYour Name 
nl_srv_is_initialized(void)815*5113495bSYour Name int nl_srv_is_initialized(void)
816*5113495bSYour Name {
817*5113495bSYour Name 	return -EPERM;
818*5113495bSYour Name }
819*5113495bSYour Name qdf_export_symbol(nl_srv_is_initialized);
820*5113495bSYour Name #endif
821*5113495bSYour Name 
822*5113495bSYour Name /**
823*5113495bSYour Name  * nl_srv_ucast_oem() - Wrapper function to send ucast msgs to OEM
824*5113495bSYour Name  * @skb: sk buffer pointer
825*5113495bSYour Name  * @dst_pid: Destination PID
826*5113495bSYour Name  * @flag: flags
827*5113495bSYour Name  *
828*5113495bSYour Name  * Sends the ucast message to OEM with generic nl socket if CNSS_GENL
829*5113495bSYour Name  * is enabled. Else, use the legacy netlink socket to send.
830*5113495bSYour Name  *
831*5113495bSYour Name  * Return: None
832*5113495bSYour Name  */
833*5113495bSYour Name #ifdef CNSS_GENL
nl_srv_ucast_oem(struct sk_buff * skb,int dst_pid,int flag)834*5113495bSYour Name void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag)
835*5113495bSYour Name {
836*5113495bSYour Name 	nl_srv_ucast(skb, dst_pid, flag, WLAN_NL_MSG_OEM,
837*5113495bSYour Name 					CLD80211_MCGRP_OEM_MSGS);
838*5113495bSYour Name }
839*5113495bSYour Name #else
nl_srv_ucast_oem(struct sk_buff * skb,int dst_pid,int flag)840*5113495bSYour Name void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag)
841*5113495bSYour Name {
842*5113495bSYour Name 	nl_srv_ucast(skb, dst_pid, flag);
843*5113495bSYour Name }
844*5113495bSYour Name 
845*5113495bSYour Name qdf_export_symbol(nl_srv_ucast_oem);
846*5113495bSYour Name #endif
847