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 + -
显示快捷键?