]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/s390/block/dasd.c
Merge tag 'v2.6.37' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / s390 / block / dasd.c
index 8373ca0de8e0b00484f40d48c5813e600da920c2..fb613d70c2cbb32e381bba6951568bc217ac8d5c 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/hdreg.h>
 #include <linux/async.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
@@ -1100,16 +1099,30 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
        cqr = (struct dasd_ccw_req *) intparm;
        if (!cqr || ((scsw_cc(&irb->scsw) == 1) &&
                     (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) &&
-                    (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))) {
+                    ((scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND) ||
+                     (scsw_stctl(&irb->scsw) == (SCSW_STCTL_STATUS_PEND |
+                                                 SCSW_STCTL_ALERT_STATUS))))) {
                if (cqr && cqr->status == DASD_CQR_IN_IO)
                        cqr->status = DASD_CQR_QUEUED;
+               if (cqr)
+                       memcpy(&cqr->irb, irb, sizeof(*irb));
                device = dasd_device_from_cdev_locked(cdev);
-               if (!IS_ERR(device)) {
-                       dasd_device_clear_timer(device);
-                       device->discipline->handle_unsolicited_interrupt(device,
-                                                                        irb);
+               if (IS_ERR(device))
+                       return;
+               /* ignore unsolicited interrupts for DIAG discipline */
+               if (device->discipline == dasd_diag_discipline_pointer) {
                        dasd_put_device(device);
+                       return;
                }
+               device->discipline->dump_sense_dbf(device, irb,
+                                                  "unsolicited");
+               if ((device->features & DASD_FEATURE_ERPLOG))
+                       device->discipline->dump_sense(device, cqr,
+                                                      irb);
+               dasd_device_clear_timer(device);
+               device->discipline->handle_unsolicited_interrupt(device,
+                                                                irb);
+               dasd_put_device(device);
                return;
        }
 
@@ -2197,7 +2210,6 @@ static void dasd_setup_queue(struct dasd_block *block)
         */
        blk_queue_max_segment_size(block->request_queue, PAGE_SIZE);
        blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1);
-       blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN);
 }
 
 /*
@@ -2236,7 +2248,6 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
        if (!block)
                return -ENODEV;
 
-       lock_kernel();
        base = block->base;
        atomic_inc(&block->open_count);
        if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) {
@@ -2271,14 +2282,12 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
                goto out;
        }
 
-       unlock_kernel();
        return 0;
 
 out:
        module_put(base->discipline->owner);
 unlock:
        atomic_dec(&block->open_count);
-       unlock_kernel();
        return rc;
 }
 
@@ -2286,10 +2295,8 @@ static int dasd_release(struct gendisk *disk, fmode_t mode)
 {
        struct dasd_block *block = disk->private_data;
 
-       lock_kernel();
        atomic_dec(&block->open_count);
        module_put(block->base->discipline->owner);
-       unlock_kernel();
        return 0;
 }