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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * SCLP Store Data support and sysfs interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright IBM Corp. 2017
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #define KMSG_COMPONENT "sclp_sd"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/printk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/async.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <asm/pgalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include "sclp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define SD_EQ_STORE_DATA	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define SD_EQ_HALT		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define SD_EQ_SIZE		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define SD_DI_CONFIG		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) struct sclp_sd_evbuf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	struct evbuf_header hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	u8 eq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	u8 di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	u8 rflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	u64 :56;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	u16 :16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	u8 fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	u64 sat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	u64 sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	u32 esize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	u32 dsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) struct sclp_sd_sccb {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	struct sccb_header hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct sclp_sd_evbuf evbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) } __packed __aligned(PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * struct sclp_sd_data - Result of a Store Data request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * @esize_bytes: Resulting esize in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * @dsize_bytes: Resulting dsize in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * @data: Pointer to data - must be released using vfree()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) struct sclp_sd_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	size_t esize_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	size_t dsize_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * struct sclp_sd_listener - Listener for asynchronous Store Data response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * @list: For enqueueing this struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * @id: Event ID of response to listen for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * @completion: Can be used to wait for response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * @evbuf: Contains the resulting Store Data response after completion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) struct sclp_sd_listener {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	struct completion completion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	struct sclp_sd_evbuf evbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * struct sclp_sd_file - Sysfs representation of a Store Data entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * @kobj: Kobject
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * @data_attr: Attribute for accessing data contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * @data_mutex: Mutex to serialize access and updates to @data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * @data: Data associated with this entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * @di: DI value associated with this entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) struct sclp_sd_file {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	struct kobject kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	struct bin_attribute data_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	struct mutex data_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct sclp_sd_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	u8 di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) #define to_sd_file(x) container_of(x, struct sclp_sd_file, kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static struct kset *sclp_sd_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) static struct sclp_sd_file *config_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) static LIST_HEAD(sclp_sd_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) static DEFINE_SPINLOCK(sclp_sd_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)  * sclp_sd_listener_add() - Add listener for Store Data responses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)  * @listener: Listener to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static void sclp_sd_listener_add(struct sclp_sd_listener *listener)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	spin_lock_irq(&sclp_sd_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	list_add_tail(&listener->list, &sclp_sd_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	spin_unlock_irq(&sclp_sd_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * sclp_sd_listener_remove() - Remove listener for Store Data responses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  * @listener: Listener to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static void sclp_sd_listener_remove(struct sclp_sd_listener *listener)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	spin_lock_irq(&sclp_sd_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	list_del(&listener->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	spin_unlock_irq(&sclp_sd_queue_lock);
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * sclp_sd_listener_init() - Initialize a Store Data response listener
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * @id: Event ID to listen for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  * Initialize a listener for asynchronous Store Data responses. This listener
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  * can afterwards be used to wait for a specific response and to retrieve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)  * the associated response data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static void sclp_sd_listener_init(struct sclp_sd_listener *listener, u32 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	memset(listener, 0, sizeof(*listener));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	listener->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	init_completion(&listener->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  * sclp_sd_receiver() - Receiver for Store Data events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  * @evbuf_hdr: Header of received events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * Process Store Data events and complete listeners with matching event IDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static void sclp_sd_receiver(struct evbuf_header *evbuf_hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	struct sclp_sd_evbuf *evbuf = (struct sclp_sd_evbuf *) evbuf_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	struct sclp_sd_listener *listener;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	int found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	pr_debug("received event (id=0x%08x)\n", evbuf->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	spin_lock(&sclp_sd_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	list_for_each_entry(listener, &sclp_sd_queue, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		if (listener->id != evbuf->id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		listener->evbuf = *evbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		complete(&listener->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		found = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	spin_unlock(&sclp_sd_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		pr_debug("unsolicited event (id=0x%08x)\n", evbuf->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static struct sclp_register sclp_sd_register = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	.send_mask = EVTYP_STORE_DATA_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	.receive_mask = EVTYP_STORE_DATA_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	.receiver_fn = sclp_sd_receiver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)  * sclp_sd_sync() - Perform Store Data request synchronously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  * @page: Address of work page - must be below 2GB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  * @eq: Input EQ value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  * @di: Input DI value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  * @sat: Input SAT value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  * @sa: Input SA value used to specify the address of the target buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  * @dsize_ptr: Optional pointer to input and output DSIZE value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * @esize_ptr: Optional pointer to output ESIZE value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * Perform Store Data request with specified parameters and wait for completion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  * Return %0 on success and store resulting DSIZE and ESIZE values in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * @dsize_ptr and @esize_ptr (if provided). Return non-zero on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int sclp_sd_sync(unsigned long page, u8 eq, u8 di, u64 sat, u64 sa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			u32 *dsize_ptr, u32 *esize_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	struct sclp_sd_sccb *sccb = (void *) page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	struct sclp_sd_listener listener;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	struct sclp_sd_evbuf *evbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	sclp_sd_listener_init(&listener, (u32) (addr_t) sccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	sclp_sd_listener_add(&listener);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	/* Prepare SCCB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	memset(sccb, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	sccb->hdr.length = sizeof(sccb->hdr) + sizeof(sccb->evbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	evbuf = &sccb->evbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	evbuf->hdr.length = sizeof(*evbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	evbuf->hdr.type = EVTYP_STORE_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	evbuf->eq = eq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	evbuf->di = di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	evbuf->id = listener.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	evbuf->fmt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	evbuf->sat = sat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	evbuf->sa = sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	if (dsize_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		evbuf->dsize = *dsize_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	/* Perform command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	pr_debug("request (eq=%d, di=%d, id=0x%08x)\n", eq, di, listener.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	rc = sclp_sync_request(SCLP_CMDW_WRITE_EVENT_DATA, sccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	pr_debug("request done (rc=%d)\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	/* Evaluate response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	if (sccb->hdr.response_code == 0x73f0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		pr_debug("event not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		goto out_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	if (sccb->hdr.response_code != 0x0020 || !(evbuf->hdr.flags & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (!(evbuf->rflags & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		rc = wait_for_completion_interruptible(&listener.completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		evbuf = &listener.evbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	switch (evbuf->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		if (dsize_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 			*dsize_ptr = evbuf->dsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		if (esize_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 			*esize_ptr = evbuf->esize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		pr_debug("success (dsize=%u, esize=%u)\n", evbuf->dsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			 evbuf->esize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		rc = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	if (rc && rc != -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		/* Provide some information about what went wrong */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		pr_warn("Store Data request failed (eq=%d, di=%d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 			"response=0x%04x, flags=0x%02x, status=%d, rc=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 			eq, di, sccb->hdr.response_code, evbuf->hdr.flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			evbuf->status, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) out_remove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	sclp_sd_listener_remove(&listener);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)  * sclp_sd_store_data() - Obtain data for specified Store Data entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)  * @result: Resulting data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)  * @di: DI value associated with this entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  * Perform a series of Store Data requests to obtain the size and contents of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  * the specified Store Data entity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)  *   %0:       Success - result is stored in @result. @result->data must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)  *	       released using vfree() after use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)  *   %-ENOENT: No data available for this entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)  *   %<0:      Other error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int sclp_sd_store_data(struct sclp_sd_data *result, u8 di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	u32 dsize = 0, esize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	unsigned long page, asce = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	void *data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	page = __get_free_page(GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	/* Get size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	rc = sclp_sd_sync(page, SD_EQ_SIZE, di, 0, 0, &dsize, &esize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	if (dsize == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		goto out_result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	/* Allocate memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	data = vzalloc(array_size((size_t)dsize, PAGE_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	if (!data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	/* Get translation table for buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	asce = base_asce_alloc((unsigned long) data, dsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	if (!asce) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		vfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	/* Get data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	rc = sclp_sd_sync(page, SD_EQ_STORE_DATA, di, asce, (u64) data, &dsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 			  &esize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		/* Cancel running request if interrupted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		if (rc == -ERESTARTSYS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 			sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		vfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) out_result:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	result->esize_bytes = (size_t) esize * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	result->dsize_bytes = (size_t) dsize * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	result->data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	base_asce_free(asce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)  * sclp_sd_data_reset() - Reset Store Data result buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)  * @data: Data buffer to reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)  * Reset @data to initial state and release associated memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static void sclp_sd_data_reset(struct sclp_sd_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	vfree(data->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	data->data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	data->dsize_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	data->esize_bytes = 0;
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)  * sclp_sd_file_release() - Release function for sclp_sd_file object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)  * @kobj: Kobject embedded in sclp_sd_file object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static void sclp_sd_file_release(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	struct sclp_sd_file *sd_file = to_sd_file(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	sclp_sd_data_reset(&sd_file->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	kfree(sd_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)  * sclp_sd_file_update() - Update contents of sclp_sd_file object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)  * @sd_file: Object to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)  * Obtain the current version of data associated with the Store Data entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)  * @sd_file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)  * On success, return %0 and generate a KOBJ_CHANGE event to indicate that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)  * data may have changed. Return non-zero otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int sclp_sd_file_update(struct sclp_sd_file *sd_file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	const char *name = kobject_name(&sd_file->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	struct sclp_sd_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	rc = sclp_sd_store_data(&data, sd_file->di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		if (rc == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 			pr_info("No data is available for the %s data entity\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 				 name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	mutex_lock(&sd_file->data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	sclp_sd_data_reset(&sd_file->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	sd_file->data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	mutex_unlock(&sd_file->data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	pr_info("A %zu-byte %s data entity was retrieved\n", data.dsize_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	kobject_uevent(&sd_file->kobj, KOBJ_CHANGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)  * sclp_sd_file_update_async() - Wrapper for asynchronous update call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)  * @data: Object to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static void sclp_sd_file_update_async(void *data, async_cookie_t cookie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	struct sclp_sd_file *sd_file = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	sclp_sd_file_update(sd_file);
^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)  * reload_store() - Store function for "reload" sysfs attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)  * @kobj: Kobject of sclp_sd_file object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)  * Initiate a reload of the data associated with an sclp_sd_file object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static ssize_t reload_store(struct kobject *kobj, struct kobj_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			    const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	struct sclp_sd_file *sd_file = to_sd_file(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	sclp_sd_file_update(sd_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static struct kobj_attribute reload_attr = __ATTR_WO(reload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) static struct attribute *sclp_sd_file_default_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	&reload_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static struct kobj_type sclp_sd_file_ktype = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	.sysfs_ops = &kobj_sysfs_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	.release = sclp_sd_file_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	.default_attrs = sclp_sd_file_default_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)  * data_read() - Read function for "read" sysfs attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)  * @kobj: Kobject of sclp_sd_file object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)  * @buffer: Target buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)  * @off: Requested file offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)  * @size: Requested number of bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)  * Store the requested portion of the Store Data entity contents into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)  * specified buffer. Return the number of bytes stored on success, or %0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)  * on EOF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static ssize_t data_read(struct file *file, struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			 struct bin_attribute *attr, char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 			 loff_t off, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	struct sclp_sd_file *sd_file = to_sd_file(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	size_t data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	mutex_lock(&sd_file->data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	data = sd_file->data.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	data_size = sd_file->data.dsize_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	if (!data || off >= data_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		if (off + size > data_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			size = data_size - off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		memcpy(buffer, data + off, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	mutex_unlock(&sd_file->data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)  * sclp_sd_file_create() - Add a sysfs file representing a Store Data entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)  * @name: Name of file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)  * @di: DI value associated with this entity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)  * Create a sysfs directory with the given @name located under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)  *   /sys/firmware/sclp_sd/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)  * The files in this directory can be used to access the contents of the Store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)  * Data entity associated with @DI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)  * Return pointer to resulting sclp_sd_file object on success, %NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)  * The object must be freed by calling kobject_put() on the embedded kobject
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)  * pointer after use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static __init struct sclp_sd_file *sclp_sd_file_create(const char *name, u8 di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	struct sclp_sd_file *sd_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	sd_file = kzalloc(sizeof(*sd_file), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	if (!sd_file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	sd_file->di = di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	mutex_init(&sd_file->data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	/* Create kobject located under /sys/firmware/sclp_sd/ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	sd_file->kobj.kset = sclp_sd_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	rc = kobject_init_and_add(&sd_file->kobj, &sclp_sd_file_ktype, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 				  "%s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		kobject_put(&sd_file->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	sysfs_bin_attr_init(&sd_file->data_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	sd_file->data_attr.attr.name = "data";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	sd_file->data_attr.attr.mode = 0444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	sd_file->data_attr.read = data_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	rc = sysfs_create_bin_file(&sd_file->kobj, &sd_file->data_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		kobject_put(&sd_file->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	 * For completeness only - users interested in entity data should listen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	 * for KOBJ_CHANGE instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	kobject_uevent(&sd_file->kobj, KOBJ_ADD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	/* Don't let a slow Store Data request delay further initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	async_schedule(sclp_sd_file_update_async, sd_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	return sd_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)  * sclp_sd_init() - Initialize sclp_sd support and register sysfs files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static __init int sclp_sd_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	rc = sclp_register(&sclp_sd_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	/* Create kset named "sclp_sd" located under /sys/firmware/ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	sclp_sd_kset = kset_create_and_add("sclp_sd", NULL, firmware_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	if (!sclp_sd_kset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		goto err_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	config_file = sclp_sd_file_create("config", SD_DI_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	if (!config_file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		goto err_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) err_config:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	kset_unregister(sclp_sd_kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) err_kset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	sclp_unregister(&sclp_sd_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) device_initcall(sclp_sd_init);