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) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * IUCV base infrastructure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Copyright IBM Corp. 2001, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Author(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *    Original source:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *	Alan Altmark (Alan_Altmark@us.ibm.com)	Sept. 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *	Xenia Tkatschow (xenia@us.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *    2Gb awareness and general cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *	Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  *    Rewritten for af_iucv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  *	Martin Schwidefsky <schwidefsky@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *    PM functions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  *	Ursula Braun (ursula.braun@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  * Documentation used:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  *    The original source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  *    CP Programming Service, IBM document # SC24-5760
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #define KMSG_COMPONENT "iucv"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/kernel_stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #include <net/iucv/iucv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #include <asm/ebcdic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #include <asm/smp.h>
^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)  * FLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49)  * All flags are defined in the field IPFLAGS1 of each function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50)  * and can be found in CP Programming Services.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51)  * IPSRCCLS - Indicates you have specified a source class.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52)  * IPTRGCLS - Indicates you have specified a target class.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53)  * IPFGPID  - Indicates you have specified a pathid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54)  * IPFGMID  - Indicates you have specified a message ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55)  * IPNORPY  - Indicates a one-way message. No reply expected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56)  * IPALL    - Indicates that all paths are affected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #define IUCV_IPSRCCLS	0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #define IUCV_IPTRGCLS	0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define IUCV_IPFGPID	0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #define IUCV_IPFGMID	0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define IUCV_IPNORPY	0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define IUCV_IPALL	0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) static int iucv_bus_match(struct device *dev, struct device_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) struct bus_type iucv_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	.name = "iucv",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	.match = iucv_bus_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) EXPORT_SYMBOL(iucv_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) struct device *iucv_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) EXPORT_SYMBOL(iucv_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) static int iucv_available;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) /* General IUCV interrupt structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) struct iucv_irq_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	u8  ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 	u8  iptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 	u32 res2[8];
^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) struct iucv_irq_list {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	struct iucv_irq_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) static struct iucv_irq_data *iucv_irq_data[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) static cpumask_t iucv_buffer_cpumask = { CPU_BITS_NONE };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) static cpumask_t iucv_irq_cpumask = { CPU_BITS_NONE };
^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)  * Queue of interrupt buffers lock for delivery via the tasklet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100)  * (fast but can't call smp_call_function).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) static LIST_HEAD(iucv_task_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)  * The tasklet for fast delivery of iucv interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) static void iucv_tasklet_fn(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) static DECLARE_TASKLET_OLD(iucv_tasklet, iucv_tasklet_fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111)  * Queue of interrupt buffers for delivery via a work queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112)  * (slower but can call smp_call_function).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) static LIST_HEAD(iucv_work_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117)  * The work element to deliver path pending interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) static void iucv_work_fn(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) static DECLARE_WORK(iucv_work, iucv_work_fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123)  * Spinlock protecting task and work queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) static DEFINE_SPINLOCK(iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) enum iucv_command_codes {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 	IUCV_QUERY = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	IUCV_RETRIEVE_BUFFER = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	IUCV_SEND = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	IUCV_RECEIVE = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	IUCV_REPLY = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	IUCV_REJECT = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	IUCV_PURGE = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 	IUCV_ACCEPT = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	IUCV_CONNECT = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	IUCV_DECLARE_BUFFER = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	IUCV_QUIESCE = 13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	IUCV_RESUME = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	IUCV_SEVER = 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	IUCV_SETMASK = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	IUCV_SETCONTROLMASK = 17,
^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)  * Error messages that are used with the iucv_sever function. They get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147)  * converted to EBCDIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) static char iucv_error_no_listener[16] = "NO LISTENER";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) static char iucv_error_no_memory[16] = "NO MEMORY";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) static char iucv_error_pathid[16] = "INVALID PATHID";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154)  * iucv_handler_list: List of registered handlers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) static LIST_HEAD(iucv_handler_list);
^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)  * iucv_path_table: an array of iucv_path structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) static struct iucv_path **iucv_path_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) static unsigned long iucv_max_pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165)  * iucv_lock: spinlock protecting iucv_handler_list and iucv_pathid_table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) static DEFINE_SPINLOCK(iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170)  * iucv_active_cpu: contains the number of the cpu executing the tasklet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171)  * or the work handler. Needed for iucv_path_sever called from tasklet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) static int iucv_active_cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176)  * Mutex and wait queue for iucv_register/iucv_unregister.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) static DEFINE_MUTEX(iucv_register_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181)  * Counter for number of non-smp capable handlers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) static int iucv_nonsmp_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186)  * IUCV control data structure. Used by iucv_path_accept, iucv_path_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187)  * iucv_path_quiesce and iucv_path_sever.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) struct iucv_cmd_control {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	u8  ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	u8  iprcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	u16 ipmsglim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	u16 res1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	u8  ipvmid[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	u8  ipuser[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	u8  iptarget[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) } __attribute__ ((packed,aligned(8)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201)  * Data in parameter list iucv structure. Used by iucv_message_send,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202)  * iucv_message_send2way and iucv_message_reply.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) struct iucv_cmd_dpl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	u8  ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	u8  iprcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	u32 ipmsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	u32 iptrgcls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	u8  iprmmsg[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	u32 ipsrccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	u32 ipmsgtag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	u32 ipbfadr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	u32 ipbfln2f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	u32 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) } __attribute__ ((packed,aligned(8)));
^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)  * Data in buffer iucv structure. Used by iucv_message_receive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220)  * iucv_message_reject, iucv_message_send, iucv_message_send2way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221)  * and iucv_declare_cpu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) struct iucv_cmd_db {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	u8  ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	u8  iprcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	u32 ipmsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	u32 iptrgcls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	u32 ipbfadr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	u32 ipbfln1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	u32 ipsrccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	u32 ipmsgtag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	u32 ipbfadr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	u32 ipbfln2f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	u32 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) } __attribute__ ((packed,aligned(8)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239)  * Purge message iucv structure. Used by iucv_message_purge.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) struct iucv_cmd_purge {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	u8  ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	u8  iprcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	u32 ipmsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	u8  ipaudit[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	u8  res1[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	u32 res2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	u32 ipsrccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	u32 ipmsgtag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	u32 res3[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) } __attribute__ ((packed,aligned(8)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255)  * Set mask iucv structure. Used by iucv_enable_cpu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) struct iucv_cmd_set_mask {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	u8  ipmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	u8  res1[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	u8  iprcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	u32 res2[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) } __attribute__ ((packed,aligned(8)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) union iucv_param {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	struct iucv_cmd_control ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	struct iucv_cmd_dpl dpl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	struct iucv_cmd_db db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	struct iucv_cmd_purge purge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	struct iucv_cmd_set_mask set_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273)  * Anchor for per-cpu IUCV command parameter block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) static union iucv_param *iucv_param[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) static union iucv_param *iucv_param_irq[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279)  * iucv_call_b2f0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280)  * @code: identifier of IUCV call to CP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281)  * @parm: pointer to a struct iucv_parm block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283)  * Calls CP to execute IUCV commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285)  * Returns the result of the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) static inline int __iucv_call_b2f0(int command, union iucv_param *parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	register unsigned long reg0 asm ("0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	register unsigned long reg1 asm ("1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	int ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	reg0 = command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	reg1 = (unsigned long)parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 		"	.long 0xb2f01000\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 		"	ipm	%0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 		"	srl	%0,28\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 		: "=d" (ccode), "=m" (*parm), "+d" (reg0), "+a" (reg1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 		:  "m" (*parm) : "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	return ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) static inline int iucv_call_b2f0(int command, union iucv_param *parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	int ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	ccode = __iucv_call_b2f0(command, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	return ccode == 1 ? parm->ctrl.iprcode : ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313)  * iucv_query_maxconn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315)  * Determines the maximum number of connections that may be established.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317)  * Returns the maximum number of connections or -EPERM is IUCV is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318)  * available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) static int __iucv_query_maxconn(void *param, unsigned long *max_pathid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	register unsigned long reg0 asm ("0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	register unsigned long reg1 asm ("1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	int ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	reg0 = IUCV_QUERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	reg1 = (unsigned long) param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	asm volatile (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 		"	.long	0xb2f01000\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 		"	ipm	%0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 		"	srl	%0,28\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 		: "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	*max_pathid = reg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	return ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) static int iucv_query_maxconn(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	unsigned long max_pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	void *param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	int ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	param = kzalloc(sizeof(union iucv_param), GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	if (!param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	ccode = __iucv_query_maxconn(param, &max_pathid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	if (ccode == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		iucv_max_pathid = max_pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	kfree(param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	return ccode ? -EPERM : 0;
^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)  * iucv_allow_cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355)  * @data: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357)  * Allow iucv interrupts on this cpu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) static void iucv_allow_cpu(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	int cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	 * Enable all iucv interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	 * ipmask contains bits for the different interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	 *	0x80 - Flag to allow nonpriority message pending interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	 *	0x40 - Flag to allow priority message pending interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	 *	0x20 - Flag to allow nonpriority message completion interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	 *	0x10 - Flag to allow priority message completion interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	 *	0x08 - Flag to allow IUCV control interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	parm = iucv_param_irq[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	parm->set_mask.ipmask = 0xf8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	iucv_call_b2f0(IUCV_SETMASK, parm);
^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) 	 * Enable all iucv control interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	 * ipmask contains bits for the different interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	 *	0x80 - Flag to allow pending connections interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	 *	0x40 - Flag to allow connection complete interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	 *	0x20 - Flag to allow connection severed interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	 *	0x10 - Flag to allow connection quiesced interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	 *	0x08 - Flag to allow connection resumed interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	parm->set_mask.ipmask = 0xf8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	iucv_call_b2f0(IUCV_SETCONTROLMASK, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	/* Set indication that iucv interrupts are allowed for this cpu. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	cpumask_set_cpu(cpu, &iucv_irq_cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395)  * iucv_block_cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396)  * @data: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398)  * Block iucv interrupts on this cpu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) static void iucv_block_cpu(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	int cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	/* Disable all iucv interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	parm = iucv_param_irq[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	iucv_call_b2f0(IUCV_SETMASK, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	/* Clear indication that iucv interrupts are allowed for this cpu. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	cpumask_clear_cpu(cpu, &iucv_irq_cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415)  * iucv_declare_cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416)  * @data: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418)  * Declare a interrupt buffer on this cpu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) static void iucv_declare_cpu(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	int cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	if (cpumask_test_cpu(cpu, &iucv_buffer_cpumask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	/* Declare interrupt buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	parm = iucv_param_irq[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 		char *err = "Unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		switch (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 		case 0x03:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 			err = "Directory error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		case 0x0a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 			err = "Invalid length";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		case 0x13:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 			err = "Buffer already exists";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		case 0x3e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 			err = "Buffer overlap";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		case 0x5c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 			err = "Paging or storage error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		pr_warn("Defining an interrupt buffer on CPU %i failed with 0x%02x (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 			cpu, rc, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	/* Set indication that an iucv buffer exists for this cpu. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	cpumask_set_cpu(cpu, &iucv_buffer_cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	if (iucv_nonsmp_handler == 0 || cpumask_empty(&iucv_irq_cpumask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		/* Enable iucv interrupts on this cpu. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		iucv_allow_cpu(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		/* Disable iucv interrupts on this cpu. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		iucv_block_cpu(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470)  * iucv_retrieve_cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471)  * @data: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473)  * Retrieve interrupt buffer on this cpu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) static void iucv_retrieve_cpu(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	int cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	if (!cpumask_test_cpu(cpu, &iucv_buffer_cpumask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	/* Block iucv interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	iucv_block_cpu(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	/* Retrieve interrupt buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	parm = iucv_param_irq[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	/* Clear indication that an iucv buffer exists for this cpu. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	cpumask_clear_cpu(cpu, &iucv_buffer_cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495)  * iucv_setmask_smp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497)  * Allow iucv interrupts on all cpus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) static void iucv_setmask_mp(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	for_each_online_cpu(cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		/* Enable all cpus with a declared buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 		if (cpumask_test_cpu(cpu, &iucv_buffer_cpumask) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 		    !cpumask_test_cpu(cpu, &iucv_irq_cpumask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 			smp_call_function_single(cpu, iucv_allow_cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 						 NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	put_online_cpus();
^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)  * iucv_setmask_up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516)  * Allow iucv interrupts on a single cpu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) static void iucv_setmask_up(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	cpumask_t cpumask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	/* Disable all cpu but the first in cpu_irq_cpumask. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	cpumask_copy(&cpumask, &iucv_irq_cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	cpumask_clear_cpu(cpumask_first(&iucv_irq_cpumask), &cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	for_each_cpu(cpu, &cpumask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 		smp_call_function_single(cpu, iucv_block_cpu, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531)  * iucv_enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533)  * This function makes iucv ready for use. It allocates the pathid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534)  * table, declares an iucv interrupt buffer and enables the iucv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535)  * interrupts. Called when the first user has registered an iucv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536)  * handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) static int iucv_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	size_t alloc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	int cpu, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	alloc_size = iucv_max_pathid * sizeof(struct iucv_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	iucv_path_table = kzalloc(alloc_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	if (!iucv_path_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	/* Declare per cpu buffers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	for_each_online_cpu(cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 		smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	if (cpumask_empty(&iucv_buffer_cpumask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 		/* No cpu could declare an iucv buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	kfree(iucv_path_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	iucv_path_table = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566)  * iucv_disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568)  * This function shuts down iucv. It disables iucv interrupts, retrieves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569)  * the iucv interrupt buffer and frees the pathid table. Called after the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570)  * last user unregister its iucv handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) static void iucv_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	on_each_cpu(iucv_retrieve_cpu, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	kfree(iucv_path_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	iucv_path_table = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	put_online_cpus();
^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) static int iucv_cpu_dead(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	kfree(iucv_param_irq[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	iucv_param_irq[cpu] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	kfree(iucv_param[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	iucv_param[cpu] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	kfree(iucv_irq_data[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	iucv_irq_data[cpu] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) static int iucv_cpu_prepare(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	/* Note: GFP_DMA used to get memory below 2G */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 			     GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	if (!iucv_irq_data[cpu])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 	/* Allocate parameter blocks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 			  GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	if (!iucv_param[cpu])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 			  GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	if (!iucv_param_irq[cpu])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	iucv_cpu_dead(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) static int iucv_cpu_online(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	if (!iucv_path_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	iucv_declare_cpu(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) static int iucv_cpu_down_prep(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	cpumask_t cpumask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	if (!iucv_path_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	cpumask_copy(&cpumask, &iucv_buffer_cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	cpumask_clear_cpu(cpu, &cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	if (cpumask_empty(&cpumask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 		/* Can't offline last IUCV enabled cpu. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	iucv_retrieve_cpu(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	if (!cpumask_empty(&iucv_irq_cpumask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	smp_call_function_single(cpumask_first(&iucv_buffer_cpumask),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 				 iucv_allow_cpu, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648)  * iucv_sever_pathid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649)  * @pathid: path identification number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650)  * @userdata: 16-bytes of user data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652)  * Sever an iucv path to free up the pathid. Used internally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) static int iucv_sever_pathid(u16 pathid, u8 *userdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	parm = iucv_param_irq[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	if (userdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	parm->ctrl.ippathid = pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	return iucv_call_b2f0(IUCV_SEVER, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667)  * __iucv_cleanup_queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668)  * @dummy: unused dummy argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670)  * Nop function called via smp_call_function to force work items from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671)  * pending external iucv interrupts to the work queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) static void __iucv_cleanup_queue(void *dummy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678)  * iucv_cleanup_queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680)  * Function called after a path has been severed to find all remaining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681)  * work items for the now stale pathid. The caller needs to hold the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682)  * iucv_table_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) static void iucv_cleanup_queue(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	struct iucv_irq_list *p, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	 * When a path is severed, the pathid can be reused immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	 * on a iucv connect or a connection pending interrupt. Remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	 * all entries from the task queue that refer to a stale pathid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	 * (iucv_path_table[ix] == NULL). Only then do the iucv connect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	 * or deliver the connection pending interrupt. To get all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	 * pending interrupts force them to the work queue by calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	 * an empty function on all cpus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	smp_call_function(__iucv_cleanup_queue, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	spin_lock_irq(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	list_for_each_entry_safe(p, n, &iucv_task_queue, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		/* Remove stale work items from the task queue. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		if (iucv_path_table[p->data.ippathid] == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 			list_del(&p->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 			kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	spin_unlock_irq(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710)  * iucv_register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711)  * @handler: address of iucv handler structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712)  * @smp: != 0 indicates that the handler can deal with out of order messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714)  * Registers a driver with IUCV.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716)  * Returns 0 on success, -ENOMEM if the memory allocation for the pathid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717)  * table failed, or -EIO if IUCV_DECLARE_BUFFER failed on all cpus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) int iucv_register(struct iucv_handler *handler, int smp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	if (!iucv_available)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 		return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	mutex_lock(&iucv_register_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	if (!smp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		iucv_nonsmp_handler++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	if (list_empty(&iucv_handler_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 		rc = iucv_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 			goto out_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	} else if (!smp && iucv_nonsmp_handler == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 		iucv_setmask_up();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	INIT_LIST_HEAD(&handler->paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	spin_lock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	list_add_tail(&handler->list, &iucv_handler_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	spin_unlock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) out_mutex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	mutex_unlock(&iucv_register_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) EXPORT_SYMBOL(iucv_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747)  * iucv_unregister
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748)  * @handler:  address of iucv handler structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749)  * @smp: != 0 indicates that the handler can deal with out of order messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751)  * Unregister driver from IUCV.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) void iucv_unregister(struct iucv_handler *handler, int smp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	struct iucv_path *p, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	mutex_lock(&iucv_register_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	spin_lock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	/* Remove handler from the iucv_handler_list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	list_del_init(&handler->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	/* Sever all pathids still referring to the handler. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	list_for_each_entry_safe(p, n, &handler->paths, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 		iucv_sever_pathid(p->pathid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 		iucv_path_table[p->pathid] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 		list_del(&p->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 		iucv_path_free(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	spin_unlock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	if (!smp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		iucv_nonsmp_handler--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	if (list_empty(&iucv_handler_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 		iucv_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	else if (!smp && iucv_nonsmp_handler == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 		iucv_setmask_mp();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	mutex_unlock(&iucv_register_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) EXPORT_SYMBOL(iucv_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) static int iucv_reboot_event(struct notifier_block *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 			     unsigned long event, void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	if (cpumask_empty(&iucv_irq_cpumask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 		return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	on_each_cpu_mask(&iucv_irq_cpumask, iucv_block_cpu, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	for (i = 0; i < iucv_max_pathid; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 		if (iucv_path_table[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 			iucv_sever_pathid(i, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	iucv_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) static struct notifier_block iucv_reboot_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	.notifier_call = iucv_reboot_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) };
^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)  * iucv_path_accept
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807)  * @handler: address of iucv handler structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808)  * @userdata: 16 bytes of data reflected to the communication partner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809)  * @private: private data passed to interrupt handlers for this path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811)  * This function is issued after the user received a connection pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812)  * external interrupt and now wishes to complete the IUCV communication path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814)  * Returns the result of the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 		     u8 *userdata, void *private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	/* Prepare parameter block. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	parm->ctrl.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	parm->ctrl.ipmsglim = path->msglim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	if (userdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	parm->ctrl.ipflags1 = path->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	rc = iucv_call_b2f0(IUCV_ACCEPT, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		path->private = private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 		path->msglim = parm->ctrl.ipmsglim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 		path->flags = parm->ctrl.ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) EXPORT_SYMBOL(iucv_path_accept);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849)  * iucv_path_connect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851)  * @handler: address of iucv handler structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852)  * @userid: 8-byte user identification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853)  * @system: 8-byte target system identification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854)  * @userdata: 16 bytes of data reflected to the communication partner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855)  * @private: private data passed to interrupt handlers for this path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857)  * This function establishes an IUCV path. Although the connect may complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858)  * successfully, you are not able to use the path until you receive an IUCV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859)  * Connection Complete external interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861)  * Returns the result of the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 		      u8 *userid, u8 *system, u8 *userdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 		      void *private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	spin_lock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	iucv_cleanup_queue();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	parm->ctrl.ipmsglim = path->msglim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	parm->ctrl.ipflags1 = path->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	if (userid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		memcpy(parm->ctrl.ipvmid, userid, sizeof(parm->ctrl.ipvmid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 		ASCEBC(parm->ctrl.ipvmid, sizeof(parm->ctrl.ipvmid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		EBC_TOUPPER(parm->ctrl.ipvmid, sizeof(parm->ctrl.ipvmid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	if (system) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		memcpy(parm->ctrl.iptarget, system,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 		       sizeof(parm->ctrl.iptarget));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		ASCEBC(parm->ctrl.iptarget, sizeof(parm->ctrl.iptarget));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 		EBC_TOUPPER(parm->ctrl.iptarget, sizeof(parm->ctrl.iptarget));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	if (userdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	rc = iucv_call_b2f0(IUCV_CONNECT, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 		if (parm->ctrl.ippathid < iucv_max_pathid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 			path->pathid = parm->ctrl.ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 			path->msglim = parm->ctrl.ipmsglim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 			path->flags = parm->ctrl.ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 			path->handler = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 			path->private = private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 			list_add_tail(&path->list, &handler->paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 			iucv_path_table[path->pathid] = path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 			iucv_sever_pathid(parm->ctrl.ippathid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 					  iucv_error_pathid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 			rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	spin_unlock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) EXPORT_SYMBOL(iucv_path_connect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917)  * iucv_path_quiesce:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919)  * @userdata: 16 bytes of data reflected to the communication partner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921)  * This function temporarily suspends incoming messages on an IUCV path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922)  * You can later reactivate the path by invoking the iucv_resume function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) int iucv_path_quiesce(struct iucv_path *path, u8 *userdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	if (userdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	parm->ctrl.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	rc = iucv_call_b2f0(IUCV_QUIESCE, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) EXPORT_SYMBOL(iucv_path_quiesce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949)  * iucv_path_resume:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951)  * @userdata: 16 bytes of data reflected to the communication partner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953)  * This function resumes incoming messages on an IUCV path that has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954)  * been stopped with iucv_path_quiesce.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) int iucv_path_resume(struct iucv_path *path, u8 *userdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	if (userdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	parm->ctrl.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	rc = iucv_call_b2f0(IUCV_RESUME, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980)  * iucv_path_sever
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982)  * @userdata: 16 bytes of data reflected to the communication partner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984)  * This function terminates an IUCV path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) int iucv_path_sever(struct iucv_path *path, u8 *userdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	if (iucv_active_cpu != smp_processor_id())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		spin_lock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	rc = iucv_sever_pathid(path->pathid, userdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	iucv_path_table[path->pathid] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	list_del_init(&path->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	if (iucv_active_cpu != smp_processor_id())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 		spin_unlock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) EXPORT_SYMBOL(iucv_path_sever);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)  * iucv_message_purge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)  * @msg: address of iucv msg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)  * @srccls: source class of message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)  * Cancels a message you have sent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 		       u32 srccls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	parm->purge.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	parm->purge.ipmsgid = msg->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	parm->purge.ipsrccls = srccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	parm->purge.ipflags1 = IUCV_IPSRCCLS | IUCV_IPFGMID | IUCV_IPFGPID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	rc = iucv_call_b2f0(IUCV_PURGE, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 		msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 		msg->tag = parm->purge.ipmsgtag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) EXPORT_SYMBOL(iucv_message_purge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)  * iucv_message_receive_iprmdata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)  * @msg: address of iucv msg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)  * @flags: how the message is received (IUCV_IPBUFLST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)  * @buffer: address of data buffer or address of struct iucv_array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)  * @size: length of data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)  * @residual:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)  * Internal function used by iucv_message_receive and __iucv_message_receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)  * to receive RMDATA data stored in struct iucv_message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) static int iucv_message_receive_iprmdata(struct iucv_path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 					 struct iucv_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 					 u8 flags, void *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 					 size_t size, size_t *residual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	struct iucv_array *array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	u8 *rmmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	size_t copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 	 * Message is 8 bytes long and has been stored to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	 * message descriptor itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 	if (residual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 		*residual = abs(size - 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	rmmsg = msg->rmmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	if (flags & IUCV_IPBUFLST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 		/* Copy to struct iucv_array. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 		size = (size < 8) ? size : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 		for (array = buffer; size > 0; array++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 			copy = min_t(size_t, size, array->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 			memcpy((u8 *)(addr_t) array->address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 				rmmsg, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 			rmmsg += copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 			size -= copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 		/* Copy to direct buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 		memcpy(buffer, rmmsg, min_t(size_t, size, 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)  * __iucv_message_receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)  * @msg: address of iucv msg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)  * @flags: how the message is received (IUCV_IPBUFLST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)  * @buffer: address of data buffer or address of struct iucv_array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)  * @size: length of data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)  * @residual:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)  * This function receives messages that are being sent to you over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)  * established paths. This function will deal with RMDATA messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)  * embedded in struct iucv_message as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)  * Locking:	no locking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 			   u8 flags, void *buffer, size_t size, size_t *residual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	if (msg->flags & IUCV_IPRMDATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 		return iucv_message_receive_iprmdata(path, msg, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 						     buffer, size, residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	if (cpumask_empty(&iucv_buffer_cpumask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	parm->db.ipbfadr1 = (u32)(addr_t) buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 	parm->db.ipbfln1f = (u32) size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	parm->db.ipmsgid = msg->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	parm->db.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	parm->db.iptrgcls = msg->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	parm->db.ipflags1 = (flags | IUCV_IPFGPID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 			     IUCV_IPFGMID | IUCV_IPTRGCLS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 	rc = iucv_call_b2f0(IUCV_RECEIVE, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	if (!rc || rc == 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 		msg->flags = parm->db.ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 		if (residual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 			*residual = parm->db.ipbfln1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) EXPORT_SYMBOL(__iucv_message_receive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)  * iucv_message_receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)  * @msg: address of iucv msg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)  * @flags: how the message is received (IUCV_IPBUFLST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)  * @buffer: address of data buffer or address of struct iucv_array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)  * @size: length of data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)  * @residual:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)  * This function receives messages that are being sent to you over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)  * established paths. This function will deal with RMDATA messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)  * embedded in struct iucv_message as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)  * Locking:	local_bh_enable/local_bh_disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 			 u8 flags, void *buffer, size_t size, size_t *residual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	if (msg->flags & IUCV_IPRMDATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 		return iucv_message_receive_iprmdata(path, msg, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 						     buffer, size, residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	rc = __iucv_message_receive(path, msg, flags, buffer, size, residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) EXPORT_SYMBOL(iucv_message_receive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)  * iucv_message_reject
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)  * @msg: address of iucv msg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)  * The reject function refuses a specified message. Between the time you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)  * are notified of a message and the time that you complete the message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)  * the message may be rejected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	parm->db.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	parm->db.ipmsgid = msg->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	parm->db.iptrgcls = msg->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	rc = iucv_call_b2f0(IUCV_REJECT, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 	local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) EXPORT_SYMBOL(iucv_message_reject);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)  * iucv_message_reply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)  * @msg: address of iucv msg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)  * @flags: how the reply is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)  * @reply: address of reply data buffer or address of struct iucv_array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)  * @size: length of reply data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)  * This function responds to the two-way messages that you receive. You
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)  * must identify completely the message to which you wish to reply. ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)  * pathid, msgid, and trgcls. Prmmsg signifies the data is moved into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)  * the parameter list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 		       u8 flags, void *reply, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 	if (flags & IUCV_IPRMDATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 		parm->dpl.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 		parm->dpl.ipflags1 = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 		parm->dpl.ipmsgid = msg->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 		parm->dpl.iptrgcls = msg->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 		memcpy(parm->dpl.iprmmsg, reply, min_t(size_t, size, 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 		parm->db.ipbfadr1 = (u32)(addr_t) reply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 		parm->db.ipbfln1f = (u32) size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 		parm->db.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 		parm->db.ipflags1 = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 		parm->db.ipmsgid = msg->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 		parm->db.iptrgcls = msg->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	rc = iucv_call_b2f0(IUCV_REPLY, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 	local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) EXPORT_SYMBOL(iucv_message_reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)  * __iucv_message_send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)  * @msg: address of iucv msg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)  * @flags: how the message is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)  * @srccls: source class of message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)  * @buffer: address of send buffer or address of struct iucv_array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)  * @size: length of send buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)  * This function transmits data to another application. Data to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)  * transmitted is in a buffer and this is a one-way message and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)  * receiver will not reply to the message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)  * Locking:	no locking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 		      u8 flags, u32 srccls, void *buffer, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 	if (flags & IUCV_IPRMDATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 		/* Message of 8 bytes can be placed into the parameter list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 		parm->dpl.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 		parm->dpl.ipflags1 = flags | IUCV_IPNORPY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 		parm->dpl.iptrgcls = msg->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 		parm->dpl.ipsrccls = srccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 		parm->dpl.ipmsgtag = msg->tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 		memcpy(parm->dpl.iprmmsg, buffer, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 		parm->db.ipbfadr1 = (u32)(addr_t) buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 		parm->db.ipbfln1f = (u32) size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 		parm->db.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 		parm->db.ipflags1 = flags | IUCV_IPNORPY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 		parm->db.iptrgcls = msg->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 		parm->db.ipsrccls = srccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 		parm->db.ipmsgtag = msg->tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	rc = iucv_call_b2f0(IUCV_SEND, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 		msg->id = parm->db.ipmsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) EXPORT_SYMBOL(__iucv_message_send);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)  * iucv_message_send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)  * @msg: address of iucv msg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)  * @flags: how the message is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)  * @srccls: source class of message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)  * @buffer: address of send buffer or address of struct iucv_array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)  * @size: length of send buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)  * This function transmits data to another application. Data to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)  * transmitted is in a buffer and this is a one-way message and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)  * receiver will not reply to the message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)  * Locking:	local_bh_enable/local_bh_disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) int iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 		      u8 flags, u32 srccls, void *buffer, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 	local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	rc = __iucv_message_send(path, msg, flags, srccls, buffer, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 	local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) EXPORT_SYMBOL(iucv_message_send);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)  * iucv_message_send2way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)  * @path: address of iucv path structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)  * @msg: address of iucv msg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)  * @flags: how the message is sent and the reply is received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)  *	   (IUCV_IPRMDATA, IUCV_IPBUFLST, IUCV_IPPRTY, IUCV_ANSLST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)  * @srccls: source class of message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)  * @buffer: address of send buffer or address of struct iucv_array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)  * @size: length of send buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)  * @ansbuf: address of answer buffer or address of struct iucv_array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)  * @asize: size of reply buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)  * This function transmits data to another application. Data to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)  * transmitted is in a buffer. The receiver of the send is expected to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)  * reply to the message and a buffer is provided into which IUCV moves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)  * the reply to this message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)  * Returns the result from the CP IUCV call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 			  u8 flags, u32 srccls, void *buffer, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 			  void *answer, size_t asize, size_t *residual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 	union iucv_param *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 	local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 	if (cpumask_empty(&iucv_buffer_cpumask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 	parm = iucv_param[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 	memset(parm, 0, sizeof(union iucv_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 	if (flags & IUCV_IPRMDATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 		parm->dpl.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 		parm->dpl.ipflags1 = path->flags;	/* priority message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 		parm->dpl.iptrgcls = msg->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 		parm->dpl.ipsrccls = srccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 		parm->dpl.ipmsgtag = msg->tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 		parm->dpl.ipbfadr2 = (u32)(addr_t) answer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 		parm->dpl.ipbfln2f = (u32) asize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 		memcpy(parm->dpl.iprmmsg, buffer, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 		parm->db.ippathid = path->pathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 		parm->db.ipflags1 = path->flags;	/* priority message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 		parm->db.iptrgcls = msg->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 		parm->db.ipsrccls = srccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 		parm->db.ipmsgtag = msg->tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 		parm->db.ipbfadr1 = (u32)(addr_t) buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 		parm->db.ipbfln1f = (u32) size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 		parm->db.ipbfadr2 = (u32)(addr_t) answer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 		parm->db.ipbfln2f = (u32) asize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	rc = iucv_call_b2f0(IUCV_SEND, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 		msg->id = parm->db.ipmsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 	local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) EXPORT_SYMBOL(iucv_message_send2way);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)  * iucv_path_pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)  * @data: Pointer to external interrupt buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)  * Process connection pending work item. Called from tasklet while holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)  * iucv_table_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) struct iucv_path_pending {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 	u8  ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 	u8  iptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 	u16 ipmsglim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 	u16 res1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 	u8  ipvmid[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 	u8  ipuser[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 	u32 res3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	u8  ippollfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 	u8  res4[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) static void iucv_path_pending(struct iucv_irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 	struct iucv_path_pending *ipp = (void *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 	struct iucv_handler *handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 	struct iucv_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	char *error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 	BUG_ON(iucv_path_table[ipp->ippathid]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 	/* New pathid, handler found. Create a new path struct. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 	error = iucv_error_no_memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 	path = iucv_path_alloc(ipp->ipmsglim, ipp->ipflags1, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 		goto out_sever;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 	path->pathid = ipp->ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 	iucv_path_table[path->pathid] = path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 	EBCASC(ipp->ipvmid, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 	/* Call registered handler until one is found that wants the path. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 	list_for_each_entry(handler, &iucv_handler_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 		if (!handler->path_pending)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 		 * Add path to handler to allow a call to iucv_path_sever
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 		 * inside the path_pending function. If the handler returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 		 * an error remove the path from the handler again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 		list_add(&path->list, &handler->paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 		path->handler = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 		if (!handler->path_pending(path, ipp->ipvmid, ipp->ipuser))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 		list_del(&path->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 		path->handler = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 	/* No handler wanted the path. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 	iucv_path_table[path->pathid] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 	iucv_path_free(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 	error = iucv_error_no_listener;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) out_sever:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 	iucv_sever_pathid(ipp->ippathid, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)  * iucv_path_complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)  * @data: Pointer to external interrupt buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)  * Process connection complete work item. Called from tasklet while holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)  * iucv_table_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) struct iucv_path_complete {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 	u8  ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 	u8  iptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 	u16 ipmsglim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 	u16 res1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 	u8  res2[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 	u8  ipuser[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 	u32 res3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 	u8  ippollfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 	u8  res4[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) static void iucv_path_complete(struct iucv_irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 	struct iucv_path_complete *ipc = (void *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 	struct iucv_path *path = iucv_path_table[ipc->ippathid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 	if (path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 		path->flags = ipc->ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 	if (path && path->handler && path->handler->path_complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 		path->handler->path_complete(path, ipc->ipuser);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)  * iucv_path_severed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)  * @data: Pointer to external interrupt buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)  * Process connection severed work item. Called from tasklet while holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)  * iucv_table_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) struct iucv_path_severed {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 	u8  res1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 	u8  iptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	u32 res2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 	u8  res3[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 	u8  ipuser[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	u32 res4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 	u8  ippollfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 	u8  res5[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) static void iucv_path_severed(struct iucv_irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 	struct iucv_path_severed *ips = (void *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 	struct iucv_path *path = iucv_path_table[ips->ippathid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 	if (!path || !path->handler)	/* Already severed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	if (path->handler->path_severed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 		path->handler->path_severed(path, ips->ipuser);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 		iucv_sever_pathid(path->pathid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 		iucv_path_table[path->pathid] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 		list_del(&path->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 		iucv_path_free(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)  * iucv_path_quiesced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)  * @data: Pointer to external interrupt buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)  * Process connection quiesced work item. Called from tasklet while holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)  * iucv_table_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) struct iucv_path_quiesced {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 	u8  res1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 	u8  iptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 	u32 res2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 	u8  res3[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) 	u8  ipuser[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 	u32 res4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) 	u8  ippollfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) 	u8  res5[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) static void iucv_path_quiesced(struct iucv_irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 	struct iucv_path_quiesced *ipq = (void *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 	struct iucv_path *path = iucv_path_table[ipq->ippathid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 	if (path && path->handler && path->handler->path_quiesced)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 		path->handler->path_quiesced(path, ipq->ipuser);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)  * iucv_path_resumed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)  * @data: Pointer to external interrupt buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)  * Process connection resumed work item. Called from tasklet while holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)  * iucv_table_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) struct iucv_path_resumed {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 	u8  res1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 	u8  iptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) 	u32 res2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) 	u8  res3[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 	u8  ipuser[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 	u32 res4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) 	u8  ippollfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 	u8  res5[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) static void iucv_path_resumed(struct iucv_irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 	struct iucv_path_resumed *ipr = (void *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 	struct iucv_path *path = iucv_path_table[ipr->ippathid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 	if (path && path->handler && path->handler->path_resumed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) 		path->handler->path_resumed(path, ipr->ipuser);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)  * iucv_message_complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)  * @data: Pointer to external interrupt buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)  * Process message complete work item. Called from tasklet while holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)  * iucv_table_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) struct iucv_message_complete {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) 	u8  ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 	u8  iptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) 	u32 ipmsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 	u32 ipaudit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 	u8  iprmmsg[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 	u32 ipsrccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 	u32 ipmsgtag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 	u32 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 	u32 ipbfln2f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 	u8  ippollfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 	u8  res2[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) static void iucv_message_complete(struct iucv_irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 	struct iucv_message_complete *imc = (void *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 	struct iucv_path *path = iucv_path_table[imc->ippathid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 	struct iucv_message msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 	if (path && path->handler && path->handler->message_complete) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 		msg.flags = imc->ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 		msg.id = imc->ipmsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) 		msg.audit = imc->ipaudit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 		memcpy(msg.rmmsg, imc->iprmmsg, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 		msg.class = imc->ipsrccls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 		msg.tag = imc->ipmsgtag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 		msg.length = imc->ipbfln2f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 		path->handler->message_complete(path, &msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)  * iucv_message_pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)  * @data: Pointer to external interrupt buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)  * Process message pending work item. Called from tasklet while holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)  * iucv_table_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) struct iucv_message_pending {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 	u16 ippathid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 	u8  ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 	u8  iptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 	u32 ipmsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	u32 iptrgcls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 	union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 		u32 iprmmsg1_u32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 		u8  iprmmsg1[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 	} ln1msg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 	union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 		u32 ipbfln1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 		u8  iprmmsg2[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 	} ln1msg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 	u32 res1[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 	u32 ipbfln2f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 	u8  ippollfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 	u8  res2[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) static void iucv_message_pending(struct iucv_irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) 	struct iucv_message_pending *imp = (void *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 	struct iucv_path *path = iucv_path_table[imp->ippathid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) 	struct iucv_message msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 	if (path && path->handler && path->handler->message_pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 		msg.flags = imp->ipflags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 		msg.id = imp->ipmsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 		msg.class = imp->iptrgcls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 		if (imp->ipflags1 & IUCV_IPRMDATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 			memcpy(msg.rmmsg, imp->ln1msg1.iprmmsg1, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 			msg.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 			msg.length = imp->ln1msg2.ipbfln1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 		msg.reply_size = imp->ipbfln2f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 		path->handler->message_pending(path, &msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)  * iucv_tasklet_fn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)  * This tasklet loops over the queue of irq buffers created by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)  * iucv_external_interrupt, calls the appropriate action handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677)  * and then frees the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) static void iucv_tasklet_fn(unsigned long ignored)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 	typedef void iucv_irq_fn(struct iucv_irq_data *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) 	static iucv_irq_fn *irq_fn[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) 		[0x02] = iucv_path_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) 		[0x03] = iucv_path_severed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 		[0x04] = iucv_path_quiesced,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) 		[0x05] = iucv_path_resumed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) 		[0x06] = iucv_message_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 		[0x07] = iucv_message_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) 		[0x08] = iucv_message_pending,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 		[0x09] = iucv_message_pending,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 	LIST_HEAD(task_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) 	struct iucv_irq_list *p, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 	/* Serialize tasklet, iucv_path_sever and iucv_path_connect. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 	if (!spin_trylock(&iucv_table_lock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 		tasklet_schedule(&iucv_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 	iucv_active_cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 	spin_lock_irq(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 	list_splice_init(&iucv_task_queue, &task_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) 	spin_unlock_irq(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) 	list_for_each_entry_safe(p, n, &task_queue, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 		list_del_init(&p->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 		irq_fn[p->data.iptype](&p->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 	iucv_active_cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 	spin_unlock(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)  * iucv_work_fn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)  * This work function loops over the queue of path pending irq blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)  * created by iucv_external_interrupt, calls the appropriate action
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)  * handler and then frees the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) static void iucv_work_fn(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) 	LIST_HEAD(work_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 	struct iucv_irq_list *p, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 	/* Serialize tasklet, iucv_path_sever and iucv_path_connect. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 	spin_lock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 	iucv_active_cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 	spin_lock_irq(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 	list_splice_init(&iucv_work_queue, &work_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 	spin_unlock_irq(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 	iucv_cleanup_queue();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 	list_for_each_entry_safe(p, n, &work_queue, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 		list_del_init(&p->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 		iucv_path_pending(&p->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) 	iucv_active_cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 	spin_unlock_bh(&iucv_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)  * iucv_external_interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)  * @code: irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)  * Handles external interrupts coming in from CP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)  * Places the interrupt buffer on a queue and schedules iucv_tasklet_fn().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) static void iucv_external_interrupt(struct ext_code ext_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 				    unsigned int param32, unsigned long param64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) 	struct iucv_irq_data *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) 	struct iucv_irq_list *work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 	inc_irq_stat(IRQEXT_IUC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 	p = iucv_irq_data[smp_processor_id()];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 	if (p->ippathid >= iucv_max_pathid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 		WARN_ON(p->ippathid >= iucv_max_pathid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 		iucv_sever_pathid(p->ippathid, iucv_error_no_listener);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 	BUG_ON(p->iptype  < 0x01 || p->iptype > 0x09);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 	work = kmalloc(sizeof(struct iucv_irq_list), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 	if (!work) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 		pr_warn("iucv_external_interrupt: out of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 	memcpy(&work->data, p, sizeof(work->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 	spin_lock(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 	if (p->iptype == 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) 		/* Path pending interrupt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 		list_add_tail(&work->list, &iucv_work_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 		schedule_work(&iucv_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 		/* The other interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 		list_add_tail(&work->list, &iucv_task_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 		tasklet_schedule(&iucv_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 	spin_unlock(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) struct iucv_interface iucv_if = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 	.message_receive = iucv_message_receive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 	.__message_receive = __iucv_message_receive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 	.message_reply = iucv_message_reply,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 	.message_reject = iucv_message_reject,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 	.message_send = iucv_message_send,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 	.__message_send = __iucv_message_send,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 	.message_send2way = iucv_message_send2way,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) 	.message_purge = iucv_message_purge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 	.path_accept = iucv_path_accept,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) 	.path_connect = iucv_path_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) 	.path_quiesce = iucv_path_quiesce,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) 	.path_resume = iucv_path_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 	.path_sever = iucv_path_sever,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 	.iucv_register = iucv_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 	.iucv_unregister = iucv_unregister,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 	.bus = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 	.root = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) EXPORT_SYMBOL(iucv_if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) static enum cpuhp_state iucv_online;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)  * iucv_init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)  * Allocates and initializes various data structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) static int __init iucv_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 	if (!MACHINE_IS_VM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 		rc = -EPROTONOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 	ctl_set_bit(0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 	rc = iucv_query_maxconn();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) 		goto out_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) 	rc = register_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) 		goto out_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) 	iucv_root = root_device_register("iucv");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) 	if (IS_ERR(iucv_root)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) 		rc = PTR_ERR(iucv_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) 		goto out_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 	rc = cpuhp_setup_state(CPUHP_NET_IUCV_PREPARE, "net/iucv:prepare",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) 			       iucv_cpu_prepare, iucv_cpu_dead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) 		goto out_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 	rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "net/iucv:online",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 			       iucv_cpu_online, iucv_cpu_down_prep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) 	if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 		goto out_prep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) 	iucv_online = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) 	rc = register_reboot_notifier(&iucv_reboot_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) 		goto out_remove_hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) 	ASCEBC(iucv_error_no_listener, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) 	ASCEBC(iucv_error_no_memory, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) 	ASCEBC(iucv_error_pathid, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) 	iucv_available = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) 	rc = bus_register(&iucv_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) 		goto out_reboot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) 	iucv_if.root = iucv_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) 	iucv_if.bus = &iucv_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) out_reboot:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) 	unregister_reboot_notifier(&iucv_reboot_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) out_remove_hp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) 	cpuhp_remove_state(iucv_online);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) out_prep:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) 	cpuhp_remove_state(CPUHP_NET_IUCV_PREPARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) out_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) 	root_device_unregister(iucv_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) out_int:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) 	unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) out_ctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) 	ctl_clear_bit(0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876)  * iucv_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878)  * Frees everything allocated from iucv_init.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) static void __exit iucv_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) 	struct iucv_irq_list *p, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) 	spin_lock_irq(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) 	list_for_each_entry_safe(p, n, &iucv_task_queue, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) 	list_for_each_entry_safe(p, n, &iucv_work_queue, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) 	spin_unlock_irq(&iucv_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) 	unregister_reboot_notifier(&iucv_reboot_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) 	cpuhp_remove_state_nocalls(iucv_online);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) 	cpuhp_remove_state(CPUHP_NET_IUCV_PREPARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) 	root_device_unregister(iucv_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) 	bus_unregister(&iucv_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) 	unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) subsys_initcall(iucv_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) module_exit(iucv_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) MODULE_LICENSE("GPL");