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