1 // SPDX-License-Identifier: ISC
2 /*
3  * Copyright (c) 2013 Broadcom Corporation
4  */
5 
6 
7  #include <linux/types.h>
8 #include <linux/slab.h>
9 #include <linux/netdevice.h>
10 
11 #include <brcmu_wifi.h>
12 #include "core.h"
13 #include "bus.h"
14 #include "debug.h"
15 #include "proto.h"
16 #include "bcdc.h"
17 #include "msgbuf.h"
18 
19 
20 int brcmf_proto_attach(struct brcmf_pub *drvr)
21 {
22 	struct brcmf_proto *proto;
23 
24 	brcmf_dbg(TRACE, "Enter\n");
25 
26 	proto = kzalloc(sizeof(*proto), GFP_ATOMIC);
27 	if (!proto)
28 		goto fail;
29 
30 	drvr->proto = proto;
31 
32 	if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) {
33 		if (brcmf_proto_bcdc_attach(drvr))
34 			goto fail;
35 	} else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) {
36 		if (brcmf_proto_msgbuf_attach(drvr))
37 			goto fail;
38 	} else {
39 		bphy_err(drvr, "Unsupported proto type %d\n",
40 			 drvr->bus_if->proto_type);
41 		goto fail;
42 	}
43 	if (!proto->tx_queue_data || (proto->hdrpull == NULL) ||
44 	    (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
45 	    (proto->configure_addr_mode == NULL) ||
46 	    (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL) ||
47 	    (proto->debugfs_create == NULL)) {
48 		bphy_err(drvr, "Not all proto handlers have been installed\n");
49 		goto fail;
50 	}
51 	return 0;
52 
53 fail:
54 	kfree(proto);
55 	drvr->proto = NULL;
56 	return -ENOMEM;
57 }
58 
59 void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr)
60 {
61 	brcmf_dbg(TRACE, "Enter\n");
62 
63 	if (drvr->proto) {
64 		if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
65 			brcmf_proto_bcdc_detach_post_delif(drvr);
66 		else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF)
67 			brcmf_proto_msgbuf_detach(drvr);
68 		kfree(drvr->proto);
69 		drvr->proto = NULL;
70 	}
71 }
72 
73 void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr)
74 {
75 	if (drvr->proto && drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
76 		brcmf_proto_bcdc_detach_pre_delif(drvr);
77 }
78