1daeccac2SArend van Spriel // SPDX-License-Identifier: ISC 205491d2cSKalle Valo /* 305491d2cSKalle Valo * Copyright (c) 2013 Broadcom Corporation 405491d2cSKalle Valo */ 505491d2cSKalle Valo 605491d2cSKalle Valo 705491d2cSKalle Valo #include <linux/types.h> 805491d2cSKalle Valo #include <linux/slab.h> 905491d2cSKalle Valo #include <linux/netdevice.h> 1005491d2cSKalle Valo 1105491d2cSKalle Valo #include <brcmu_wifi.h> 1205491d2cSKalle Valo #include "core.h" 1305491d2cSKalle Valo #include "bus.h" 1405491d2cSKalle Valo #include "debug.h" 1505491d2cSKalle Valo #include "proto.h" 1605491d2cSKalle Valo #include "bcdc.h" 1705491d2cSKalle Valo #include "msgbuf.h" 1805491d2cSKalle Valo 1905491d2cSKalle Valo brcmf_proto_attach(struct brcmf_pub * drvr)2005491d2cSKalle Valoint brcmf_proto_attach(struct brcmf_pub *drvr) 2105491d2cSKalle Valo { 2205491d2cSKalle Valo struct brcmf_proto *proto; 2305491d2cSKalle Valo 2405491d2cSKalle Valo brcmf_dbg(TRACE, "Enter\n"); 2505491d2cSKalle Valo 2605491d2cSKalle Valo proto = kzalloc(sizeof(*proto), GFP_ATOMIC); 2705491d2cSKalle Valo if (!proto) 2805491d2cSKalle Valo goto fail; 2905491d2cSKalle Valo 3005491d2cSKalle Valo drvr->proto = proto; 3105491d2cSKalle Valo 3205491d2cSKalle Valo if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) { 3305491d2cSKalle Valo if (brcmf_proto_bcdc_attach(drvr)) 3405491d2cSKalle Valo goto fail; 3505491d2cSKalle Valo } else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) { 3605491d2cSKalle Valo if (brcmf_proto_msgbuf_attach(drvr)) 3705491d2cSKalle Valo goto fail; 3805491d2cSKalle Valo } else { 39dcb1471bSRafał Miłecki bphy_err(drvr, "Unsupported proto type %d\n", 4005491d2cSKalle Valo drvr->bus_if->proto_type); 4105491d2cSKalle Valo goto fail; 4205491d2cSKalle Valo } 43b073ac1fSRafał Miłecki if (!proto->tx_queue_data || (proto->hdrpull == NULL) || 4405491d2cSKalle Valo (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) || 4505491d2cSKalle Valo (proto->configure_addr_mode == NULL) || 4634789d0cSArend Van Spriel (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL) || 4734789d0cSArend Van Spriel (proto->debugfs_create == NULL)) { 48dcb1471bSRafał Miłecki bphy_err(drvr, "Not all proto handlers have been installed\n"); 4905491d2cSKalle Valo goto fail; 5005491d2cSKalle Valo } 5105491d2cSKalle Valo return 0; 5205491d2cSKalle Valo 5305491d2cSKalle Valo fail: 5405491d2cSKalle Valo kfree(proto); 5505491d2cSKalle Valo drvr->proto = NULL; 5605491d2cSKalle Valo return -ENOMEM; 5705491d2cSKalle Valo } 5805491d2cSKalle Valo brcmf_proto_detach(struct brcmf_pub * drvr)59*a84a60ccSArend van Sprielvoid brcmf_proto_detach(struct brcmf_pub *drvr) 6005491d2cSKalle Valo { 6105491d2cSKalle Valo brcmf_dbg(TRACE, "Enter\n"); 6205491d2cSKalle Valo 6305491d2cSKalle Valo if (drvr->proto) { 6405491d2cSKalle Valo if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) 65*a84a60ccSArend van Spriel brcmf_proto_bcdc_detach(drvr); 6605491d2cSKalle Valo else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) 6705491d2cSKalle Valo brcmf_proto_msgbuf_detach(drvr); 6805491d2cSKalle Valo kfree(drvr->proto); 6905491d2cSKalle Valo drvr->proto = NULL; 7005491d2cSKalle Valo } 7105491d2cSKalle Valo } 72