Merge branch 'for-linus' of git://git.alsa-project.org/alsa-kernel
[pandora-kernel.git] / drivers / s390 / block / dasd.c
index ccf46c9..1b6c52e 100644 (file)
@@ -63,6 +63,7 @@ static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
  */
 static wait_queue_head_t dasd_init_waitq;
 static wait_queue_head_t dasd_flush_wq;
+static wait_queue_head_t generic_waitq;
 
 /*
  * Allocate memory for a new device structure.
@@ -925,6 +926,8 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
        struct dasd_ccw_req *cqr;
        struct dasd_device *device;
 
+       if (!intparm)
+               return;
        cqr = (struct dasd_ccw_req *) intparm;
        if (cqr->status != DASD_CQR_IN_IO) {
                MESSAGE(KERN_DEBUG,
@@ -976,31 +979,30 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
        if (IS_ERR(irb)) {
                switch (PTR_ERR(irb)) {
                case -EIO:
-                       dasd_handle_killed_request(cdev, intparm);
                        break;
                case -ETIMEDOUT:
                        printk(KERN_WARNING"%s(%s): request timed out\n",
-                              __FUNCTION__, cdev->dev.bus_id);
-                       //FIXME - dasd uses own timeout interface...
+                              __func__, cdev->dev.bus_id);
                        break;
                default:
                        printk(KERN_WARNING"%s(%s): unknown error %ld\n",
-                              __FUNCTION__, cdev->dev.bus_id, PTR_ERR(irb));
+                              __func__, cdev->dev.bus_id, PTR_ERR(irb));
                }
+               dasd_handle_killed_request(cdev, intparm);
                return;
        }
 
        now = get_clock();
 
        DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x",
-                 cdev->dev.bus_id, ((irb->scsw.cstat<<8)|irb->scsw.dstat),
-                 (unsigned int) intparm);
+                 cdev->dev.bus_id, ((irb->scsw.cmd.cstat << 8) |
+                 irb->scsw.cmd.dstat), (unsigned int) intparm);
 
        /* check for unsolicited interrupts */
        cqr = (struct dasd_ccw_req *) intparm;
-       if (!cqr || ((irb->scsw.cc == 1) &&
-                    (irb->scsw.fctl & SCSW_FCTL_START_FUNC) &&
-                    (irb->scsw.stctl & SCSW_STCTL_STATUS_PEND)) ) {
+       if (!cqr || ((irb->scsw.cmd.cc == 1) &&
+                    (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) &&
+                    (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND))) {
                if (cqr && cqr->status == DASD_CQR_IN_IO)
                        cqr->status = DASD_CQR_QUEUED;
                device = dasd_device_from_cdev_locked(cdev);
@@ -1023,7 +1025,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
 
        /* Check for clear pending */
        if (cqr->status == DASD_CQR_CLEAR_PENDING &&
-           irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
+           irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC) {
                cqr->status = DASD_CQR_CLEARED;
                dasd_device_clear_timer(device);
                wake_up(&dasd_flush_wq);
@@ -1039,11 +1041,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
                return;
        }
        DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p",
-                     ((irb->scsw.cstat << 8) | irb->scsw.dstat), cqr);
+                     ((irb->scsw.cmd.cstat << 8) | irb->scsw.cmd.dstat), cqr);
        next = NULL;
        expires = 0;
