Merge tag 'media/v6.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[platform/kernel/linux-rpi.git] / block / blk-sysfs.c
index e71b3b4..93d9e9c 100644 (file)
@@ -470,6 +470,9 @@ static ssize_t queue_wb_lat_show(struct request_queue *q, char *page)
        if (!wbt_rq_qos(q))
                return -EINVAL;
 
+       if (wbt_disabled(q))
+               return sprintf(page, "0\n");
+
        return sprintf(page, "%llu\n", div_u64(wbt_get_min_lat(q), 1000));
 }
 
@@ -680,8 +683,8 @@ static struct attribute *queue_attrs[] = {
 static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr,
                                int n)
 {
-       struct request_queue *q =
-               container_of(kobj, struct request_queue, kobj);
+       struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
+       struct request_queue *q = disk->queue;
 
        if (attr == &queue_io_timeout_entry.attr &&
                (!q->mq_ops || !q->mq_ops->timeout))
@@ -707,8 +710,8 @@ static ssize_t
 queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
 {
        struct queue_sysfs_entry *entry = to_queue(attr);
-       struct request_queue *q =
-               container_of(kobj, struct request_queue, kobj);
+       struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
+       struct request_queue *q = disk->queue;
        ssize_t res;
 
        if (!entry->show)
@@ -724,68 +727,19 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
                    const char *page, size_t length)
 {
        struct queue_sysfs_entry *entry = to_queue(attr);
-       struct request_queue *q;
+       struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
+       struct request_queue *q = disk->queue;
        ssize_t res;
 
        if (!entry->store)
                return -EIO;
 
-       q = container_of(kobj, struct request_queue, kobj);
        mutex_lock(&q->sysfs_lock);
        res = entry->store(q, page, length);
        mutex_unlock(&q->sysfs_lock);
        return res;
 }
 
-static void blk_free_queue_rcu(struct rcu_head *rcu_head)
-{
-       struct request_queue *q = container_of(rcu_head, struct request_queue,
-                                              rcu_head);
-
-       kmem_cache_free(blk_get_queue_kmem_cache(blk_queue_has_srcu(q)), q);
-}
-
-/**
- * blk_release_queue - releases all allocated resources of the request_queue
- * @kobj: pointer to a kobject, whose container is a request_queue
- *
- * This function releases all allocated resources of the request queue.
- *
- * The struct request_queue refcount is incremented with blk_get_queue() and
- * decremented with blk_put_queue(). Once the refcount reaches 0 this function
- * is called.
- *
- * Drivers exist which depend on the release of the request_queue to be
- * synchronous, it should not be deferred.
- *
- * Context: can sleep
- */
-static void blk_release_queue(struct kobject *kobj)
-{
-       struct request_queue *q =
-               container_of(kobj, struct request_queue, kobj);
-
-       might_sleep();
-
-       percpu_ref_exit(&q->q_usage_counter);
-
-       if (q->poll_stat)
-               blk_stat_remove_callback(q, q->poll_cb);
-       blk_stat_free_callback(q->poll_cb);
-
-       blk_free_queue_stats(q->stats);
-       kfree(q->poll_stat);
-
-       if (queue_is_mq(q))
-               blk_mq_release(q);
-
-       if (blk_queue_has_srcu(q))
-               cleanup_srcu_struct(q->srcu);
-
-       ida_free(&blk_queue_ida, q->id);
-       call_rcu(&q->rcu_head, blk_free_queue_rcu);
-}
-
 static const struct sysfs_ops queue_sysfs_ops = {
        .show   = queue_attr_show,
        .store  = queue_attr_store,
@@ -796,12 +750,30 @@ static const struct attribute_group *blk_queue_attr_groups[] = {
        NULL
 };
 
-struct kobj_type blk_queue_ktype = {
+static void blk_queue_release(struct kobject *kobj)
+{
+       /* nothing to do here, all data is associated with the parent gendisk */
+}
+
+static struct kobj_type blk_queue_ktype = {
        .default_groups = blk_queue_attr_groups,
        .sysfs_ops      = &queue_sysfs_ops,
-       .release        = blk_release_queue,
+       .release        = blk_queue_release,
 };
 
+static void blk_debugfs_remove(struct gendisk *disk)
+{
+       struct request_queue *q = disk->queue;
+
+       mutex_lock(&q->debugfs_mutex);
+       blk_trace_shutdown(q);
+       debugfs_remove_recursive(q->debugfs_dir);
+       q->debugfs_dir = NULL;
+       q->sched_debugfs_dir = NULL;
+       q->rqos_debugfs_dir = NULL;
+       mutex_unlock(&q->debugfs_mutex);
+}
+
 /**
  * blk_register_queue - register a block layer queue with sysfs
  * @disk: Disk of which the request queue should be registered with sysfs.
@@ -812,47 +784,47 @@ int blk_register_queue(struct gendisk *disk)
        int ret;
 
        mutex_lock(&q->sysfs_dir_lock);
-
-       ret = kobject_add(&q->kobj, &disk_to_dev(disk)->kobj, "queue");
+       kobject_init(&disk->queue_kobj, &blk_queue_ktype);
+       ret = kobject_add(&disk->queue_kobj, &disk_to_dev(disk)->kobj, "queue");
        if (ret < 0)
-               goto unlock;
+               goto out_put_queue_kobj;
 
-       if (queue_is_mq(q))
-               blk_mq_sysfs_register(disk);
+       if (queue_is_mq(q)) {
+               ret = blk_mq_sysfs_register(disk);
+               if (ret)
+                       goto out_put_queue_kobj;
+       }
        mutex_lock(&q->sysfs_lock);
 
        mutex_lock(&q->debugfs_mutex);
-       q->debugfs_dir = debugfs_create_dir(kobject_name(q->kobj.parent),
-                                           blk_debugfs_root);
+       q->debugfs_dir = debugfs_create_dir(disk->disk_name, blk_debugfs_root);
        if (queue_is_mq(q))
                blk_mq_debugfs_register(q);
        mutex_unlock(&q->debugfs_mutex);
 
        ret = disk_register_independent_access_ranges(disk);
        if (ret)
-               goto put_dev;
+               goto out_debugfs_remove;
 
        if (q->elevator) {
                ret = elv_register_queue(q, false);
                if (ret)
-                       goto put_dev;
+                       goto out_unregister_ia_ranges;
        }
 
-       ret = blk_crypto_sysfs_register(q);
+       ret = blk_crypto_sysfs_register(disk);
        if (ret)
-               goto put_dev;
+               goto out_elv_unregister;
 
        blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);
        wbt_enable_default(q);
        blk_throtl_register(disk);
 
        /* Now everything is ready and send out KOBJ_ADD uevent */
-       kobject_uevent(&q->kobj, KOBJ_ADD);
+       kobject_uevent(&disk->queue_kobj, KOBJ_ADD);
        if (q->elevator)
                kobject_uevent(&q->elevator->kobj, KOBJ_ADD);
        mutex_unlock(&q->sysfs_lock);
-
-unlock:
        mutex_unlock(&q->sysfs_dir_lock);
 
        /*
@@ -871,13 +843,16 @@ unlock:
 
        return ret;
 
-put_dev:
+out_elv_unregister:
        elv_unregister_queue(q);
+out_unregister_ia_ranges:
        disk_unregister_independent_access_ranges(disk);
+out_debugfs_remove:
+       blk_debugfs_remove(disk);
        mutex_unlock(&q->sysfs_lock);
+out_put_queue_kobj:
+       kobject_put(&disk->queue_kobj);
        mutex_unlock(&q->sysfs_dir_lock);
-       kobject_del(&q->kobj);
-
        return ret;
 }
 
@@ -915,7 +890,7 @@ void blk_unregister_queue(struct gendisk *disk)
         */
        if (queue_is_mq(q))
                blk_mq_sysfs_unregister(disk);
-       blk_crypto_sysfs_unregister(q);
+       blk_crypto_sysfs_unregister(disk);
 
        mutex_lock(&q->sysfs_lock);
        elv_unregister_queue(q);
@@ -923,15 +898,9 @@ void blk_unregister_queue(struct gendisk *disk)
        mutex_unlock(&q->sysfs_lock);
 
        /* Now that we've deleted all child objects, we can delete the queue. */
-       kobject_uevent(&q->kobj, KOBJ_REMOVE);
-       kobject_del(&q->kobj);
+       kobject_uevent(&disk->queue_kobj, KOBJ_REMOVE);
+       kobject_del(&disk->queue_kobj);
        mutex_unlock(&q->sysfs_dir_lock);
 
-       mutex_lock(&q->debugfs_mutex);
-       blk_trace_shutdown(q);
-       debugfs_remove_recursive(q->debugfs_dir);
-       q->debugfs_dir = NULL;
-       q->sched_debugfs_dir = NULL;
-       q->rqos_debugfs_dir = NULL;
-       mutex_unlock(&q->debugfs_mutex);
+       blk_debugfs_remove(disk);
 }