^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-1.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright IBM Corp. 2002, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Cornelia Huck (cornelia.huck@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/ccwdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/idals.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/chpid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/fcx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "cio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "cio_debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "css.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "chsc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "device.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "chp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * ccw_device_set_options_mask() - set some options and unset the rest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * @cdev: device for which the options are to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * @flags: options to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * All flags specified in @flags are set, all flags not specified in @flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * are cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * %0 on success, -%EINVAL on an invalid flag combination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * The flag usage is mutal exclusive ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if ((flags & CCWDEV_EARLY_NOTIFICATION) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) (flags & CCWDEV_REPORT_ALL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) cdev->private->options.mpath = (flags & CCWDEV_DO_MULTIPATH) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * ccw_device_set_options() - set some options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * @cdev: device for which the options are to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * @flags: options to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * All flags specified in @flags are set, the remainder is left untouched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * %0 on success, -%EINVAL if an invalid flag combination would ensue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * The flag usage is mutal exclusive ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (((flags & CCWDEV_EARLY_NOTIFICATION) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) (flags & CCWDEV_REPORT_ALL)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ((flags & CCWDEV_EARLY_NOTIFICATION) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) cdev->private->options.repall) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ((flags & CCWDEV_REPORT_ALL) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) cdev->private->options.fast))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) cdev->private->options.fast |= (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) cdev->private->options.mpath |= (flags & CCWDEV_DO_MULTIPATH) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * ccw_device_clear_options() - clear some options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @cdev: device for which the options are to be cleared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @flags: options to be cleared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * All flags specified in @flags are cleared, the remainder is left untouched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) cdev->private->options.mpath &= (flags & CCWDEV_DO_MULTIPATH) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * ccw_device_is_pathgroup() - determine if paths to this device are grouped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * @cdev: ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * Return non-zero if there is a path group, zero otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int ccw_device_is_pathgroup(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return cdev->private->flags.pgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) EXPORT_SYMBOL(ccw_device_is_pathgroup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * ccw_device_is_multipath() - determine if device is operating in multipath mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * @cdev: ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * Return non-zero if device is operating in multipath mode, zero otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int ccw_device_is_multipath(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return cdev->private->flags.mpath;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) EXPORT_SYMBOL(ccw_device_is_multipath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * ccw_device_clear() - terminate I/O request processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @cdev: target ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * @intparm: interruption parameter to be returned upon conclusion of csch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * ccw_device_clear() calls csch on @cdev's subchannel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * %0 on success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * -%ENODEV on device not operational,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * -%EINVAL on invalid device state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * Context:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * Interrupts disabled, ccw device lock held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct subchannel *sch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!cdev || !cdev->dev.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (!sch->schib.pmcw.ena)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (cdev->private->state == DEV_STATE_NOT_OPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (cdev->private->state != DEV_STATE_ONLINE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) cdev->private->state != DEV_STATE_W4SENSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ret = cio_clear(sch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) cdev->private->intparm = intparm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * @cdev: target ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * @cpa: logical start address of channel program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * @intparm: user specific interruption parameter; will be presented back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * @cdev's interrupt handler. Allows a device driver to associate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * the interrupt with a particular I/O request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * @lpm: defines the channel path to be used for a specific I/O request. A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * value of 0 will make cio use the opm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @key: storage key to be used for the I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * @flags: additional flags; defines the action to be performed for I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * @expires: timeout value in jiffies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * Start a S/390 channel program. When the interrupt arrives, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * IRQ handler is called, either immediately, delayed (dev-end missing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * or sense required) or never (no IRQ handler registered).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * This function notifies the device driver if the channel program has not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * completed during the time specified by @expires. If a timeout occurs, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * channel program is terminated via xsch, hsch or csch, and the device's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * The interruption handler will echo back the @intparm specified here, unless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * another interruption parameter is specified by a subsequent invocation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * ccw_device_halt() or ccw_device_clear().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * %0, if the operation was successful;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * -%EBUSY, if the device is busy, or status pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * -%EACCES, if no path specified in @lpm is operational;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * -%ENODEV, if the device is not operational.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * Context:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * Interrupts disabled, ccw device lock held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned long intparm, __u8 lpm, __u8 key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) unsigned long flags, int expires)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct subchannel *sch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (!cdev || !cdev->dev.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (!sch->schib.pmcw.ena)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (cdev->private->state == DEV_STATE_NOT_OPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (cdev->private->state == DEV_STATE_VERIFY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* Remember to fake irb when finished. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!cdev->private->flags.fake_irb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) cdev->private->flags.fake_irb = FAKE_CMD_IRB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) cdev->private->intparm = intparm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* There's already a fake I/O around. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (cdev->private->state != DEV_STATE_ONLINE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ((sch->schib.scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) cdev->private->flags.doverify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ret = cio_set_options (sch, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /* Adjust requested path mask to exclude unusable paths. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (lpm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) lpm &= sch->lpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (lpm == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ret = cio_start_key (sch, cpa, lpm, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) cdev->private->intparm = intparm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (expires)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ccw_device_set_timeout(cdev, expires);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) case -EACCES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) case -ENODEV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) dev_fsm_event(cdev, DEV_EVENT_VERIFY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * ccw_device_start_key() - start a s390 channel program with key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * @cdev: target ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * @cpa: logical start address of channel program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * @intparm: user specific interruption parameter; will be presented back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * @cdev's interrupt handler. Allows a device driver to associate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * the interrupt with a particular I/O request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * @lpm: defines the channel path to be used for a specific I/O request. A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * value of 0 will make cio use the opm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * @key: storage key to be used for the I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * @flags: additional flags; defines the action to be performed for I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Start a S/390 channel program. When the interrupt arrives, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * IRQ handler is called, either immediately, delayed (dev-end missing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * or sense required) or never (no IRQ handler registered).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * The interruption handler will echo back the @intparm specified here, unless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * another interruption parameter is specified by a subsequent invocation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * ccw_device_halt() or ccw_device_clear().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * %0, if the operation was successful;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * -%EBUSY, if the device is busy, or status pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * -%EACCES, if no path specified in @lpm is operational;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * -%ENODEV, if the device is not operational.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Context:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * Interrupts disabled, ccw device lock held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) unsigned long intparm, __u8 lpm, __u8 key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) flags, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * ccw_device_start() - start a s390 channel program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * @cdev: target ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * @cpa: logical start address of channel program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * @intparm: user specific interruption parameter; will be presented back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * @cdev's interrupt handler. Allows a device driver to associate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * the interrupt with a particular I/O request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * @lpm: defines the channel path to be used for a specific I/O request. A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * value of 0 will make cio use the opm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * @flags: additional flags; defines the action to be performed for I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * Start a S/390 channel program. When the interrupt arrives, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * IRQ handler is called, either immediately, delayed (dev-end missing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * or sense required) or never (no IRQ handler registered).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * The interruption handler will echo back the @intparm specified here, unless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * another interruption parameter is specified by a subsequent invocation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * ccw_device_halt() or ccw_device_clear().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * %0, if the operation was successful;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * -%EBUSY, if the device is busy, or status pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * -%EACCES, if no path specified in @lpm is operational;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * -%ENODEV, if the device is not operational.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * Context:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * Interrupts disabled, ccw device lock held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned long intparm, __u8 lpm, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return ccw_device_start_key(cdev, cpa, intparm, lpm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) PAGE_DEFAULT_KEY, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * ccw_device_start_timeout() - start a s390 channel program with timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * @cdev: target ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * @cpa: logical start address of channel program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * @intparm: user specific interruption parameter; will be presented back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * @cdev's interrupt handler. Allows a device driver to associate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * the interrupt with a particular I/O request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * @lpm: defines the channel path to be used for a specific I/O request. A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * value of 0 will make cio use the opm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * @flags: additional flags; defines the action to be performed for I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * @expires: timeout value in jiffies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * Start a S/390 channel program. When the interrupt arrives, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * IRQ handler is called, either immediately, delayed (dev-end missing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * or sense required) or never (no IRQ handler registered).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * This function notifies the device driver if the channel program has not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * completed during the time specified by @expires. If a timeout occurs, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * channel program is terminated via xsch, hsch or csch, and the device's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * The interruption handler will echo back the @intparm specified here, unless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * another interruption parameter is specified by a subsequent invocation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * ccw_device_halt() or ccw_device_clear().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * %0, if the operation was successful;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * -%EBUSY, if the device is busy, or status pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * -%EACCES, if no path specified in @lpm is operational;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * -%ENODEV, if the device is not operational.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * Context:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * Interrupts disabled, ccw device lock held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned long intparm, __u8 lpm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) unsigned long flags, int expires)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) PAGE_DEFAULT_KEY, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) expires);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * ccw_device_halt() - halt I/O request processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * @cdev: target ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * @intparm: interruption parameter to be returned upon conclusion of hsch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * ccw_device_halt() calls hsch on @cdev's subchannel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * The interruption handler will echo back the @intparm specified here, unless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * another interruption parameter is specified by a subsequent invocation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * ccw_device_clear().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * %0 on success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * -%ENODEV on device not operational,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * -%EINVAL on invalid device state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * -%EBUSY on device busy or interrupt pending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * Context:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * Interrupts disabled, ccw device lock held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct subchannel *sch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (!cdev || !cdev->dev.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (!sch->schib.pmcw.ena)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (cdev->private->state == DEV_STATE_NOT_OPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (cdev->private->state != DEV_STATE_ONLINE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) cdev->private->state != DEV_STATE_W4SENSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ret = cio_halt(sch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) cdev->private->intparm = intparm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * ccw_device_resume() - resume channel program execution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * @cdev: target ccw device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * ccw_device_resume() calls rsch on @cdev's subchannel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * %0 on success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * -%ENODEV on device not operational,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * -%EINVAL on invalid device state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * -%EBUSY on device busy or interrupt pending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * Context:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * Interrupts disabled, ccw device lock held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int ccw_device_resume(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct subchannel *sch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (!cdev || !cdev->dev.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (!sch->schib.pmcw.ena)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (cdev->private->state == DEV_STATE_NOT_OPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (cdev->private->state != DEV_STATE_ONLINE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) !(sch->schib.scsw.cmd.actl & SCSW_ACTL_SUSPENDED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return cio_resume(sch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * ccw_device_get_ciw() - Search for CIW command in extended sense data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * @cdev: ccw device to inspect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * @ct: command type to look for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * During SenseID, command information words (CIWs) describing special
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * commands available to the device may have been stored in the extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * sense data. This function searches for CIWs of a specified command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * type in the extended sense data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * %NULL if no extended sense data has been stored or if no CIW of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * specified command type could be found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * else a pointer to the CIW of the specified command type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) int ciw_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (cdev->private->flags.esid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) for (ciw_cnt = 0; ciw_cnt < MAX_CIWS; ciw_cnt++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (cdev->private->dma_area->senseid.ciw[ciw_cnt].ct == ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return cdev->private->dma_area->senseid.ciw + ciw_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * ccw_device_get_path_mask() - get currently available paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * @cdev: ccw device to be queried
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * %0 if no subchannel for the device is available,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * else the mask of currently available paths for the ccw device's subchannel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) __u8 ccw_device_get_path_mask(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct subchannel *sch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (!cdev->dev.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return sch->lpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * ccw_device_get_chp_desc() - return newly allocated channel-path descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * @cdev: device to obtain the descriptor for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * @chp_idx: index of the channel path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * On success return a newly allocated copy of the channel-path description
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * data associated with the given channel path. Return %NULL on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int chp_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct subchannel *sch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct chp_id chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) chp_id_init(&chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) chpid.id = sch->schib.pmcw.chpid[chp_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return chp_get_chp_desc(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * ccw_device_get_util_str() - return newly allocated utility strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * @cdev: device to obtain the utility strings for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * @chp_idx: index of the channel path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * On success return a newly allocated copy of the utility strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * associated with the given channel path. Return %NULL on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct subchannel *sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct channel_path *chp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct chp_id chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) u8 *util_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) chp_id_init(&chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) chpid.id = sch->schib.pmcw.chpid[chp_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) chp = chpid_to_chp(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) util_str = kmalloc(sizeof(chp->desc_fmt3.util_str), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (!util_str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) mutex_lock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) memcpy(util_str, chp->desc_fmt3.util_str, sizeof(chp->desc_fmt3.util_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) mutex_unlock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return util_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * ccw_device_get_id() - obtain a ccw device id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * @cdev: device to obtain the id for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * @dev_id: where to fill in the values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) *dev_id = cdev->private->dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) EXPORT_SYMBOL(ccw_device_get_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * ccw_device_tm_start_timeout_key() - perform start function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * @cdev: ccw device on which to perform the start function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * @tcw: transport-command word to be started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * @intparm: user defined parameter to be passed to the interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * @lpm: mask of paths to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * @key: storage key to use for storage access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * @expires: time span in jiffies after which to abort request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * Start the tcw on the given ccw device. Return zero on success, non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) unsigned long intparm, u8 lpm, u8 key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) int expires)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct subchannel *sch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (!sch->schib.pmcw.ena)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (cdev->private->state == DEV_STATE_VERIFY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* Remember to fake irb when finished. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (!cdev->private->flags.fake_irb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) cdev->private->flags.fake_irb = FAKE_TM_IRB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) cdev->private->intparm = intparm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /* There's already a fake I/O around. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (cdev->private->state != DEV_STATE_ONLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* Adjust requested path mask to exclude unusable paths. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (lpm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) lpm &= sch->lpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (lpm == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) rc = cio_tm_start_key(sch, tcw, lpm, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) cdev->private->intparm = intparm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (expires)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ccw_device_set_timeout(cdev, expires);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) EXPORT_SYMBOL(ccw_device_tm_start_timeout_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * ccw_device_tm_start_key() - perform start function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * @cdev: ccw device on which to perform the start function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * @tcw: transport-command word to be started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * @intparm: user defined parameter to be passed to the interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * @lpm: mask of paths to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * @key: storage key to use for storage access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * Start the tcw on the given ccw device. Return zero on success, non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) unsigned long intparm, u8 lpm, u8 key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return ccw_device_tm_start_timeout_key(cdev, tcw, intparm, lpm, key, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) EXPORT_SYMBOL(ccw_device_tm_start_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * ccw_device_tm_start() - perform start function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * @cdev: ccw device on which to perform the start function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * @tcw: transport-command word to be started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * @intparm: user defined parameter to be passed to the interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * @lpm: mask of paths to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * Start the tcw on the given ccw device. Return zero on success, non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int ccw_device_tm_start(struct ccw_device *cdev, struct tcw *tcw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) unsigned long intparm, u8 lpm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return ccw_device_tm_start_key(cdev, tcw, intparm, lpm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) PAGE_DEFAULT_KEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) EXPORT_SYMBOL(ccw_device_tm_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * ccw_device_tm_start_timeout() - perform start function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * @cdev: ccw device on which to perform the start function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * @tcw: transport-command word to be started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * @intparm: user defined parameter to be passed to the interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * @lpm: mask of paths to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * @expires: time span in jiffies after which to abort request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * Start the tcw on the given ccw device. Return zero on success, non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) int ccw_device_tm_start_timeout(struct ccw_device *cdev, struct tcw *tcw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) unsigned long intparm, u8 lpm, int expires)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return ccw_device_tm_start_timeout_key(cdev, tcw, intparm, lpm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) PAGE_DEFAULT_KEY, expires);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) EXPORT_SYMBOL(ccw_device_tm_start_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * ccw_device_get_mdc() - accumulate max data count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * @cdev: ccw device for which the max data count is accumulated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * @mask: mask of paths to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * Return the number of 64K-bytes blocks all paths at least support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * for a transport command. Return value 0 indicates failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct subchannel *sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct channel_path *chp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct chp_id chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) int mdc = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /* Adjust requested path mask to excluded varied off paths. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) mask &= sch->lpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) mask = sch->lpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) chp_id_init(&chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (!(mask & (0x80 >> i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) chpid.id = sch->schib.pmcw.chpid[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) chp = chpid_to_chp(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (!chp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) mutex_lock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (!chp->desc_fmt1.f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) mutex_unlock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (!chp->desc_fmt1.r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) mdc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) mdc = mdc ? min_t(int, mdc, chp->desc_fmt1.mdc) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) chp->desc_fmt1.mdc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) mutex_unlock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return mdc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) EXPORT_SYMBOL(ccw_device_get_mdc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * ccw_device_tm_intrg() - perform interrogate function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * @cdev: ccw device on which to perform the interrogate function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * Perform an interrogate function on the given ccw device. Return zero on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * success, non-zero otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int ccw_device_tm_intrg(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct subchannel *sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (!sch->schib.pmcw.ena)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (cdev->private->state != DEV_STATE_ONLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!scsw_is_tm(&sch->schib.scsw) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_START_PEND))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return cio_tm_intrg(sch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) EXPORT_SYMBOL(ccw_device_tm_intrg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * ccw_device_get_schid() - obtain a subchannel id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * @cdev: device to obtain the id for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * @schid: where to fill in the values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) void ccw_device_get_schid(struct ccw_device *cdev, struct subchannel_id *schid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct subchannel *sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) *schid = sch->schid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) EXPORT_SYMBOL_GPL(ccw_device_get_schid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * ccw_device_pnso() - Perform Network-Subchannel Operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * @cdev: device on which PNSO is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * @pnso_area: request and response block for the operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * @oc: Operation Code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * @resume_token: resume token for multiblock response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * @cnc: Boolean change-notification control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * pnso_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * Returns 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int ccw_device_pnso(struct ccw_device *cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) struct chsc_pnso_area *pnso_area, u8 oc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) struct chsc_pnso_resume_token resume_token, int cnc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct subchannel_id schid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ccw_device_get_schid(cdev, &schid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return chsc_pnso(schid, pnso_area, oc, resume_token, cnc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) EXPORT_SYMBOL_GPL(ccw_device_pnso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * ccw_device_get_cssid() - obtain Channel Subsystem ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * @cdev: device to obtain the CSSID for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * @cssid: The resulting Channel Subsystem ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) int ccw_device_get_cssid(struct ccw_device *cdev, u8 *cssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct device *sch_dev = cdev->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) struct channel_subsystem *css = to_css(sch_dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (css->id_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) *cssid = css->cssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return css->id_valid ? 0 : -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) EXPORT_SYMBOL_GPL(ccw_device_get_cssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * ccw_device_get_iid() - obtain MIF-image ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * @cdev: device to obtain the MIF-image ID for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * @iid: The resulting MIF-image ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) int ccw_device_get_iid(struct ccw_device *cdev, u8 *iid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) struct device *sch_dev = cdev->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) struct channel_subsystem *css = to_css(sch_dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (css->id_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) *iid = css->iid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return css->id_valid ? 0 : -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) EXPORT_SYMBOL_GPL(ccw_device_get_iid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * ccw_device_get_chpid() - obtain Channel Path ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * @cdev: device to obtain the Channel Path ID for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * @chp_idx: Index of the channel path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * @chpid: The resulting Channel Path ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) int ccw_device_get_chpid(struct ccw_device *cdev, int chp_idx, u8 *chpid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct subchannel *sch = to_subchannel(cdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if ((chp_idx < 0) || (chp_idx > 7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) mask = 0x80 >> chp_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (!(sch->schib.pmcw.pim & mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) *chpid = sch->schib.pmcw.chpid[chp_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) EXPORT_SYMBOL_GPL(ccw_device_get_chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * ccw_device_get_chid() - obtain Channel ID associated with specified CHPID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * @cdev: device to obtain the Channel ID for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * @chp_idx: Index of the channel path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * @chid: The resulting Channel ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) int ccw_device_get_chid(struct ccw_device *cdev, int chp_idx, u16 *chid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct chp_id cssid_chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct channel_path *chp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) chp_id_init(&cssid_chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) rc = ccw_device_get_chpid(cdev, chp_idx, &cssid_chpid.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) chp = chpid_to_chp(cssid_chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (!chp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) mutex_lock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (chp->desc_fmt1.flags & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) *chid = chp->desc_fmt1.chid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) mutex_unlock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) EXPORT_SYMBOL_GPL(ccw_device_get_chid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * Allocate zeroed dma coherent 31 bit addressable memory using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * the subchannels dma pool. Maximal size of allocation supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) * is PAGE_SIZE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (!get_device(&cdev->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) addr = cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (IS_ERR_OR_NULL(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) put_device(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) EXPORT_SYMBOL(ccw_device_dma_zalloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) void ccw_device_dma_free(struct ccw_device *cdev, void *cpu_addr, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!cpu_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) cio_gp_dma_free(cdev->private->dma_pool, cpu_addr, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) put_device(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) EXPORT_SYMBOL(ccw_device_dma_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) EXPORT_SYMBOL(ccw_device_set_options_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) EXPORT_SYMBOL(ccw_device_set_options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) EXPORT_SYMBOL(ccw_device_clear_options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) EXPORT_SYMBOL(ccw_device_clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) EXPORT_SYMBOL(ccw_device_halt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) EXPORT_SYMBOL(ccw_device_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) EXPORT_SYMBOL(ccw_device_start_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) EXPORT_SYMBOL(ccw_device_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) EXPORT_SYMBOL(ccw_device_start_timeout_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) EXPORT_SYMBOL(ccw_device_start_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) EXPORT_SYMBOL(ccw_device_get_ciw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) EXPORT_SYMBOL(ccw_device_get_path_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) EXPORT_SYMBOL_GPL(ccw_device_get_util_str);