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