Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / net / wireless / broadcom / brcm80211 / brcmfmac / proto.c
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 }