diff options
Diffstat (limited to 'drivers/s390/cio/device_ops.c')
| -rw-r--r-- | drivers/s390/cio/device_ops.c | 99 | 
1 files changed, 82 insertions, 17 deletions
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 6da84543dfe..f3c417943da 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -198,7 +198,7 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,  	if (cdev->private->state == DEV_STATE_VERIFY) {  		/* Remember to fake irb when finished. */  		if (!cdev->private->flags.fake_irb) { -			cdev->private->flags.fake_irb = 1; +			cdev->private->flags.fake_irb = FAKE_CMD_IRB;  			cdev->private->intparm = intparm;  			return 0;  		} else @@ -213,9 +213,9 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,  	ret = cio_set_options (sch, flags);  	if (ret)  		return ret; -	/* Adjust requested path mask to excluded varied off paths. */ +	/* Adjust requested path mask to exclude unusable paths. */  	if (lpm) { -		lpm &= sch->opm; +		lpm &= sch->lpm;  		if (lpm == 0)  			return -EACCES;  	} @@ -418,12 +418,9 @@ int ccw_device_resume(struct ccw_device *cdev)  int  ccw_device_call_handler(struct ccw_device *cdev)  { -	struct subchannel *sch;  	unsigned int stctl;  	int ending_status; -	sch = to_subchannel(cdev->dev.parent); -  	/*  	 * we allow for the device action handler if .  	 *  - we received ending status @@ -566,14 +563,23 @@ out_unlock:  	return rc;  } -void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) +/** + * chp_get_chp_desc - return newly allocated channel-path descriptor + * @cdev: device to obtain the descriptor for + * @chp_idx: index of the channel path + * + * On success return a newly allocated copy of the channel-path description + * data associated with the given channel path. Return %NULL on error. + */ +struct channel_path_desc *ccw_device_get_chp_desc(struct ccw_device *cdev, +						  int chp_idx)  {  	struct subchannel *sch;  	struct chp_id chpid;  	sch = to_subchannel(cdev->dev.parent);  	chp_id_init(&chpid); -	chpid.id = sch->schib.pmcw.chpid[chp_no]; +	chpid.id = sch->schib.pmcw.chpid[chp_idx];  	return chp_get_chp_desc(chpid);  } @@ -608,11 +614,21 @@ int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,  	sch = to_subchannel(cdev->dev.parent);  	if (!sch->schib.pmcw.ena)  		return -EINVAL; +	if (cdev->private->state == DEV_STATE_VERIFY) { +		/* Remember to fake irb when finished. */ +		if (!cdev->private->flags.fake_irb) { +			cdev->private->flags.fake_irb = FAKE_TM_IRB; +			cdev->private->intparm = intparm; +			return 0; +		} else +			/* There's already a fake I/O around. */ +			return -EBUSY; +	}  	if (cdev->private->state != DEV_STATE_ONLINE)  		return -EIO; -	/* Adjust requested path mask to excluded varied off paths. */ +	/* Adjust requested path mask to exclude unusable paths. */  	if (lpm) { -		lpm &= sch->opm; +		lpm &= sch->lpm;  		if (lpm == 0)  			return -EACCES;  	} @@ -687,6 +703,52 @@ int ccw_device_tm_start_timeout(struct ccw_device *cdev, struct tcw *tcw,  EXPORT_SYMBOL(ccw_device_tm_start_timeout);  /** + * ccw_device_get_mdc - accumulate max data count + * @cdev: ccw device for which the max data count is accumulated + * @mask: mask of paths to use + * + * Return the number of 64K-bytes blocks all paths at least support + * for a transport command. Return values <= 0 indicate failures. + */ +int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask) +{ +	struct subchannel *sch = to_subchannel(cdev->dev.parent); +	struct channel_path *chp; +	struct chp_id chpid; +	int mdc = 0, i; + +	/* Adjust requested path mask to excluded varied off paths. */ +	if (mask) +		mask &= sch->lpm; +	else +		mask = sch->lpm; + +	chp_id_init(&chpid); +	for (i = 0; i < 8; i++) { +		if (!(mask & (0x80 >> i))) +			continue; +		chpid.id = sch->schib.pmcw.chpid[i]; +		chp = chpid_to_chp(chpid); +		if (!chp) +			continue; + +		mutex_lock(&chp->lock); +		if (!chp->desc_fmt1.f) { +			mutex_unlock(&chp->lock); +			return 0; +		} +		if (!chp->desc_fmt1.r) +			mdc = 1; +		mdc = mdc ? min_t(int, mdc, chp->desc_fmt1.mdc) : +			    chp->desc_fmt1.mdc; +		mutex_unlock(&chp->lock); +	} + +	return mdc; +} +EXPORT_SYMBOL(ccw_device_get_mdc); + +/**   * ccw_device_tm_intrg - perform interrogate function   * @cdev: ccw device on which to perform the interrogate function   * @@ -708,14 +770,18 @@ int ccw_device_tm_intrg(struct ccw_device *cdev)  }  EXPORT_SYMBOL(ccw_device_tm_intrg); -// FIXME: these have to go: - -int -_ccw_device_get_subchannel_number(struct ccw_device *cdev) +/** + * ccw_device_get_schid - obtain a subchannel id + * @cdev: device to obtain the id for + * @schid: where to fill in the values + */ +void ccw_device_get_schid(struct ccw_device *cdev, struct subchannel_id *schid)  { -	return cdev->private->schid.sch_no; -} +	struct subchannel *sch = to_subchannel(cdev->dev.parent); +	*schid = sch->schid; +} +EXPORT_SYMBOL_GPL(ccw_device_get_schid);  MODULE_LICENSE("GPL");  EXPORT_SYMBOL(ccw_device_set_options_mask); @@ -730,5 +796,4 @@ EXPORT_SYMBOL(ccw_device_start_timeout_key);  EXPORT_SYMBOL(ccw_device_start_key);  EXPORT_SYMBOL(ccw_device_get_ciw);  EXPORT_SYMBOL(ccw_device_get_path_mask); -EXPORT_SYMBOL(_ccw_device_get_subchannel_number);  EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);  | 