-       if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
-           irb->scsw.cstat == 0 && !irb->esw.esw0.erw.cons) {
+       if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
+           irb->scsw.cmd.cstat == 0 && !irb->esw.esw0.erw.cons) {
                /* request was completed successfully */
                cqr->status = DASD_CQR_SUCCESS;
                cqr->stopclk = now;
@@ -1150,11 +1152,15 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
        struct list_head *l, *n;
        struct dasd_ccw_req *cqr;
        struct dasd_block *block;
+       void (*callback)(struct dasd_ccw_req *, void *data);
+       void *callback_data;
 
        list_for_each_safe(l, n, final_queue) {
                cqr = list_entry(l, struct dasd_ccw_req, devlist);
                list_del_init(&cqr->devlist);
                block = cqr->block;
+               callback = cqr->callback;
+               callback_data = cqr->callback_data;
                if (block)
                        spin_lock_bh(&block->queue_lock);
                switch (cqr->status) {
@@ -1175,7 +1181,7 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
                        BUG();
                }
                if (cqr->callback != NULL)
-                       (cqr->callback)(cqr, cqr->callback_data);
+                       (callback)(cqr, callback_data);
                if (block)
                        spin_unlock_bh(&block->queue_lock);
        }
@@ -1405,17 +1411,15 @@ static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr)
  */
 int dasd_sleep_on(struct dasd_ccw_req *cqr)
 {
-       wait_queue_head_t wait_q;
        struct dasd_device *device;
        int rc;
 
        device = cqr->startdev;
 
-       init_waitqueue_head (&wait_q);
        cqr->callback = dasd_wakeup_cb;
-       cqr->callback_data = (void *) &wait_q;
+       cqr->callback_data = (void *) &generic_waitq;
        dasd_add_request_tail(cqr);
-       wait_event(wait_q, _wait_for_wakeup(cqr));
+       wait_event(generic_waitq, _wait_for_wakeup(cqr));
 
        /* Request status is either done or failed. */
        rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
@@ -1428,20 +1432,18 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr)
  */
 int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr)
 {
-       wait_queue_head_t wait_q;
        struct dasd_device *device;
        int rc;
 
        device = cqr->startdev;
-       init_waitqueue_head (&wait_q);
        cqr->callback = dasd_wakeup_cb;
-       cqr->callback_data = (void *) &wait_q;
+       cqr->callback_data = (void *) &generic_waitq;
        dasd_add_request_tail(cqr);
-       rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr));
+       rc = wait_event_interruptible(generic_waitq, _wait_for_wakeup(cqr));
        if (rc == -ERESTARTSYS) {
                dasd_cancel_req(cqr);
                /* wait (non-interruptible) for final status */
-               wait_event(wait_q, _wait_for_wakeup(cqr));
+               wait_event(generic_waitq, _wait_for_wakeup(cqr));
        }
        rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
        return rc;
@@ -1465,7 +1467,6 @@ static inline int _dasd_term_running_cqr(struct dasd_device *device)
 
 int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
 {
-       wait_queue_head_t wait_q;
        struct dasd_device *device;
        int rc;
 
@@ -1477,9 +1478,8 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
                return rc;
        }
 
-       init_waitqueue_head (&wait_q);
        cqr->callback = dasd_wakeup_cb;
-       cqr->callback_data = (void *) &wait_q;
+       cqr->callback_data = (void *) &generic_waitq;
        cqr->status = DASD_CQR_QUEUED;
        list_add(&cqr->devlist, &device->ccw_queue);
 
@@ -1488,7 +1488,7 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
 
        spin_unlock_irq(get_ccwdev_lock(device->cdev));
 
-       wait_event(wait_q, _wait_for_wakeup(cqr));
+       wait_event(generic_waitq, _wait_for_wakeup(cqr));
 
        /* Request status is either done or failed. */
        rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
@@ -1956,6 +1956,7 @@ static int dasd_alloc_queue(struct dasd_block *block)
        block->request_queue->queuedata = block;
 
        elevator_exit(block->request_queue->elevator);
+       block->request_queue->elevator = NULL;
        rc = elevator_init(block->request_queue, "deadline");
        if (rc) {
                blk_cleanup_queue(block->request_queue);
@@ -2298,9 +2299,8 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
         * in the other openers.
         */
        if (device->block) {
-               struct dasd_block *block = device->block;
-               max_count = block->bdev ? 0 : -1;
-               open_count = (int) atomic_read(&block->open_count);
+               max_count = device->block->bdev ? 0 : -1;
+               open_count = atomic_read(&device->block->open_count);
                if (open_count > max_count) {
                        if (open_count > 0)
                                printk(KERN_WARNING "Can't offline dasd "
@@ -2429,6 +2429,7 @@ static int __init dasd_init(void)
 
        init_waitqueue_head(&dasd_init_waitq);
        init_waitqueue_head(&dasd_flush_wq);
+       init_waitqueue_head(&generic_waitq);
 
        /* register 'common' DASD debug area, used for all DBF_XXX calls */
        dasd_debug_area = debug_register("dasd", 1, 1, 8 * sizeof(long));