Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
0004  *          Horst Hummel <Horst.Hummel@de.ibm.com>
0005  *          Carsten Otte <Cotte@de.ibm.com>
0006  *          Martin Schwidefsky <schwidefsky@de.ibm.com>
0007  * Bugreports.to..: <Linux390@de.ibm.com>
0008  * Copyright IBM Corp. 1999, 2001
0009  *
0010  */
0011 
0012 #define KMSG_COMPONENT "dasd"
0013 
0014 #include <linux/ctype.h>
0015 #include <linux/init.h>
0016 
0017 #include <asm/debug.h>
0018 #include <asm/ebcdic.h>
0019 #include <linux/uaccess.h>
0020 
0021 /* This is ugly... */
0022 #define PRINTK_HEADER "dasd_erp:"
0023 
0024 #include "dasd_int.h"
0025 
0026 struct dasd_ccw_req *
0027 dasd_alloc_erp_request(unsigned int magic, int cplength, int datasize,
0028                struct dasd_device * device)
0029 {
0030     unsigned long flags;
0031     struct dasd_ccw_req *cqr;
0032     char *data;
0033     int size;
0034 
0035     /* Sanity checks */
0036     BUG_ON(datasize > PAGE_SIZE ||
0037            (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
0038 
0039     size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
0040     if (cplength > 0)
0041         size += cplength * sizeof(struct ccw1);
0042     if (datasize > 0)
0043         size += datasize;
0044     spin_lock_irqsave(&device->mem_lock, flags);
0045     cqr = (struct dasd_ccw_req *)
0046         dasd_alloc_chunk(&device->erp_chunks, size);
0047     spin_unlock_irqrestore(&device->mem_lock, flags);
0048     if (cqr == NULL)
0049         return ERR_PTR(-ENOMEM);
0050     memset(cqr, 0, sizeof(struct dasd_ccw_req));
0051     INIT_LIST_HEAD(&cqr->devlist);
0052     INIT_LIST_HEAD(&cqr->blocklist);
0053     data = (char *) cqr + ((sizeof(struct dasd_ccw_req) + 7L) & -8L);
0054     cqr->cpaddr = NULL;
0055     if (cplength > 0) {
0056         cqr->cpaddr = (struct ccw1 *) data;
0057         data += cplength*sizeof(struct ccw1);
0058         memset(cqr->cpaddr, 0, cplength*sizeof(struct ccw1));
0059     }
0060     cqr->data = NULL;
0061     if (datasize > 0) {
0062         cqr->data = data;
0063         memset(cqr->data, 0, datasize);
0064     }
0065     cqr->magic = magic;
0066     ASCEBC((char *) &cqr->magic, 4);
0067     set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
0068     dasd_get_device(device);
0069     return cqr;
0070 }
0071 
0072 void
0073 dasd_free_erp_request(struct dasd_ccw_req *cqr, struct dasd_device * device)
0074 {
0075     unsigned long flags;
0076 
0077     spin_lock_irqsave(&device->mem_lock, flags);
0078     dasd_free_chunk(&device->erp_chunks, cqr);
0079     spin_unlock_irqrestore(&device->mem_lock, flags);
0080     atomic_dec(&device->ref_count);
0081 }
0082 
0083 
0084 /*
0085  * dasd_default_erp_action just retries the current cqr
0086  */
0087 struct dasd_ccw_req *
0088 dasd_default_erp_action(struct dasd_ccw_req *cqr)
0089 {
0090     struct dasd_device *device;
0091 
0092     device = cqr->startdev;
0093 
0094         /* just retry - there is nothing to save ... I got no sense data.... */
0095         if (cqr->retries > 0) {
0096         DBF_DEV_EVENT(DBF_DEBUG, device,
0097                              "default ERP called (%i retries left)",
0098                              cqr->retries);
0099         if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))
0100             cqr->lpm = dasd_path_get_opm(device);
0101         cqr->status = DASD_CQR_FILLED;
0102         } else {
0103         pr_err("%s: default ERP has run out of retries and failed\n",
0104                dev_name(&device->cdev->dev));
0105         cqr->status = DASD_CQR_FAILED;
0106         cqr->stopclk = get_tod_clock();
0107         }
0108         return cqr;
0109 }               /* end dasd_default_erp_action */
0110 
0111 /*
0112  * DESCRIPTION
0113  *   Frees all ERPs of the current ERP Chain and set the status
0114  *   of the original CQR either to DASD_CQR_DONE if ERP was successful
0115  *   or to DASD_CQR_FAILED if ERP was NOT successful.
0116  *   NOTE: This function is only called if no discipline postaction
0117  *     is available
0118  *
0119  * PARAMETER
0120  *   erp        current erp_head
0121  *
0122  * RETURN VALUES
0123  *   cqr        pointer to the original CQR
0124  */
0125 struct dasd_ccw_req *dasd_default_erp_postaction(struct dasd_ccw_req *cqr)
0126 {
0127     int success;
0128     unsigned long startclk, stopclk;
0129     struct dasd_device *startdev;
0130 
0131     BUG_ON(cqr->refers == NULL || cqr->function == NULL);
0132 
0133     success = cqr->status == DASD_CQR_DONE;
0134     startclk = cqr->startclk;
0135     stopclk = cqr->stopclk;
0136     startdev = cqr->startdev;
0137 
0138     /* free all ERPs - but NOT the original cqr */
0139     while (cqr->refers != NULL) {
0140         struct dasd_ccw_req *refers;
0141 
0142         refers = cqr->refers;
0143         /* remove the request from the block queue */
0144         list_del(&cqr->blocklist);
0145         /* free the finished erp request */
0146         dasd_free_erp_request(cqr, cqr->memdev);
0147         cqr = refers;
0148     }
0149 
0150     /* set corresponding status to original cqr */
0151     cqr->startclk = startclk;
0152     cqr->stopclk = stopclk;
0153     cqr->startdev = startdev;
0154     if (success)
0155         cqr->status = DASD_CQR_DONE;
0156     else {
0157         cqr->status = DASD_CQR_FAILED;
0158         cqr->stopclk = get_tod_clock();
0159     }
0160 
0161     return cqr;
0162 
0163 }               /* end default_erp_postaction */
0164 
0165 void
0166 dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb)
0167 {
0168     struct dasd_device *device;
0169 
0170     device = cqr->startdev;
0171     if (cqr->intrc == -ETIMEDOUT) {
0172         dev_err(&device->cdev->dev,
0173             "A timeout error occurred for cqr %p\n", cqr);
0174         return;
0175     }
0176     if (cqr->intrc == -ENOLINK) {
0177         dev_err(&device->cdev->dev,
0178             "A transport error occurred for cqr %p\n", cqr);
0179         return;
0180     }
0181     /* dump sense data */
0182     if (device->discipline && device->discipline->dump_sense)
0183         device->discipline->dump_sense(device, cqr, irb);
0184 }
0185 
0186 void
0187 dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb)
0188 {
0189     struct dasd_device *device;
0190 
0191     device = cqr->startdev;
0192     /* dump sense data to s390 debugfeature*/
0193     if (device->discipline && device->discipline->dump_sense_dbf)
0194         device->discipline->dump_sense_dbf(device, irb, "log");
0195 }
0196 EXPORT_SYMBOL(dasd_log_sense_dbf);
0197 
0198 EXPORT_SYMBOL(dasd_default_erp_action);
0199 EXPORT_SYMBOL(dasd_default_erp_postaction);
0200 EXPORT_SYMBOL(dasd_alloc_erp_request);
0201 EXPORT_SYMBOL(dasd_free_erp_request);
0202 EXPORT_SYMBOL(dasd_log_sense);
0203