^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Link Layer Control manager
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2012 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <net/nfc/llc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "llc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static LIST_HEAD(llc_engines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) int nfc_llc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) r = nfc_llc_nop_register();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) r = nfc_llc_shdlc_register();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) nfc_llc_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) void nfc_llc_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct nfc_llc_engine *llc_engine, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) list_for_each_entry_safe(llc_engine, n, &llc_engines, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) list_del(&llc_engine->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) kfree(llc_engine->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) kfree(llc_engine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int nfc_llc_register(const char *name, struct nfc_llc_ops *ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct nfc_llc_engine *llc_engine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) llc_engine = kzalloc(sizeof(struct nfc_llc_engine), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (llc_engine == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) llc_engine->name = kstrdup(name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (llc_engine->name == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) kfree(llc_engine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) llc_engine->ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) INIT_LIST_HEAD(&llc_engine->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) list_add_tail(&llc_engine->entry, &llc_engines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static struct nfc_llc_engine *nfc_llc_name_to_engine(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct nfc_llc_engine *llc_engine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) list_for_each_entry(llc_engine, &llc_engines, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (strcmp(llc_engine->name, name) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return llc_engine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) void nfc_llc_unregister(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct nfc_llc_engine *llc_engine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) llc_engine = nfc_llc_name_to_engine(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (llc_engine == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) list_del(&llc_engine->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) kfree(llc_engine->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) kfree(llc_engine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct nfc_llc *nfc_llc_allocate(const char *name, struct nfc_hci_dev *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) xmit_to_drv_t xmit_to_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) rcv_to_hci_t rcv_to_hci, int tx_headroom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int tx_tailroom, llc_failure_t llc_failure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct nfc_llc_engine *llc_engine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct nfc_llc *llc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) llc_engine = nfc_llc_name_to_engine(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (llc_engine == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) llc = kzalloc(sizeof(struct nfc_llc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (llc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) llc->data = llc_engine->ops->init(hdev, xmit_to_drv, rcv_to_hci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) tx_headroom, tx_tailroom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) &llc->rx_headroom, &llc->rx_tailroom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) llc_failure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (llc->data == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) kfree(llc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) llc->ops = llc_engine->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return llc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) void nfc_llc_free(struct nfc_llc *llc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) llc->ops->deinit(llc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) kfree(llc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int nfc_llc_start(struct nfc_llc *llc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return llc->ops->start(llc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) EXPORT_SYMBOL(nfc_llc_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int nfc_llc_stop(struct nfc_llc *llc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return llc->ops->stop(llc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) EXPORT_SYMBOL(nfc_llc_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) void nfc_llc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) llc->ops->rcv_from_drv(llc, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int nfc_llc_xmit_from_hci(struct nfc_llc *llc, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return llc->ops->xmit_from_hci(llc, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) void *nfc_llc_get_data(struct nfc_llc *llc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return llc->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }