]> err.no Git - linux-2.6/blobdiff - drivers/s390/cio/device_ops.c
Merge branch 'for-linus' of git://git.infradead.org/ubi-2.6
[linux-2.6] / drivers / s390 / cio / device_ops.c
index b39c1fa48acd22cac1fd92990da9699193913510..16f59fcb66b13938480a497f4d2deeda2d9fa669 100644 (file)
 
 #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"
 
-int
-ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
+int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
 {
        /*
        * The flag usage is mutal exclusive ...
@@ -39,6 +40,33 @@ ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
        return 0;
 }
 
+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;
+}
+
+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;
+}
+
 int
 ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
 {
@@ -302,7 +330,7 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb)
        wake_up(&cdev->private->wait_q);
 }
 
-static inline int
+static int
 __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, __u8 lpm)
 {
        int ret;
@@ -316,9 +344,9 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
                        ccw_device_set_timeout(cdev, 0);
                if (ret == -EBUSY) {
                        /* Try again later. */
-                       spin_unlock_irq(&sch->lock);
+                       spin_unlock_irq(sch->lock);
                        msleep(10);
-                       spin_lock_irq(&sch->lock);
+                       spin_lock_irq(sch->lock);
                        continue;
                }
                if (ret != 0)
@@ -326,12 +354,12 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
                        break;
                /* Wait for end of request. */
                cdev->private->intparm = magic;
-               spin_unlock_irq(&sch->lock);
+               spin_unlock_irq(sch->lock);
                wait_event(cdev->private->wait_q,
                           (cdev->private->intparm == -EIO) ||
                           (cdev->private->intparm == -EAGAIN) ||
                           (cdev->private->intparm == 0));
-               spin_lock_irq(&sch->lock);
+               spin_lock_irq(sch->lock);
                /* Check at least for channel end / device end */
                if (cdev->private->intparm == -EIO) {
                        /* Non-retryable error. */
@@ -342,9 +370,9 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
                        /* Success. */
                        break;
                /* Try again later. */
-               spin_unlock_irq(&sch->lock);
+               spin_unlock_irq(sch->lock);
                msleep(10);
-               spin_lock_irq(&sch->lock);
+               spin_lock_irq(sch->lock);
        } while (1);
 
        return ret;
@@ -389,7 +417,7 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length)
                return ret;
        }
 
-       spin_lock_irq(&sch->lock);
+       spin_lock_irq(sch->lock);
        /* Save interrupt handler. */
        handler = cdev->handler;
        /* Temporarily install own handler. */
@@ -406,7 +434,7 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length)
 
        /* Restore interrupt handler. */
        cdev->handler = handler;
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
 
        clear_normalized_cda (rdc_ccw);
        kfree(rdc_ccw);
@@ -463,7 +491,7 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp
        rcd_ccw->count = ciw->count;
        rcd_ccw->flags = CCW_FLAG_SLI;
 
-       spin_lock_irq(&sch->lock);
+       spin_lock_irq(sch->lock);
        /* Save interrupt handler. */
        handler = cdev->handler;
        /* Temporarily install own handler. */
@@ -480,7 +508,7 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp
 
        /* Restore interrupt handler. */
        cdev->handler = handler;
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
 
        /*
         * on success we update the user input parms
@@ -537,7 +565,7 @@ ccw_device_stlck(struct ccw_device *cdev)
                kfree(buf);
                return -ENOMEM;
        }
-       spin_lock_irqsave(&sch->lock, flags);
+       spin_lock_irqsave(sch->lock, flags);
        ret = cio_enable_subchannel(sch, 3);
        if (ret)
                goto out_unlock;
@@ -559,9 +587,9 @@ ccw_device_stlck(struct ccw_device *cdev)
                goto out_unlock;
        }
        cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND;
-       spin_unlock_irqrestore(&sch->lock, flags);
+       spin_unlock_irqrestore(sch->lock, flags);
        wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0);
-       spin_lock_irqsave(&sch->lock, flags);
+       spin_lock_irqsave(sch->lock, flags);
        cio_disable_subchannel(sch); //FIXME: return code?
        if ((cdev->private->irb.scsw.dstat !=
             (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
@@ -572,7 +600,7 @@ ccw_device_stlck(struct ccw_device *cdev)
 out_unlock:
        kfree(buf);
        kfree(buf2);
-       spin_unlock_irqrestore(&sch->lock, flags);
+       spin_unlock_irqrestore(sch->lock, flags);
        return ret;
 }
 
@@ -580,9 +608,12 @@ void *
 ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
 {
        struct subchannel *sch;
+       struct chp_id chpid;
 
        sch = to_subchannel(cdev->dev.parent);
-       return chsc_get_chp_desc(sch, chp_no);
+       chp_id_init(&chpid);
+       chpid.id = sch->schib.pmcw.chpid[chp_no];
+       return chp_get_chp_desc(chpid);
 }
 
 // FIXME: these have to go:
@@ -601,7 +632,9 @@ _ccw_device_get_device_number(struct ccw_device *cdev)
 
 
 MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(ccw_device_set_options_mask);
 EXPORT_SYMBOL(ccw_device_set_options);
+EXPORT_SYMBOL(ccw_device_clear_options);
 EXPORT_SYMBOL(ccw_device_clear);
 EXPORT_SYMBOL(ccw_device_halt);
 EXPORT_SYMBOL(ccw_device_resume);