^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* $Id: kcapi.c,v 1.1.2.8 2004/03/26 19:57:20 armin Exp $
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Kernel CAPI 2.0 Module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 1999 by Carsten Paeth <calle@calle.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This software may be used and distributed according to the terms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * of the GNU General Public License, incorporated herein by reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "kcapi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/capi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/kernelcapi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/isdn/capicmd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/isdn/capiutil.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/rcupdate.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int showcapimsgs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static struct workqueue_struct *kcapi_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) module_param(showcapimsgs, uint, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* ------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct capictr_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u32 controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* ------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static const struct capi_version driver_version = {2, 0, 1, 1 << 4};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static char driver_serial[CAPI_SERIAL_LEN] = "0004711";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static char capi_manufakturer[64] = "AVM Berlin";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct capi_ctr *capi_controller[CAPI_MAXCONTR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) DEFINE_MUTEX(capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct capi20_appl *capi_applications[CAPI_MAXAPPL];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static int ncontrollers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* -------- controller ref counting -------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static inline struct capi_ctr *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) capi_ctr_get(struct capi_ctr *ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (!try_module_get(ctr->owner))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) capi_ctr_put(struct capi_ctr *ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) module_put(ctr->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* ------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (contr < 1 || contr - 1 >= CAPI_MAXCONTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return capi_controller[contr - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) lockdep_assert_held(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return capi_applications[applid - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return rcu_dereference(capi_applications[applid - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* -------- util functions ------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static inline int capi_cmd_valid(u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) case CAPI_ALERT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) case CAPI_CONNECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) case CAPI_CONNECT_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) case CAPI_CONNECT_B3_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) case CAPI_CONNECT_B3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case CAPI_CONNECT_B3_T90_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) case CAPI_DATA_B3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case CAPI_DISCONNECT_B3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case CAPI_DISCONNECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case CAPI_FACILITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case CAPI_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) case CAPI_LISTEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case CAPI_MANUFACTURER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) case CAPI_RESET_B3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case CAPI_SELECT_B_PROTOCOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static inline int capi_subcmd_valid(u8 subcmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) switch (subcmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) case CAPI_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case CAPI_CONF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case CAPI_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) case CAPI_RESP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* ------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) register_appl(struct capi_ctr *ctr, u16 applid, capi_register_params *rparam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ctr = capi_ctr_get(ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ctr->register_appl(ctr, applid, rparam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) printk(KERN_WARNING "%s: cannot get controller resources\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static void release_appl(struct capi_ctr *ctr, u16 applid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) DBG("applid %#x", applid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ctr->release_appl(ctr, applid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) capi_ctr_put(ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static void notify_up(u32 contr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct capi20_appl *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct capi_ctr *ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u16 applid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (showcapimsgs & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ctr = get_capi_ctr_by_nr(contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (ctr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (ctr->state == CAPI_CTR_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) goto unlock_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ctr->state = CAPI_CTR_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ap = __get_capi_appl_by_nr(applid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) register_appl(ctr, applid, &ap->rparam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) unlock_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static void ctr_down(struct capi_ctr *ctr, int new_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct capi20_appl *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u16 applid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (ctr->state == CAPI_CTR_DETECTED || ctr->state == CAPI_CTR_DETACHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ctr->state = new_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) memset(ctr->manu, 0, sizeof(ctr->manu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) memset(&ctr->version, 0, sizeof(ctr->version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) memset(&ctr->profile, 0, sizeof(ctr->profile));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) memset(ctr->serial, 0, sizeof(ctr->serial));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ap = __get_capi_appl_by_nr(applid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) capi_ctr_put(ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static void notify_down(u32 contr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct capi_ctr *ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (showcapimsgs & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ctr = get_capi_ctr_by_nr(contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ctr_down(ctr, CAPI_CTR_DETECTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static void do_notify_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct capictr_event *event =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) container_of(work, struct capictr_event, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) switch (event->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case CAPICTR_UP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) notify_up(event->controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case CAPICTR_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) notify_down(event->controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) kfree(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int notify_push(unsigned int event_type, u32 controller)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) INIT_WORK(&event->work, do_notify_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) event->type = event_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) event->controller = controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) queue_work(kcapi_wq, &event->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* -------- Receiver ------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static void recv_handler(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct capi20_appl *ap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) container_of(work, struct capi20_appl, recv_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if ((!ap) || (ap->release_in_progress))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mutex_lock(&ap->recv_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) while ((skb = skb_dequeue(&ap->recv_queue))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ap->nrecvdatapkt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ap->nrecvctlpkt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ap->recv_message(ap, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mutex_unlock(&ap->recv_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * capi_ctr_handle_message() - handle incoming CAPI message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * @ctr: controller descriptor structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * @appl: application ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * @skb: message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * Called by hardware driver to pass a CAPI message to the application.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct capi20_appl *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int showctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) u8 cmd, subcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) _cdebbuf *cdb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (ctr->state != CAPI_CTR_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) cdb = capi_message2str(skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (cdb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ctr->cnr, cdb->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) cdebbuf_free(cdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ctr->cnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) cmd = CAPIMSG_COMMAND(skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) subcmd = CAPIMSG_SUBCOMMAND(skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) ctr->nrecvdatapkt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (ctr->traceflag > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) showctl |= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ctr->nrecvctlpkt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (ctr->traceflag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) showctl |= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) showctl |= (ctr->traceflag & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (showctl & 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (showctl & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ctr->cnr, CAPIMSG_APPID(skb->data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) capi_cmd2str(cmd, subcmd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) CAPIMSG_LEN(skb->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) cdb = capi_message2str(skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (cdb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) printk(KERN_DEBUG "kcapi: got [%03d] %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ctr->cnr, cdb->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) cdebbuf_free(cdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ctr->cnr, CAPIMSG_APPID(skb->data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) capi_cmd2str(cmd, subcmd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) CAPIMSG_LEN(skb->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (!ap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) cdb = capi_message2str(skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (cdb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) CAPIMSG_APPID(skb->data), cdb->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) cdebbuf_free(cdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) CAPIMSG_APPID(skb->data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) capi_cmd2str(cmd, subcmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) skb_queue_tail(&ap->recv_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) queue_work(kcapi_wq, &ap->recv_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) EXPORT_SYMBOL(capi_ctr_handle_message);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * capi_ctr_ready() - signal CAPI controller ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * @ctr: controller descriptor structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * Called by hardware driver to signal that the controller is up and running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) void capi_ctr_ready(struct capi_ctr *ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) ctr->cnr, ctr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) notify_push(CAPICTR_UP, ctr->cnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) EXPORT_SYMBOL(capi_ctr_ready);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * capi_ctr_down() - signal CAPI controller not ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * @ctr: controller descriptor structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * Called by hardware driver to signal that the controller is down and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * unavailable for use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) void capi_ctr_down(struct capi_ctr *ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) notify_push(CAPICTR_DOWN, ctr->cnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) EXPORT_SYMBOL(capi_ctr_down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* ------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * attach_capi_ctr() - register CAPI controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * @ctr: controller descriptor structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * Called by hardware driver to register a controller with the CAPI subsystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * Return value: 0 on success, error code < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int attach_capi_ctr(struct capi_ctr *ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) for (i = 0; i < CAPI_MAXCONTR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (!capi_controller[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (i == CAPI_MAXCONTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) printk(KERN_ERR "kcapi: out of controller slots\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) capi_controller[i] = ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ctr->nrecvctlpkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ctr->nrecvdatapkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ctr->nsentctlpkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ctr->nsentdatapkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ctr->cnr = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ctr->state = CAPI_CTR_DETECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) ctr->blocked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ctr->traceflag = showcapimsgs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ctr->procent = proc_create_single_data(ctr->procfn, 0, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ctr->proc_show, ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ncontrollers++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ctr->cnr, ctr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) EXPORT_SYMBOL(attach_capi_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * detach_capi_ctr() - unregister CAPI controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * @ctr: controller descriptor structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * Called by hardware driver to remove the registration of a controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * with the CAPI subsystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * Return value: 0 on success, error code < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int detach_capi_ctr(struct capi_ctr *ctr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) ctr_down(ctr, CAPI_CTR_DETACHED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (ctr->cnr < 1 || ctr->cnr - 1 >= CAPI_MAXCONTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) goto unlock_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (capi_controller[ctr->cnr - 1] != ctr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) goto unlock_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) capi_controller[ctr->cnr - 1] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ncontrollers--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (ctr->procent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) remove_proc_entry(ctr->procfn, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ctr->cnr, ctr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) unlock_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) EXPORT_SYMBOL(detach_capi_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /* ------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* -------- CAPI2.0 Interface ---------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /* ------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * capi20_isinstalled() - CAPI 2.0 operation CAPI_INSTALLED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * Return value: CAPI result code (CAPI_NOERROR if at least one ISDN controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * is ready for use, CAPI_REGNOTINSTALLED otherwise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) u16 capi20_isinstalled(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) u16 ret = CAPI_REGNOTINSTALLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) for (i = 0; i < CAPI_MAXCONTR; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (capi_controller[i] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) capi_controller[i]->state == CAPI_CTR_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ret = CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * capi20_register() - CAPI 2.0 operation CAPI_REGISTER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * @ap: CAPI application descriptor structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * Register an application's presence with CAPI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * A unique application ID is assigned and stored in @ap->applid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * After this function returns successfully, the message receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * callback function @ap->recv_message() may be called at any time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * until capi20_release() has been called for the same @ap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * Return value: CAPI result code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) u16 capi20_register(struct capi20_appl *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) u16 applid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) DBG("");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (ap->rparam.datablklen < 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return CAPI_LOGBLKSIZETOSMALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ap->nrecvctlpkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) ap->nrecvdatapkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) ap->nsentctlpkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) ap->nsentdatapkt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) mutex_init(&ap->recv_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) skb_queue_head_init(&ap->recv_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) INIT_WORK(&ap->recv_work, recv_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) ap->release_in_progress = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (capi_applications[applid - 1] == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (applid > CAPI_MAXAPPL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return CAPI_TOOMANYAPPLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ap->applid = applid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) capi_applications[applid - 1] = ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) for (i = 0; i < CAPI_MAXCONTR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (!capi_controller[i] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) capi_controller[i]->state != CAPI_CTR_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) register_appl(capi_controller[i], applid, &ap->rparam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (showcapimsgs & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * capi20_release() - CAPI 2.0 operation CAPI_RELEASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * @ap: CAPI application descriptor structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * Terminate an application's registration with CAPI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * After this function returns successfully, the message receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * callback function @ap->recv_message() will no longer be called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * Return value: CAPI result code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) u16 capi20_release(struct capi20_appl *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) DBG("applid %#x", ap->applid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ap->release_in_progress = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) capi_applications[ap->applid - 1] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) for (i = 0; i < CAPI_MAXCONTR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (!capi_controller[i] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) capi_controller[i]->state != CAPI_CTR_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) release_appl(capi_controller[i], ap->applid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) flush_workqueue(kcapi_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) skb_queue_purge(&ap->recv_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (showcapimsgs & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * @ap: CAPI application descriptor structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * @skb: CAPI message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * Transfer a single message to CAPI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * Return value: CAPI result code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct capi_ctr *ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) int showctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) u8 cmd, subcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) DBG("applid %#x", ap->applid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (ncontrollers == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return CAPI_REGNOTINSTALLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if ((ap->applid == 0) || ap->release_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return CAPI_ILLAPPNR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (skb->len < 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * The controller reference is protected by the existence of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * application passed to us. We assume that the caller properly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * synchronizes this service with capi20_release.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (!ctr || ctr->state != CAPI_CTR_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return CAPI_REGNOTINSTALLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (ctr->blocked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return CAPI_SENDQUEUEFULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) cmd = CAPIMSG_COMMAND(skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) subcmd = CAPIMSG_SUBCOMMAND(skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ctr->nsentdatapkt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) ap->nsentdatapkt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (ctr->traceflag > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) showctl |= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ctr->nsentctlpkt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ap->nsentctlpkt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (ctr->traceflag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) showctl |= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) showctl |= (ctr->traceflag & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (showctl & 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (showctl & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) CAPIMSG_CONTROLLER(skb->data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) CAPIMSG_APPID(skb->data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) capi_cmd2str(cmd, subcmd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) CAPIMSG_LEN(skb->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) _cdebbuf *cdb = capi_message2str(skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (cdb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) printk(KERN_DEBUG "kcapi: put [%03d] %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) CAPIMSG_CONTROLLER(skb->data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) cdb->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) cdebbuf_free(cdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) CAPIMSG_CONTROLLER(skb->data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) CAPIMSG_APPID(skb->data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) capi_cmd2str(cmd, subcmd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) CAPIMSG_LEN(skb->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return ctr->send_message(ctr, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * @contr: controller number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * @buf: result buffer (64 bytes).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * Retrieve information about the manufacturer of the specified ISDN controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * or (for @contr == 0) the driver itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * Return value: CAPI result code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) struct capi_ctr *ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) u16 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (contr == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) ctr = get_capi_ctr_by_nr(contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (ctr && ctr->state == CAPI_CTR_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) strncpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ret = CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) ret = CAPI_REGNOTINSTALLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * @contr: controller number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * @verp: result structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * Retrieve version information for the specified ISDN controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * or (for @contr == 0) the driver itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * Return value: CAPI result code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) u16 capi20_get_version(u32 contr, struct capi_version *verp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct capi_ctr *ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) u16 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (contr == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) *verp = driver_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) ctr = get_capi_ctr_by_nr(contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (ctr && ctr->state == CAPI_CTR_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) memcpy(verp, &ctr->version, sizeof(capi_version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ret = CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) ret = CAPI_REGNOTINSTALLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) * @contr: controller number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * @serial: result buffer (8 bytes).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * Retrieve the serial number of the specified ISDN controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * or (for @contr == 0) the driver itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * Return value: CAPI result code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) struct capi_ctr *ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) u16 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (contr == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) strlcpy(serial, driver_serial, CAPI_SERIAL_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ctr = get_capi_ctr_by_nr(contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (ctr && ctr->state == CAPI_CTR_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) ret = CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) ret = CAPI_REGNOTINSTALLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * @contr: controller number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * @profp: result structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * Retrieve capability information for the specified ISDN controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) * or (for @contr == 0) the number of installed controllers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * Return value: CAPI result code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct capi_ctr *ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) u16 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (contr == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) profp->ncontroller = ncontrollers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) ctr = get_capi_ctr_by_nr(contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (ctr && ctr->state == CAPI_CTR_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) memcpy(profp, &ctr->profile, sizeof(struct capi_profile));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ret = CAPI_NOERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) ret = CAPI_REGNOTINSTALLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * @cmd: command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * @data: parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * Perform manufacturer specific command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * Return value: CAPI result code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) int capi20_manufacturer(unsigned long cmd, void __user *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) struct capi_ctr *ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) case KCAPI_CMD_TRACE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) kcapi_flagdef fdef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) mutex_lock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) ctr = get_capi_ctr_by_nr(fdef.contr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (ctr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) ctr->traceflag = fdef.flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) ctr->cnr, ctr->traceflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) retval = -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) mutex_unlock(&capi_controller_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) printk(KERN_ERR "kcapi: manufacturer command %lu unknown.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* ------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) /* -------- Init & Cleanup ------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /* ------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * init / exit functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) int __init kcapi_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) kcapi_wq = alloc_workqueue("kcapi", 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (!kcapi_wq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) err = cdebug_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) destroy_workqueue(kcapi_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) kcapi_proc_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) void kcapi_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) kcapi_proc_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) cdebug_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) destroy_workqueue(kcapi_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }