^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 in absolute storage"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright IBM Corp. 2003, 2013
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author(s): Michael Holzheu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define KMSG_COMPONENT "sclp_sdias"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/sclp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/ipl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "sclp_sdias.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "sclp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "sclp_rw.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define TRACE(x...) debug_sprintf_event(sdias_dbf, 1, x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SDIAS_RETRIES 300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static struct debug_info *sdias_dbf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static struct sclp_register sclp_sdias_register = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) .send_mask = EVTYP_SDIAS_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static struct sdias_sccb *sclp_sdias_sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static struct sdias_evbuf sdias_evbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static DECLARE_COMPLETION(evbuf_accepted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static DECLARE_COMPLETION(evbuf_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static DEFINE_MUTEX(sdias_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Called by SCLP base when read event data has been completed (async mode only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static void sclp_sdias_receiver_fn(struct evbuf_header *evbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) memcpy(&sdias_evbuf, evbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) min_t(unsigned long, sizeof(sdias_evbuf), evbuf->length));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) complete(&evbuf_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) TRACE("sclp_sdias_receiver_fn done\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * Called by SCLP base when sdias event has been accepted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void sdias_callback(struct sclp_req *request, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) complete(&evbuf_accepted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) TRACE("callback done\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static int sdias_sclp_send(struct sclp_req *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct sdias_sccb *sccb = sclp_sdias_sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int retries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) for (retries = SDIAS_RETRIES; retries; retries--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) TRACE("add request\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) rc = sclp_add_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* not initiated, wait some time and retry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) TRACE("add request failed: rc = %i\n",rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) schedule_timeout(msecs_to_jiffies(500));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* initiated, wait for completion of service call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) wait_for_completion(&evbuf_accepted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (req->status == SCLP_REQ_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) TRACE("sclp request failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* if not accepted, retry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!(sccb->evbuf.hdr.flags & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) TRACE("sclp request failed: flags=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) sccb->evbuf.hdr.flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * for the sync interface the response is in the initial sccb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!sclp_sdias_register.receiver_fn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) memcpy(&sdias_evbuf, &sccb->evbuf, sizeof(sdias_evbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) TRACE("sync request done\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* otherwise we wait for completion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) wait_for_completion(&evbuf_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) TRACE("request done\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * Get number of blocks (4K) available in the HSA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int sclp_sdias_blk_count(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct sdias_sccb *sccb = sclp_sdias_sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct sclp_req request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) mutex_lock(&sdias_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) memset(sccb, 0, sizeof(*sccb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) memset(&request, 0, sizeof(request));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) sccb->hdr.length = sizeof(*sccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) sccb->evbuf.hdr.type = EVTYP_SDIAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) sccb->evbuf.event_qual = SDIAS_EQ_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) sccb->evbuf.event_id = 4712;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) sccb->evbuf.dbs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) request.sccb = sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) request.command = SCLP_CMDW_WRITE_EVENT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) request.status = SCLP_REQ_FILLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) request.callback = sdias_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) rc = sdias_sclp_send(&request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pr_err("sclp_send failed for get_nr_blocks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (sccb->hdr.response_code != 0x0020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) TRACE("send failed: %x\n", sccb->hdr.response_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) switch (sdias_evbuf.event_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) rc = sdias_evbuf.blk_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) pr_err("SCLP error: %x\n", sdias_evbuf.event_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) TRACE("%i blocks\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) mutex_unlock(&sdias_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * Copy from HSA to absolute storage (not reentrant):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * @dest : Address of buffer where data should be copied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * @start_blk: Start Block (beginning with 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * @nr_blks : Number of 4K blocks to copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * Return Value: 0 : Requested 'number' of blocks of data copied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * <0: ERROR - negative event status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct sdias_sccb *sccb = sclp_sdias_sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct sclp_req request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) mutex_lock(&sdias_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) memset(sccb, 0, sizeof(*sccb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) memset(&request, 0, sizeof(request));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) sccb->hdr.length = sizeof(*sccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) sccb->evbuf.hdr.type = EVTYP_SDIAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) sccb->evbuf.hdr.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) sccb->evbuf.event_qual = SDIAS_EQ_STORE_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) sccb->evbuf.event_id = 4712;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) sccb->evbuf.asa_size = SDIAS_ASA_SIZE_64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) sccb->evbuf.event_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) sccb->evbuf.blk_cnt = nr_blks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) sccb->evbuf.asa = (unsigned long)dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) sccb->evbuf.fbn = start_blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) sccb->evbuf.lbn = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) sccb->evbuf.dbs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) request.sccb = sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) request.command = SCLP_CMDW_WRITE_EVENT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) request.status = SCLP_REQ_FILLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) request.callback = sdias_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) rc = sdias_sclp_send(&request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) pr_err("sclp_send failed: %x\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (sccb->hdr.response_code != 0x0020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) TRACE("copy failed: %x\n", sccb->hdr.response_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) switch (sdias_evbuf.event_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) case SDIAS_EVSTATE_ALL_STORED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) TRACE("all stored\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) case SDIAS_EVSTATE_PART_STORED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) TRACE("part stored: %i\n", sdias_evbuf.blk_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) case SDIAS_EVSTATE_NO_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) TRACE("no data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) pr_err("Error from SCLP while copying hsa. Event status = %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) sdias_evbuf.event_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) mutex_unlock(&sdias_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static int __init sclp_sdias_register_check(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) rc = sclp_register(&sclp_sdias_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (sclp_sdias_blk_count() == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) sclp_unregister(&sclp_sdias_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static int __init sclp_sdias_init_sync(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) TRACE("Try synchronous mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) sclp_sdias_register.receive_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) sclp_sdias_register.receiver_fn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return sclp_sdias_register_check();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static int __init sclp_sdias_init_async(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) TRACE("Try asynchronous mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) sclp_sdias_register.receive_mask = EVTYP_SDIAS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) sclp_sdias_register.receiver_fn = sclp_sdias_receiver_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return sclp_sdias_register_check();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int __init sclp_sdias_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!is_ipl_type_dump())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) sclp_sdias_sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) BUG_ON(!sclp_sdias_sccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) sdias_dbf = debug_register("dump_sdias", 4, 1, 4 * sizeof(long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) debug_register_view(sdias_dbf, &debug_sprintf_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) debug_set_level(sdias_dbf, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (sclp_sdias_init_sync() == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (sclp_sdias_init_async() == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) TRACE("init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) free_page((unsigned long) sclp_sdias_sccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) TRACE("init done\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }