drm/exynos: Debounce gpio hotplug interrupts
[cascardo/linux.git] / block / genhd.c
index df9816e..fb03e00 100644 (file)
@@ -743,7 +743,7 @@ void __init printk_all_partitions(void)
                struct hd_struct *part;
                char name_buf[BDEVNAME_SIZE];
                char devt_buf[BDEVT_SIZE];
-               u8 uuid[PARTITION_META_INFO_UUIDLTH * 2 + 1];
+               char uuid_buf[PARTITION_META_INFO_UUIDLTH * 2 + 5];
 
                /*
                 * Don't show empty devices or things that have been
@@ -762,14 +762,16 @@ void __init printk_all_partitions(void)
                while ((part = disk_part_iter_next(&piter))) {
                        bool is_part0 = part == &disk->part0;
 
-                       uuid[0] = 0;
+                       uuid_buf[0] = '\0';
                        if (part->info)
-                               part_unpack_uuid(part->info->uuid, uuid);
+                               snprintf(uuid_buf, sizeof(uuid_buf), "%pU",
+                                        part->info->uuid);
 
                        printk("%s%s %10llu %s %s", is_part0 ? "" : "  ",
                               bdevt_str(part_devt(part), devt_buf),
                               (unsigned long long)part->nr_sects >> 1,
-                              disk_name(disk, part->partno, name_buf), uuid);
+                              disk_name(disk, part->partno, name_buf),
+                              uuid_buf);
                        if (is_part0) {
                                if (disk->driverfs_dev != NULL &&
                                    disk->driverfs_dev->driver != NULL)
@@ -1457,19 +1459,19 @@ void disk_block_events(struct gendisk *disk)
        mutex_unlock(&ev->block_mutex);
 }
 
+/**
+ * CONTEXT: ev->lock should be held when calling this function
+ */
 static void __disk_unblock_events(struct gendisk *disk, bool check_now)
 {
        struct disk_events *ev = disk->ev;
        unsigned long intv;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ev->lock, flags);
 
        if (WARN_ON_ONCE(ev->block <= 0))
-               goto out_unlock;
+               return;
 
        if (--ev->block)
-               goto out_unlock;
+               return;
 
        /*
         * Not exactly a latency critical operation, set poll timer
@@ -1481,8 +1483,6 @@ static void __disk_unblock_events(struct gendisk *disk, bool check_now)
                queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
        else if (intv)
                queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv);
-out_unlock:
-       spin_unlock_irqrestore(&ev->lock, flags);
 }
 
 /**
@@ -1497,8 +1497,14 @@ out_unlock:
  */
 void disk_unblock_events(struct gendisk *disk)
 {
-       if (disk->ev)
+       struct disk_events *ev = disk->ev;
+       unsigned long flags;
+
+       if (ev) {
+               spin_lock_irqsave(&ev->lock, flags);
                __disk_unblock_events(disk, false);
+               spin_unlock_irqrestore(&ev->lock, flags);
+       }
 }
 
 /**
@@ -1561,12 +1567,18 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
 
        /* uncondtionally schedule event check and wait for it to finish */
        disk_block_events(disk);
-       queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
+       /* We need to put the work on system_nrt_wq here since there is a
+        * deadlock that happens while probing a usb device while suspending. If
+        * we put work on a freezable worqueue here, a usb probe will wait here
+        * until the workqueue is unfrozen during suspend. Since suspend waits
+        * on all probes to complete, we have a deadlock
+        */
+       queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
        flush_delayed_work(&ev->dwork);
+       spin_lock_irq(&ev->lock);
        __disk_unblock_events(disk, false);
 
        /* then, fetch and clear pending events */
-       spin_lock_irq(&ev->lock);
        WARN_ON_ONCE(ev->clearing & mask);      /* cleared by workfn */
        pending = ev->pending & mask;
        ev->pending &= ~mask;
@@ -1680,7 +1692,9 @@ static ssize_t disk_events_poll_msecs_store(struct device *dev,
 
        disk_block_events(disk);
        disk->ev->poll_msecs = intv;
+       spin_lock_irq(&disk->ev->lock);
        __disk_unblock_events(disk, true);
+       spin_unlock_irq(&disk->ev->lock);
 
        return count;
 }
@@ -1780,7 +1794,9 @@ static void disk_add_events(struct gendisk *disk)
         * Block count is initialized to 1 and the following initial
         * unblock kicks it into action.
         */
+       spin_lock_irq(&disk->ev->lock);
        __disk_unblock_events(disk, true);
+       spin_unlock_irq(&disk->ev->lock);
 }
 
 static void disk_del_events(struct gendisk *disk)