device_ops.c

来自「linux 内核源代码」· C语言 代码 · 共 588 行 · 第 1/2 页

C
588
字号
/* *  drivers/s390/cio/device_ops.c * *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, *			 IBM Corporation *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) *               Cornelia Huck (cornelia.huck@de.ibm.com) */#include <linux/module.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/list.h>#include <linux/device.h>#include <linux/delay.h>#include <asm/ccwdev.h>#include <asm/idals.h>#include <asm/chpid.h>#include "cio.h"#include "cio_debug.h"#include "css.h"#include "chsc.h"#include "device.h"#include "chp.h"/** * ccw_device_set_options_mask() - set some options and unset the rest * @cdev: device for which the options are to be set * @flags: options to be set * * All flags specified in @flags are set, all flags not specified in @flags * are cleared. * Returns: *   %0 on success, -%EINVAL on an invalid flag combination. */int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags){       /*	* The flag usage is mutal exclusive ...	*/	if ((flags & CCWDEV_EARLY_NOTIFICATION) &&	    (flags & CCWDEV_REPORT_ALL))		return -EINVAL;	cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0;	cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0;	cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0;	cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0;	return 0;}/** * ccw_device_set_options() - set some options * @cdev: device for which the options are to be set * @flags: options to be set * * All flags specified in @flags are set, the remainder is left untouched. * Returns: *   %0 on success, -%EINVAL if an invalid flag combination would ensue. */int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags){       /*	* The flag usage is mutal exclusive ...	*/	if (((flags & CCWDEV_EARLY_NOTIFICATION) &&	    (flags & CCWDEV_REPORT_ALL)) ||	    ((flags & CCWDEV_EARLY_NOTIFICATION) &&	     cdev->private->options.repall) ||	    ((flags & CCWDEV_REPORT_ALL) &&	     cdev->private->options.fast))		return -EINVAL;	cdev->private->options.fast |= (flags & CCWDEV_EARLY_NOTIFICATION) != 0;	cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0;	cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0;	cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0;	return 0;}/** * ccw_device_clear_options() - clear some options * @cdev: device for which the options are to be cleared * @flags: options to be cleared * * All flags specified in @flags are cleared, the remainder is left untouched. */void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags){	cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0;	cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0;	cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0;	cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;}/** * ccw_device_clear() - terminate I/O request processing * @cdev: target ccw device * @intparm: interruption parameter; value is only used if no I/O is *	     outstanding, otherwise the intparm associated with the I/O request *	     is returned * * ccw_device_clear() calls csch on @cdev's subchannel. * Returns: *  %0 on success, *  -%ENODEV on device not operational, *  -%EINVAL on invalid device state. * Context: *  Interrupts disabled, ccw device lock held */int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm){	struct subchannel *sch;	int ret;	if (!cdev)		return -ENODEV;	if (cdev->private->state == DEV_STATE_NOT_OPER)		return -ENODEV;	if (cdev->private->state != DEV_STATE_ONLINE &&	    cdev->private->state != DEV_STATE_W4SENSE)		return -EINVAL;	sch = to_subchannel(cdev->dev.parent);	if (!sch)		return -ENODEV;	ret = cio_clear(sch);	if (ret == 0)		cdev->private->intparm = intparm;	return ret;}/** * ccw_device_start_key() - start a s390 channel program with key * @cdev: target ccw device * @cpa: logical start address of channel program * @intparm: user specific interruption parameter; will be presented back to *	     @cdev's interrupt handler. Allows a device driver to associate *	     the interrupt with a particular I/O request. * @lpm: defines the channel path to be used for a specific I/O request. A *	 value of 0 will make cio use the opm. * @key: storage key to be used for the I/O * @flags: additional flags; defines the action to be performed for I/O *	   processing. * * Start a S/390 channel program. When the interrupt arrives, the * IRQ handler is called, either immediately, delayed (dev-end missing, * or sense required) or never (no IRQ handler registered). * Returns: *  %0, if the operation was successful; *  -%EBUSY, if the device is busy, or status pending; *  -%EACCES, if no path specified in @lpm is operational; *  -%ENODEV, if the device is not operational. * Context: *  Interrupts disabled, ccw device lock held */int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,			 unsigned long intparm, __u8 lpm, __u8 key,			 unsigned long flags){	struct subchannel *sch;	int ret;	if (!cdev)		return -ENODEV;	sch = to_subchannel(cdev->dev.parent);	if (!sch)		return -ENODEV;	if (cdev->private->state == DEV_STATE_NOT_OPER)		return -ENODEV;	if (cdev->private->state == DEV_STATE_VERIFY ||	    cdev->private->state == DEV_STATE_CLEAR_VERIFY) {		/* Remember to fake irb when finished. */		if (!cdev->private->flags.fake_irb) {			cdev->private->flags.fake_irb = 1;			cdev->private->intparm = intparm;			return 0;		} else			/* There's already a fake I/O around. */			return -EBUSY;	}	if (cdev->private->state != DEV_STATE_ONLINE ||	    ((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&	     !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||	    cdev->private->flags.doverify)		return -EBUSY;	ret = cio_set_options (sch, flags);	if (ret)		return ret;	/* Adjust requested path mask to excluded varied off paths. */	if (lpm) {		lpm &= sch->opm;		if (lpm == 0)			return -EACCES;	}	ret = cio_start_key (sch, cpa, lpm, key);	if (ret == 0)		cdev->private->intparm = intparm;	return ret;}/** * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key * @cdev: target ccw device * @cpa: logical start address of channel program * @intparm: user specific interruption parameter; will be presented back to *	     @cdev's interrupt handler. Allows a device driver to associate *	     the interrupt with a particular I/O request. * @lpm: defines the channel path to be used for a specific I/O request. A *	 value of 0 will make cio use the opm. * @key: storage key to be used for the I/O * @flags: additional flags; defines the action to be performed for I/O *	   processing. * @expires: timeout value in jiffies * * Start a S/390 channel program. When the interrupt arrives, the * IRQ handler is called, either immediately, delayed (dev-end missing, * or sense required) or never (no IRQ handler registered). * This function notifies the device driver if the channel program has not * completed during the time specified by @expires. If a timeout occurs, the * channel program is terminated via xsch, hsch or csch, and the device's * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT). * Returns: *  %0, if the operation was successful; *  -%EBUSY, if the device is busy, or status pending; *  -%EACCES, if no path specified in @lpm is operational; *  -%ENODEV, if the device is not operational. * Context: *  Interrupts disabled, ccw device lock held */int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,				 unsigned long intparm, __u8 lpm, __u8 key,				 unsigned long flags, int expires){	int ret;	if (!cdev)		return -ENODEV;	ccw_device_set_timeout(cdev, expires);	ret = ccw_device_start_key(cdev, cpa, intparm, lpm, key, flags);	if (ret != 0)		ccw_device_set_timeout(cdev, 0);	return ret;}/** * ccw_device_start() - start a s390 channel program * @cdev: target ccw device * @cpa: logical start address of channel program * @intparm: user specific interruption parameter; will be presented back to *	     @cdev's interrupt handler. Allows a device driver to associate *	     the interrupt with a particular I/O request. * @lpm: defines the channel path to be used for a specific I/O request. A *	 value of 0 will make cio use the opm. * @flags: additional flags; defines the action to be performed for I/O *	   processing. * * Start a S/390 channel program. When the interrupt arrives, the * IRQ handler is called, either immediately, delayed (dev-end missing, * or sense required) or never (no IRQ handler registered). * Returns: *  %0, if the operation was successful; *  -%EBUSY, if the device is busy, or status pending; *  -%EACCES, if no path specified in @lpm is operational; *  -%ENODEV, if the device is not operational. * Context: *  Interrupts disabled, ccw device lock held */int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa,		     unsigned long intparm, __u8 lpm, unsigned long flags){	return ccw_device_start_key(cdev, cpa, intparm, lpm,				    PAGE_DEFAULT_KEY, flags);}/** * ccw_device_start_timeout() - start a s390 channel program with timeout * @cdev: target ccw device * @cpa: logical start address of channel program * @intparm: user specific interruption parameter; will be presented back to *	     @cdev's interrupt handler. Allows a device driver to associate *	     the interrupt with a particular I/O request. * @lpm: defines the channel path to be used for a specific I/O request. A *	 value of 0 will make cio use the opm. * @flags: additional flags; defines the action to be performed for I/O *	   processing. * @expires: timeout value in jiffies * * Start a S/390 channel program. When the interrupt arrives, the * IRQ handler is called, either immediately, delayed (dev-end missing, * or sense required) or never (no IRQ handler registered). * This function notifies the device driver if the channel program has not * completed during the time specified by @expires. If a timeout occurs, the * channel program is terminated via xsch, hsch or csch, and the device's * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?