brintos

brintos / linux-shallow public Read only

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