cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dasd_erp.c (5349B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
      4 *		    Horst Hummel <Horst.Hummel@de.ibm.com>
      5 *		    Carsten Otte <Cotte@de.ibm.com>
      6 *		    Martin Schwidefsky <schwidefsky@de.ibm.com>
      7 * Bugreports.to..: <Linux390@de.ibm.com>
      8 * Copyright IBM Corp. 1999, 2001
      9 *
     10 */
     11
     12#define KMSG_COMPONENT "dasd"
     13
     14#include <linux/ctype.h>
     15#include <linux/init.h>
     16
     17#include <asm/debug.h>
     18#include <asm/ebcdic.h>
     19#include <linux/uaccess.h>
     20
     21/* This is ugly... */
     22#define PRINTK_HEADER "dasd_erp:"
     23
     24#include "dasd_int.h"
     25
     26struct dasd_ccw_req *
     27dasd_alloc_erp_request(unsigned int magic, int cplength, int datasize,
     28		       struct dasd_device * device)
     29{
     30	unsigned long flags;
     31	struct dasd_ccw_req *cqr;
     32	char *data;
     33	int size;
     34
     35	/* Sanity checks */
     36	BUG_ON(datasize > PAGE_SIZE ||
     37	       (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
     38
     39	size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
     40	if (cplength > 0)
     41		size += cplength * sizeof(struct ccw1);
     42	if (datasize > 0)
     43		size += datasize;
     44	spin_lock_irqsave(&device->mem_lock, flags);
     45	cqr = (struct dasd_ccw_req *)
     46		dasd_alloc_chunk(&device->erp_chunks, size);
     47	spin_unlock_irqrestore(&device->mem_lock, flags);
     48	if (cqr == NULL)
     49		return ERR_PTR(-ENOMEM);
     50	memset(cqr, 0, sizeof(struct dasd_ccw_req));
     51	INIT_LIST_HEAD(&cqr->devlist);
     52	INIT_LIST_HEAD(&cqr->blocklist);
     53	data = (char *) cqr + ((sizeof(struct dasd_ccw_req) + 7L) & -8L);
     54	cqr->cpaddr = NULL;
     55	if (cplength > 0) {
     56		cqr->cpaddr = (struct ccw1 *) data;
     57		data += cplength*sizeof(struct ccw1);
     58		memset(cqr->cpaddr, 0, cplength*sizeof(struct ccw1));
     59	}
     60	cqr->data = NULL;
     61	if (datasize > 0) {
     62		cqr->data = data;
     63 		memset(cqr->data, 0, datasize);
     64	}
     65	cqr->magic = magic;
     66	ASCEBC((char *) &cqr->magic, 4);
     67	set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
     68	dasd_get_device(device);
     69	return cqr;
     70}
     71
     72void
     73dasd_free_erp_request(struct dasd_ccw_req *cqr, struct dasd_device * device)
     74{
     75	unsigned long flags;
     76
     77	spin_lock_irqsave(&device->mem_lock, flags);
     78	dasd_free_chunk(&device->erp_chunks, cqr);
     79	spin_unlock_irqrestore(&device->mem_lock, flags);
     80	atomic_dec(&device->ref_count);
     81}
     82
     83
     84/*
     85 * dasd_default_erp_action just retries the current cqr
     86 */
     87struct dasd_ccw_req *
     88dasd_default_erp_action(struct dasd_ccw_req *cqr)
     89{
     90	struct dasd_device *device;
     91
     92	device = cqr->startdev;
     93
     94        /* just retry - there is nothing to save ... I got no sense data.... */
     95        if (cqr->retries > 0) {
     96		DBF_DEV_EVENT(DBF_DEBUG, device,
     97                             "default ERP called (%i retries left)",
     98                             cqr->retries);
     99		if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))
    100			cqr->lpm = dasd_path_get_opm(device);
    101		cqr->status = DASD_CQR_FILLED;
    102        } else {
    103		pr_err("%s: default ERP has run out of retries and failed\n",
    104		       dev_name(&device->cdev->dev));
    105		cqr->status = DASD_CQR_FAILED;
    106		cqr->stopclk = get_tod_clock();
    107        }
    108        return cqr;
    109}				/* end dasd_default_erp_action */
    110
    111/*
    112 * DESCRIPTION
    113 *   Frees all ERPs of the current ERP Chain and set the status
    114 *   of the original CQR either to DASD_CQR_DONE if ERP was successful
    115 *   or to DASD_CQR_FAILED if ERP was NOT successful.
    116 *   NOTE: This function is only called if no discipline postaction
    117 *	   is available
    118 *
    119 * PARAMETER
    120 *   erp		current erp_head
    121 *
    122 * RETURN VALUES
    123 *   cqr		pointer to the original CQR
    124 */
    125struct dasd_ccw_req *dasd_default_erp_postaction(struct dasd_ccw_req *cqr)
    126{
    127	int success;
    128	unsigned long startclk, stopclk;
    129	struct dasd_device *startdev;
    130
    131	BUG_ON(cqr->refers == NULL || cqr->function == NULL);
    132
    133	success = cqr->status == DASD_CQR_DONE;
    134	startclk = cqr->startclk;
    135	stopclk = cqr->stopclk;
    136	startdev = cqr->startdev;
    137
    138	/* free all ERPs - but NOT the original cqr */
    139	while (cqr->refers != NULL) {
    140		struct dasd_ccw_req *refers;
    141
    142		refers = cqr->refers;
    143		/* remove the request from the block queue */
    144		list_del(&cqr->blocklist);
    145		/* free the finished erp request */
    146		dasd_free_erp_request(cqr, cqr->memdev);
    147		cqr = refers;
    148	}
    149
    150	/* set corresponding status to original cqr */
    151	cqr->startclk = startclk;
    152	cqr->stopclk = stopclk;
    153	cqr->startdev = startdev;
    154	if (success)
    155		cqr->status = DASD_CQR_DONE;
    156	else {
    157		cqr->status = DASD_CQR_FAILED;
    158		cqr->stopclk = get_tod_clock();
    159	}
    160
    161	return cqr;
    162
    163}				/* end default_erp_postaction */
    164
    165void
    166dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb)
    167{
    168	struct dasd_device *device;
    169
    170	device = cqr->startdev;
    171	if (cqr->intrc == -ETIMEDOUT) {
    172		dev_err(&device->cdev->dev,
    173			"A timeout error occurred for cqr %p\n", cqr);
    174		return;
    175	}
    176	if (cqr->intrc == -ENOLINK) {
    177		dev_err(&device->cdev->dev,
    178			"A transport error occurred for cqr %p\n", cqr);
    179		return;
    180	}
    181	/* dump sense data */
    182	if (device->discipline && device->discipline->dump_sense)
    183		device->discipline->dump_sense(device, cqr, irb);
    184}
    185
    186void
    187dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb)
    188{
    189	struct dasd_device *device;
    190
    191	device = cqr->startdev;
    192	/* dump sense data to s390 debugfeature*/
    193	if (device->discipline && device->discipline->dump_sense_dbf)
    194		device->discipline->dump_sense_dbf(device, irb, "log");
    195}
    196EXPORT_SYMBOL(dasd_log_sense_dbf);
    197
    198EXPORT_SYMBOL(dasd_default_erp_action);
    199EXPORT_SYMBOL(dasd_default_erp_postaction);
    200EXPORT_SYMBOL(dasd_alloc_erp_request);
    201EXPORT_SYMBOL(dasd_free_erp_request);
    202EXPORT_SYMBOL(dasd_log_sense);
    203