^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);