Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * SCLP "store data in absolute storage"
0004  *
0005  * Copyright IBM Corp. 2003, 2013
0006  * Author(s): Michael Holzheu
0007  */
0008 
0009 #define KMSG_COMPONENT "sclp_sdias"
0010 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0011 
0012 #include <linux/completion.h>
0013 #include <linux/sched.h>
0014 #include <asm/sclp.h>
0015 #include <asm/debug.h>
0016 #include <asm/ipl.h>
0017 
0018 #include "sclp_sdias.h"
0019 #include "sclp.h"
0020 #include "sclp_rw.h"
0021 
0022 #define TRACE(x...) debug_sprintf_event(sdias_dbf, 1, x)
0023 
0024 #define SDIAS_RETRIES 300
0025 
0026 static struct debug_info *sdias_dbf;
0027 
0028 static struct sclp_register sclp_sdias_register = {
0029     .send_mask = EVTYP_SDIAS_MASK,
0030 };
0031 
0032 static struct sdias_sccb *sclp_sdias_sccb;
0033 static struct sdias_evbuf sdias_evbuf;
0034 
0035 static DECLARE_COMPLETION(evbuf_accepted);
0036 static DECLARE_COMPLETION(evbuf_done);
0037 static DEFINE_MUTEX(sdias_mutex);
0038 
0039 /*
0040  * Called by SCLP base when read event data has been completed (async mode only)
0041  */
0042 static void sclp_sdias_receiver_fn(struct evbuf_header *evbuf)
0043 {
0044     memcpy(&sdias_evbuf, evbuf,
0045            min_t(unsigned long, sizeof(sdias_evbuf), evbuf->length));
0046     complete(&evbuf_done);
0047     TRACE("sclp_sdias_receiver_fn done\n");
0048 }
0049 
0050 /*
0051  * Called by SCLP base when sdias event has been accepted
0052  */
0053 static void sdias_callback(struct sclp_req *request, void *data)
0054 {
0055     complete(&evbuf_accepted);
0056     TRACE("callback done\n");
0057 }
0058 
0059 static int sdias_sclp_send(struct sclp_req *req)
0060 {
0061     struct sdias_sccb *sccb = sclp_sdias_sccb;
0062     int retries;
0063     int rc;
0064 
0065     for (retries = SDIAS_RETRIES; retries; retries--) {
0066         TRACE("add request\n");
0067         rc = sclp_add_request(req);
0068         if (rc) {
0069             /* not initiated, wait some time and retry */
0070             set_current_state(TASK_INTERRUPTIBLE);
0071             TRACE("add request failed: rc = %i\n",rc);
0072             schedule_timeout(msecs_to_jiffies(500));
0073             continue;
0074         }
0075         /* initiated, wait for completion of service call */
0076         wait_for_completion(&evbuf_accepted);
0077         if (req->status == SCLP_REQ_FAILED) {
0078             TRACE("sclp request failed\n");
0079             continue;
0080         }
0081         /* if not accepted, retry */
0082         if (!(sccb->evbuf.hdr.flags & 0x80)) {
0083             TRACE("sclp request failed: flags=%x\n",
0084                   sccb->evbuf.hdr.flags);
0085             continue;
0086         }
0087         /*
0088          * for the sync interface the response is in the initial sccb
0089          */
0090         if (!sclp_sdias_register.receiver_fn) {
0091             memcpy(&sdias_evbuf, &sccb->evbuf, sizeof(sdias_evbuf));
0092             TRACE("sync request done\n");
0093             return 0;
0094         }
0095         /* otherwise we wait for completion */
0096         wait_for_completion(&evbuf_done);
0097         TRACE("request done\n");
0098         return 0;
0099     }
0100     return -EIO;
0101 }
0102 
0103 /*
0104  * Get number of blocks (4K) available in the HSA
0105  */
0106 int sclp_sdias_blk_count(void)
0107 {
0108     struct sdias_sccb *sccb = sclp_sdias_sccb;
0109     struct sclp_req request;
0110     int rc;
0111 
0112     mutex_lock(&sdias_mutex);
0113 
0114     memset(sccb, 0, sizeof(*sccb));
0115     memset(&request, 0, sizeof(request));
0116 
0117     sccb->hdr.length = sizeof(*sccb);
0118     sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf);
0119     sccb->evbuf.hdr.type = EVTYP_SDIAS;
0120     sccb->evbuf.event_qual = SDIAS_EQ_SIZE;
0121     sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP;
0122     sccb->evbuf.event_id = 4712;
0123     sccb->evbuf.dbs = 1;
0124 
0125     request.sccb = sccb;
0126     request.command = SCLP_CMDW_WRITE_EVENT_DATA;
0127     request.status = SCLP_REQ_FILLED;
0128     request.callback = sdias_callback;
0129 
0130     rc = sdias_sclp_send(&request);
0131     if (rc) {
0132         pr_err("sclp_send failed for get_nr_blocks\n");
0133         goto out;
0134     }
0135     if (sccb->hdr.response_code != 0x0020) {
0136         TRACE("send failed: %x\n", sccb->hdr.response_code);
0137         rc = -EIO;
0138         goto out;
0139     }
0140 
0141     switch (sdias_evbuf.event_status) {
0142         case 0:
0143             rc = sdias_evbuf.blk_cnt;
0144             break;
0145         default:
0146             pr_err("SCLP error: %x\n", sdias_evbuf.event_status);
0147             rc = -EIO;
0148             goto out;
0149     }
0150     TRACE("%i blocks\n", rc);
0151 out:
0152     mutex_unlock(&sdias_mutex);
0153     return rc;
0154 }
0155 
0156 /*
0157  * Copy from HSA to absolute storage (not reentrant):
0158  *
0159  * @dest     : Address of buffer where data should be copied
0160  * @start_blk: Start Block (beginning with 1)
0161  * @nr_blks  : Number of 4K blocks to copy
0162  *
0163  * Return Value: 0 : Requested 'number' of blocks of data copied
0164  *       <0: ERROR - negative event status
0165  */
0166 int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)
0167 {
0168     struct sdias_sccb *sccb = sclp_sdias_sccb;
0169     struct sclp_req request;
0170     int rc;
0171 
0172     mutex_lock(&sdias_mutex);
0173 
0174     memset(sccb, 0, sizeof(*sccb));
0175     memset(&request, 0, sizeof(request));
0176 
0177     sccb->hdr.length = sizeof(*sccb);
0178     sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf);
0179     sccb->evbuf.hdr.type = EVTYP_SDIAS;
0180     sccb->evbuf.hdr.flags = 0;
0181     sccb->evbuf.event_qual = SDIAS_EQ_STORE_DATA;
0182     sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP;
0183     sccb->evbuf.event_id = 4712;
0184     sccb->evbuf.asa_size = SDIAS_ASA_SIZE_64;
0185     sccb->evbuf.event_status = 0;
0186     sccb->evbuf.blk_cnt = nr_blks;
0187     sccb->evbuf.asa = __pa(dest);
0188     sccb->evbuf.fbn = start_blk;
0189     sccb->evbuf.lbn = 0;
0190     sccb->evbuf.dbs = 1;
0191 
0192     request.sccb     = sccb;
0193     request.command  = SCLP_CMDW_WRITE_EVENT_DATA;
0194     request.status   = SCLP_REQ_FILLED;
0195     request.callback = sdias_callback;
0196 
0197     rc = sdias_sclp_send(&request);
0198     if (rc) {
0199         pr_err("sclp_send failed: %x\n", rc);
0200         goto out;
0201     }
0202     if (sccb->hdr.response_code != 0x0020) {
0203         TRACE("copy failed: %x\n", sccb->hdr.response_code);
0204         rc = -EIO;
0205         goto out;
0206     }
0207 
0208     switch (sdias_evbuf.event_status) {
0209     case SDIAS_EVSTATE_ALL_STORED:
0210         TRACE("all stored\n");
0211         break;
0212     case SDIAS_EVSTATE_PART_STORED:
0213         TRACE("part stored: %i\n", sdias_evbuf.blk_cnt);
0214         break;
0215     case SDIAS_EVSTATE_NO_DATA:
0216         TRACE("no data\n");
0217         fallthrough;
0218     default:
0219         pr_err("Error from SCLP while copying hsa. Event status = %x\n",
0220                sdias_evbuf.event_status);
0221         rc = -EIO;
0222     }
0223 out:
0224     mutex_unlock(&sdias_mutex);
0225     return rc;
0226 }
0227 
0228 static int __init sclp_sdias_register_check(void)
0229 {
0230     int rc;
0231 
0232     rc = sclp_register(&sclp_sdias_register);
0233     if (rc)
0234         return rc;
0235     if (sclp_sdias_blk_count() == 0) {
0236         sclp_unregister(&sclp_sdias_register);
0237         return -ENODEV;
0238     }
0239     return 0;
0240 }
0241 
0242 static int __init sclp_sdias_init_sync(void)
0243 {
0244     TRACE("Try synchronous mode\n");
0245     sclp_sdias_register.receive_mask = 0;
0246     sclp_sdias_register.receiver_fn = NULL;
0247     return sclp_sdias_register_check();
0248 }
0249 
0250 static int __init sclp_sdias_init_async(void)
0251 {
0252     TRACE("Try asynchronous mode\n");
0253     sclp_sdias_register.receive_mask = EVTYP_SDIAS_MASK;
0254     sclp_sdias_register.receiver_fn = sclp_sdias_receiver_fn;
0255     return sclp_sdias_register_check();
0256 }
0257 
0258 int __init sclp_sdias_init(void)
0259 {
0260     if (!is_ipl_type_dump())
0261         return 0;
0262     sclp_sdias_sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA);
0263     BUG_ON(!sclp_sdias_sccb);
0264     sdias_dbf = debug_register("dump_sdias", 4, 1, 4 * sizeof(long));
0265     debug_register_view(sdias_dbf, &debug_sprintf_view);
0266     debug_set_level(sdias_dbf, 6);
0267     if (sclp_sdias_init_sync() == 0)
0268         goto out;
0269     if (sclp_sdias_init_async() == 0)
0270         goto out;
0271     TRACE("init failed\n");
0272     free_page((unsigned long) sclp_sdias_sccb);
0273     return -ENODEV;
0274 out:
0275     TRACE("init done\n");
0276     return 0;
0277 }