linux/drivers/s390/cio/device_ops.c
<<
>>
Prefs
   1/*
   2 *  drivers/s390/cio/device_ops.c
   3 *
   4 *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
   5 *                       IBM Corporation
   6 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
   7 *               Cornelia Huck (cornelia.huck@de.ibm.com)
   8 */
   9#include <linux/module.h>
  10#include <linux/init.h>
  11#include <linux/errno.h>
  12#include <linux/slab.h>
  13#include <linux/list.h>
  14#include <linux/device.h>
  15#include <linux/delay.h>
  16
  17#include <asm/ccwdev.h>
  18#include <asm/idals.h>
  19#include <asm/chpid.h>
  20
  21#include "cio.h"
  22#include "cio_debug.h"
  23#include "css.h"
  24#include "chsc.h"
  25#include "device.h"
  26#include "chp.h"
  27
  28/**
  29 * ccw_device_set_options_mask() - set some options and unset the rest
  30 * @cdev: device for which the options are to be set
  31 * @flags: options to be set
  32 *
  33 * All flags specified in @flags are set, all flags not specified in @flags
  34 * are cleared.
  35 * Returns:
  36 *   %0 on success, -%EINVAL on an invalid flag combination.
  37 */
  38int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
  39{
  40       /*
  41        * The flag usage is mutal exclusive ...
  42        */
  43        if ((flags & CCWDEV_EARLY_NOTIFICATION) &&
  44            (flags & CCWDEV_REPORT_ALL))
  45                return -EINVAL;
  46        cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
  47        cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0;
  48        cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0;
  49        cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0;
  50        return 0;
  51}
  52
  53/**
  54 * ccw_device_set_options() - set some options
  55 * @cdev: device for which the options are to be set
  56 * @flags: options to be set
  57 *
  58 * All flags specified in @flags are set, the remainder is left untouched.
  59 * Returns:
  60 *   %0 on success, -%EINVAL if an invalid flag combination would ensue.
  61 */
  62int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
  63{
  64       /*
  65        * The flag usage is mutal exclusive ...
  66        */
  67        if (((flags & CCWDEV_EARLY_NOTIFICATION) &&
  68            (flags & CCWDEV_REPORT_ALL)) ||
  69            ((flags & CCWDEV_EARLY_NOTIFICATION) &&
  70             cdev->private->options.repall) ||
  71            ((flags & CCWDEV_REPORT_ALL) &&
  72             cdev->private->options.fast))
  73                return -EINVAL;
  74        cdev->private->options.fast |= (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
  75        cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0;
  76        cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0;
  77        cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0;
  78        return 0;
  79}
  80
  81/**
  82 * ccw_device_clear_options() - clear some options
  83 * @cdev: device for which the options are to be cleared
  84 * @flags: options to be cleared
  85 *
  86 * All flags specified in @flags are cleared, the remainder is left untouched.
  87 */
  88void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
  89{
  90        cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0;
  91        cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0;
  92        cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0;
  93        cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;
  94}
  95
  96/**
  97 * ccw_device_clear() - terminate I/O request processing
  98 * @cdev: target ccw device
  99 * @intparm: interruption parameter; value is only used if no I/O is
 100 *           outstanding, otherwise the intparm associated with the I/O request
 101 *           is returned
 102 *
 103 * ccw_device_clear() calls csch on @cdev's subchannel.
 104 * Returns:
 105 *  %0 on success,
 106 *  -%ENODEV on device not operational,
 107 *  -%EINVAL on invalid device state.
 108 * Context:
 109 *  Interrupts disabled, ccw device lock held
 110 */
 111int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
 112{
 113        struct subchannel *sch;
 114        int ret;
 115
 116        if (!cdev)
 117                return -ENODEV;
 118        if (cdev->private->state == DEV_STATE_NOT_OPER)
 119                return -ENODEV;
 120        if (cdev->private->state != DEV_STATE_ONLINE &&
 121            cdev->private->state != DEV_STATE_W4SENSE)
 122                return -EINVAL;
 123        sch = to_subchannel(cdev->dev.parent);
 124        if (!sch)
 125                return -ENODEV;
 126        ret = cio_clear(sch);
 127        if (ret == 0)
 128                cdev->private->intparm = intparm;
 129        return ret;
 130}
 131
 132/**
 133 * ccw_device_start_key() - start a s390 channel program with key
 134 * @cdev: target ccw device
 135 * @cpa: logical start address of channel program
 136 * @intparm: user specific interruption parameter; will be presented back to
 137 *           @cdev's interrupt handler. Allows a device driver to associate
 138 *           the interrupt with a particular I/O request.
 139 * @lpm: defines the channel path to be used for a specific I/O request. A
 140 *       value of 0 will make cio use the opm.
 141 * @key: storage key to be used for the I/O
 142 * @flags: additional flags; defines the action to be performed for I/O
 143 *         processing.
 144 *
 145 * Start a S/390 channel program. When the interrupt arrives, the
 146 * IRQ handler is called, either immediately, delayed (dev-end missing,
 147 * or sense required) or never (no IRQ handler registered).
 148 * Returns:
 149 *  %0, if the operation was successful;
 150 *  -%EBUSY, if the device is busy, or status pending;
 151 *  -%EACCES, if no path specified in @lpm is operational;
 152 *  -%ENODEV, if the device is not operational.
 153 * Context:
 154 *  Interrupts disabled, ccw device lock held
 155 */
 156int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
 157                         unsigned long intparm, __u8 lpm, __u8 key,
 158                         unsigned long flags)
 159{
 160        struct subchannel *sch;
 161        int ret;
 162
 163        if (!cdev)
 164                return -ENODEV;
 165        sch = to_subchannel(cdev->dev.parent);
 166        if (!sch)
 167                return -ENODEV;
 168        if (cdev->private->state == DEV_STATE_NOT_OPER)
 169                return -ENODEV;
 170        if (cdev->private->state == DEV_STATE_VERIFY ||
 171            cdev->private->state == DEV_STATE_CLEAR_VERIFY) {
 172                /* Remember to fake irb when finished. */
 173                if (!cdev->private->flags.fake_irb) {
 174                        cdev->private->flags.fake_irb = 1;
 175                        cdev->private->intparm = intparm;
 176                        return 0;
 177                } else
 178                        /* There's already a fake I/O around. */
 179                        return -EBUSY;
 180        }
 181        if (cdev->private->state != DEV_STATE_ONLINE ||
 182            ((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
 183             !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
 184            cdev->private->flags.doverify)
 185                return -EBUSY;
 186        ret = cio_set_options (sch, flags);
 187        if (ret)
 188                return ret;
 189        /* Adjust requested path mask to excluded varied off paths. */
 190        if (lpm) {
 191                lpm &= sch->opm;
 192                if (lpm == 0)
 193                        return -EACCES;
 194        }
 195        ret = cio_start_key (sch, cpa, lpm, key);
 196        if (ret == 0)
 197                cdev->private->intparm = intparm;
 198        return ret;
 199}
 200
 201/**
 202 * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key
 203 * @cdev: target ccw device
 204 * @cpa: logical start address of channel program
 205 * @intparm: user specific interruption parameter; will be presented back to
 206 *           @cdev's interrupt handler. Allows a device driver to associate
 207 *           the interrupt with a particular I/O request.
 208 * @lpm: defines the channel path to be used for a specific I/O request. A
 209 *       value of 0 will make cio use the opm.
 210 * @key: storage key to be used for the I/O
 211 * @flags: additional flags; defines the action to be performed for I/O
 212 *         processing.
 213 * @expires: timeout value in jiffies
 214 *
 215 * Start a S/390 channel program. When the interrupt arrives, the
 216 * IRQ handler is called, either immediately, delayed (dev-end missing,
 217 * or sense required) or never (no IRQ handler registered).
 218 * This function notifies the device driver if the channel program has not
 219 * completed during the time specified by @expires. If a timeout occurs, the
 220 * channel program is terminated via xsch, hsch or csch, and the device's
 221 * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
 222 * Returns:
 223 *  %0, if the operation was successful;
 224 *  -%EBUSY, if the device is busy, or status pending;
 225 *  -%EACCES, if no path specified in @lpm is operational;
 226 *  -%ENODEV, if the device is not operational.
 227 * Context:
 228 *  Interrupts disabled, ccw device lock held
 229 */
 230int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
 231                                 unsigned long intparm, __u8 lpm, __u8 key,
 232                                 unsigned long flags, int expires)
 233{
 234        int ret;
 235
 236        if (!cdev)
 237                return -ENODEV;
 238        ccw_device_set_timeout(cdev, expires);
 239        ret = ccw_device_start_key(cdev, cpa, intparm, lpm, key, flags);
 240        if (ret != 0)
 241                ccw_device_set_timeout(cdev, 0);
 242        return ret;
 243}
 244
 245/**
 246 * ccw_device_start() - start a s390 channel program
 247 * @cdev: target ccw device
 248 * @cpa: logical start address of channel program
 249 * @intparm: user specific interruption parameter; will be presented back to
 250 *           @cdev's interrupt handler. Allows a device driver to associate
 251 *           the interrupt with a particular I/O request.
 252 * @lpm: defines the channel path to be used for a specific I/O request. A
 253 *       value of 0 will make cio use the opm.
 254 * @flags: additional flags; defines the action to be performed for I/O
 255 *         processing.
 256 *
 257 * Start a S/390 channel program. When the interrupt arrives, the
 258 * IRQ handler is called, either immediately, delayed (dev-end missing,
 259 * or sense required) or never (no IRQ handler registered).
 260 * Returns:
 261 *  %0, if the operation was successful;
 262 *  -%EBUSY, if the device is busy, or status pending;
 263 *  -%EACCES, if no path specified in @lpm is operational;
 264 *  -%ENODEV, if the device is not operational.
 265 * Context:
 266 *  Interrupts disabled, ccw device lock held
 267 */
 268int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa,
 269                     unsigned long intparm, __u8 lpm, unsigned long flags)
 270{
 271        return ccw_device_start_key(cdev, cpa, intparm, lpm,
 272                                    PAGE_DEFAULT_KEY, flags);
 273}
 274
 275/**
 276 * ccw_device_start_timeout() - start a s390 channel program with timeout
 277 * @cdev: target ccw device
 278 * @cpa: logical start address of channel program
 279 * @intparm: user specific interruption parameter; will be presented back to
 280 *           @cdev's interrupt handler. Allows a device driver to associate
 281 *           the interrupt with a particular I/O request.
 282 * @lpm: defines the channel path to be used for a specific I/O request. A
 283 *       value of 0 will make cio use the opm.
 284 * @flags: additional flags; defines the action to be performed for I/O
 285 *         processing.
 286 * @expires: timeout value in jiffies
 287 *
 288 * Start a S/390 channel program. When the interrupt arrives, the
 289 * IRQ handler is called, either immediately, delayed (dev-end missing,
 290 * or sense required) or never (no IRQ handler registered).
 291 * This function notifies the device driver if the channel program has not
 292 * completed during the time specified by @expires. If a timeout occurs, the
 293 * channel program is terminated via xsch, hsch or csch, and the device's
 294 * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
 295 * Returns:
 296 *  %0, if the operation was successful;
 297 *  -%EBUSY, if the device is busy, or status pending;
 298 *  -%EACCES, if no path specified in @lpm is operational;
 299 *  -%ENODEV, if the device is not operational.
 300 * Context:
 301 *  Interrupts disabled, ccw device lock held
 302 */
 303int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa,
 304                             unsigned long intparm, __u8 lpm,
 305                             unsigned long flags, int expires)
 306{
 307        return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm,
 308                                            PAGE_DEFAULT_KEY, flags,
 309                                            expires);
 310}
 311
 312
 313/**
 314 * ccw_device_halt() - halt I/O request processing
 315 * @cdev: target ccw device
 316 * @intparm: interruption parameter; value is only used if no I/O is
 317 *           outstanding, otherwise the intparm associated with the I/O request
 318 *           is returned
 319 *
 320 * ccw_device_halt() calls hsch on @cdev's subchannel.
 321 * Returns:
 322 *  %0 on success,
 323 *  -%ENODEV on device not operational,
 324 *  -%EINVAL on invalid device state,
 325 *  -%EBUSY on device busy or interrupt pending.
 326 * Context:
 327 *  Interrupts disabled, ccw device lock held
 328 */
 329int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
 330{
 331        struct subchannel *sch;
 332        int ret;
 333
 334        if (!cdev)
 335                return -ENODEV;
 336        if (cdev->private->state == DEV_STATE_NOT_OPER)
 337                return -ENODEV;
 338        if (cdev->private->state != DEV_STATE_ONLINE &&
 339            cdev->private->state != DEV_STATE_W4SENSE)
 340                return -EINVAL;
 341        sch = to_subchannel(cdev->dev.parent);
 342        if (!sch)
 343                return -ENODEV;
 344        ret = cio_halt(sch);
 345        if (ret == 0)
 346                cdev->private->intparm = intparm;
 347        return ret;
 348}
 349
 350/**
 351 * ccw_device_resume() - resume channel program execution
 352 * @cdev: target ccw device
 353 *
 354 * ccw_device_resume() calls rsch on @cdev's subchannel.
 355 * Returns:
 356 *  %0 on success,
 357 *  -%ENODEV on device not operational,
 358 *  -%EINVAL on invalid device state,
 359 *  -%EBUSY on device busy or interrupt pending.
 360 * Context:
 361 *  Interrupts disabled, ccw device lock held
 362 */
 363int ccw_device_resume(struct ccw_device *cdev)
 364{
 365        struct subchannel *sch;
 366
 367        if (!cdev)
 368                return -ENODEV;
 369        sch = to_subchannel(cdev->dev.parent);
 370        if (!sch)
 371                return -ENODEV;
 372        if (cdev->private->state == DEV_STATE_NOT_OPER)
 373                return -ENODEV;
 374        if (cdev->private->state != DEV_STATE_ONLINE ||
 375            !(sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED))
 376                return -EINVAL;
 377        return cio_resume(sch);
 378}
 379
 380/*
 381 * Pass interrupt to device driver.
 382 */
 383int
 384ccw_device_call_handler(struct ccw_device *cdev)
 385{
 386        struct subchannel *sch;
 387        unsigned int stctl;
 388        int ending_status;
 389
 390        sch = to_subchannel(cdev->dev.parent);
 391
 392        /*
 393         * we allow for the device action handler if .
 394         *  - we received ending status
 395         *  - the action handler requested to see all interrupts
 396         *  - we received an intermediate status
 397         *  - fast notification was requested (primary status)
 398         *  - unsolicited interrupts
 399         */
 400        stctl = cdev->private->irb.scsw.stctl;
 401        ending_status = (stctl & SCSW_STCTL_SEC_STATUS) ||
 402                (stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) ||
 403                (stctl == SCSW_STCTL_STATUS_PEND);
 404        if (!ending_status &&
 405            !cdev->private->options.repall &&
 406            !(stctl & SCSW_STCTL_INTER_STATUS) &&
 407            !(cdev->private->options.fast &&
 408              (stctl & SCSW_STCTL_PRIM_STATUS)))
 409                return 0;
 410
 411        /* Clear pending timers for device driver initiated I/O. */
 412        if (ending_status)
 413                ccw_device_set_timeout(cdev, 0);
 414        /*
 415         * Now we are ready to call the device driver interrupt handler.
 416         */
 417        if (cdev->handler)
 418                cdev->handler(cdev, cdev->private->intparm,
 419                              &cdev->private->irb);
 420
 421        /*
 422         * Clear the old and now useless interrupt response block.
 423         */
 424        memset(&cdev->private->irb, 0, sizeof(struct irb));
 425
 426        return 1;
 427}
 428
 429/**
 430 * ccw_device_get_ciw() - Search for CIW command in extended sense data.
 431 * @cdev: ccw device to inspect
 432 * @ct: command type to look for
 433 *
 434 * During SenseID, command information words (CIWs) describing special
 435 * commands available to the device may have been stored in the extended
 436 * sense data. This function searches for CIWs of a specified command
 437 * type in the extended sense data.
 438 * Returns:
 439 *  %NULL if no extended sense data has been stored or if no CIW of the
 440 *  specified command type could be found,
 441 *  else a pointer to the CIW of the specified command type.
 442 */
 443struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct)
 444{
 445        int ciw_cnt;
 446
 447        if (cdev->private->flags.esid == 0)
 448                return NULL;
 449        for (ciw_cnt = 0; ciw_cnt < MAX_CIWS; ciw_cnt++)
 450                if (cdev->private->senseid.ciw[ciw_cnt].ct == ct)
 451                        return cdev->private->senseid.ciw + ciw_cnt;
 452        return NULL;
 453}
 454
 455/**
 456 * ccw_device_get_path_mask() - get currently available paths
 457 * @cdev: ccw device to be queried
 458 * Returns:
 459 *  %0 if no subchannel for the device is available,
 460 *  else the mask of currently available paths for the ccw device's subchannel.
 461 */
 462__u8 ccw_device_get_path_mask(struct ccw_device *cdev)
 463{
 464        struct subchannel *sch;
 465
 466        sch = to_subchannel(cdev->dev.parent);
 467        if (!sch)
 468                return 0;
 469        else
 470                return sch->lpm;
 471}
 472
 473/*
 474 * Try to break the lock on a boxed device.
 475 */
 476int
 477ccw_device_stlck(struct ccw_device *cdev)
 478{
 479        void *buf, *buf2;
 480        unsigned long flags;
 481        struct subchannel *sch;
 482        int ret;
 483
 484        if (!cdev)
 485                return -ENODEV;
 486
 487        if (cdev->drv && !cdev->private->options.force)
 488                return -EINVAL;
 489
 490        sch = to_subchannel(cdev->dev.parent);
 491        
 492        CIO_TRACE_EVENT(2, "stl lock");
 493        CIO_TRACE_EVENT(2, cdev->dev.bus_id);
 494
 495        buf = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
 496        if (!buf)
 497                return -ENOMEM;
 498        buf2 = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
 499        if (!buf2) {
 500                kfree(buf);
 501                return -ENOMEM;
 502        }
 503        spin_lock_irqsave(sch->lock, flags);
 504        ret = cio_enable_subchannel(sch, 3);
 505        if (ret)
 506                goto out_unlock;
 507        /*
 508         * Setup ccw. We chain an unconditional reserve and a release so we
 509         * only break the lock.
 510         */
 511        cdev->private->iccws[0].cmd_code = CCW_CMD_STLCK;
 512        cdev->private->iccws[0].cda = (__u32) __pa(buf);
 513        cdev->private->iccws[0].count = 32;
 514        cdev->private->iccws[0].flags = CCW_FLAG_CC;
 515        cdev->private->iccws[1].cmd_code = CCW_CMD_RELEASE;
 516        cdev->private->iccws[1].cda = (__u32) __pa(buf2);
 517        cdev->private->iccws[1].count = 32;
 518        cdev->private->iccws[1].flags = 0;
 519        ret = cio_start(sch, cdev->private->iccws, 0);
 520        if (ret) {
 521                cio_disable_subchannel(sch); //FIXME: return code?
 522                goto out_unlock;
 523        }
 524        cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND;
 525        spin_unlock_irqrestore(sch->lock, flags);
 526        wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0);
 527        spin_lock_irqsave(sch->lock, flags);
 528        cio_disable_subchannel(sch); //FIXME: return code?
 529        if ((cdev->private->irb.scsw.dstat !=
 530             (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
 531            (cdev->private->irb.scsw.cstat != 0))
 532                ret = -EIO;
 533        /* Clear irb. */
 534        memset(&cdev->private->irb, 0, sizeof(struct irb));
 535out_unlock:
 536        kfree(buf);
 537        kfree(buf2);
 538        spin_unlock_irqrestore(sch->lock, flags);
 539        return ret;
 540}
 541
 542void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
 543{
 544        struct subchannel *sch;
 545        struct chp_id chpid;
 546
 547        sch = to_subchannel(cdev->dev.parent);
 548        chp_id_init(&chpid);
 549        chpid.id = sch->schib.pmcw.chpid[chp_no];
 550        return chp_get_chp_desc(chpid);
 551}
 552
 553/**
 554 * ccw_device_get_id - obtain a ccw device id
 555 * @cdev: device to obtain the id for
 556 * @dev_id: where to fill in the values
 557 */
 558void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id)
 559{
 560        *dev_id = cdev->private->dev_id;
 561}
 562EXPORT_SYMBOL(ccw_device_get_id);
 563
 564// FIXME: these have to go:
 565
 566int
 567_ccw_device_get_subchannel_number(struct ccw_device *cdev)
 568{
 569        return cdev->private->schid.sch_no;
 570}
 571
 572
 573MODULE_LICENSE("GPL");
 574EXPORT_SYMBOL(ccw_device_set_options_mask);
 575EXPORT_SYMBOL(ccw_device_set_options);
 576EXPORT_SYMBOL(ccw_device_clear_options);
 577EXPORT_SYMBOL(ccw_device_clear);
 578EXPORT_SYMBOL(ccw_device_halt);
 579EXPORT_SYMBOL(ccw_device_resume);
 580EXPORT_SYMBOL(ccw_device_start_timeout);
 581EXPORT_SYMBOL(ccw_device_start);
 582EXPORT_SYMBOL(ccw_device_start_timeout_key);
 583EXPORT_SYMBOL(ccw_device_start_key);
 584EXPORT_SYMBOL(ccw_device_get_ciw);
 585EXPORT_SYMBOL(ccw_device_get_path_mask);
 586EXPORT_SYMBOL(_ccw_device_get_subchannel_number);
 587EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);
 588
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.