Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }