LCOV - code coverage report
Current view: top level - drivers/scsi - hosts.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 2 292 0.7 %
Date: 2021-04-22 12:43:58 Functions: 1 21 4.8 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  *  hosts.c Copyright (C) 1992 Drew Eckhardt
       4             :  *          Copyright (C) 1993, 1994, 1995 Eric Youngdale
       5             :  *          Copyright (C) 2002-2003 Christoph Hellwig
       6             :  *
       7             :  *  mid to lowlevel SCSI driver interface
       8             :  *      Initial versions: Drew Eckhardt
       9             :  *      Subsequent revisions: Eric Youngdale
      10             :  *
      11             :  *  <drew@colorado.edu>
      12             :  *
      13             :  *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
      14             :  *  Added QLOGIC QLA1280 SCSI controller kernel host support. 
      15             :  *     August 4, 1999 Fred Lewis, Intel DuPont
      16             :  *
      17             :  *  Updated to reflect the new initialization scheme for the higher 
      18             :  *  level of scsi drivers (sd/sr/st)
      19             :  *  September 17, 2000 Torben Mathiasen <tmm@image.dk>
      20             :  *
      21             :  *  Restructured scsi_host lists and associated functions.
      22             :  *  September 04, 2002 Mike Anderson (andmike@us.ibm.com)
      23             :  */
      24             : 
      25             : #include <linux/module.h>
      26             : #include <linux/blkdev.h>
      27             : #include <linux/kernel.h>
      28             : #include <linux/slab.h>
      29             : #include <linux/kthread.h>
      30             : #include <linux/string.h>
      31             : #include <linux/mm.h>
      32             : #include <linux/init.h>
      33             : #include <linux/completion.h>
      34             : #include <linux/transport_class.h>
      35             : #include <linux/platform_device.h>
      36             : #include <linux/pm_runtime.h>
      37             : #include <linux/idr.h>
      38             : #include <scsi/scsi_device.h>
      39             : #include <scsi/scsi_host.h>
      40             : #include <scsi/scsi_transport.h>
      41             : #include <scsi/scsi_cmnd.h>
      42             : 
      43             : #include "scsi_priv.h"
      44             : #include "scsi_logging.h"
      45             : 
      46             : 
      47             : static int shost_eh_deadline = -1;
      48             : 
      49             : module_param_named(eh_deadline, shost_eh_deadline, int, S_IRUGO|S_IWUSR);
      50             : MODULE_PARM_DESC(eh_deadline,
      51             :                  "SCSI EH timeout in seconds (should be between 0 and 2^31-1)");
      52             : 
      53             : static DEFINE_IDA(host_index_ida);
      54             : 
      55             : 
      56           0 : static void scsi_host_cls_release(struct device *dev)
      57             : {
      58           0 :         put_device(&class_to_shost(dev)->shost_gendev);
      59           0 : }
      60             : 
      61             : static struct class shost_class = {
      62             :         .name           = "scsi_host",
      63             :         .dev_release    = scsi_host_cls_release,
      64             : };
      65             : 
      66             : /**
      67             :  *      scsi_host_set_state - Take the given host through the host state model.
      68             :  *      @shost: scsi host to change the state of.
      69             :  *      @state: state to change to.
      70             :  *
      71             :  *      Returns zero if unsuccessful or an error if the requested
      72             :  *      transition is illegal.
      73             :  **/
      74           0 : int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
      75             : {
      76           0 :         enum scsi_host_state oldstate = shost->shost_state;
      77             : 
      78           0 :         if (state == oldstate)
      79             :                 return 0;
      80             : 
      81           0 :         switch (state) {
      82           0 :         case SHOST_CREATED:
      83             :                 /* There are no legal states that come back to
      84             :                  * created.  This is the manually initialised start
      85             :                  * state */
      86           0 :                 goto illegal;
      87             : 
      88           0 :         case SHOST_RUNNING:
      89           0 :                 switch (oldstate) {
      90             :                 case SHOST_CREATED:
      91             :                 case SHOST_RECOVERY:
      92             :                         break;
      93           0 :                 default:
      94           0 :                         goto illegal;
      95             :                 }
      96             :                 break;
      97             : 
      98           0 :         case SHOST_RECOVERY:
      99           0 :                 switch (oldstate) {
     100             :                 case SHOST_RUNNING:
     101             :                         break;
     102           0 :                 default:
     103           0 :                         goto illegal;
     104             :                 }
     105             :                 break;
     106             : 
     107           0 :         case SHOST_CANCEL:
     108           0 :                 switch (oldstate) {
     109             :                 case SHOST_CREATED:
     110             :                 case SHOST_RUNNING:
     111             :                 case SHOST_CANCEL_RECOVERY:
     112             :                         break;
     113           0 :                 default:
     114           0 :                         goto illegal;
     115             :                 }
     116             :                 break;
     117             : 
     118           0 :         case SHOST_DEL:
     119           0 :                 switch (oldstate) {
     120             :                 case SHOST_CANCEL:
     121             :                 case SHOST_DEL_RECOVERY:
     122             :                         break;
     123           0 :                 default:
     124           0 :                         goto illegal;
     125             :                 }
     126             :                 break;
     127             : 
     128           0 :         case SHOST_CANCEL_RECOVERY:
     129           0 :                 switch (oldstate) {
     130             :                 case SHOST_CANCEL:
     131             :                 case SHOST_RECOVERY:
     132             :                         break;
     133           0 :                 default:
     134           0 :                         goto illegal;
     135             :                 }
     136             :                 break;
     137             : 
     138           0 :         case SHOST_DEL_RECOVERY:
     139           0 :                 switch (oldstate) {
     140             :                 case SHOST_CANCEL_RECOVERY:
     141             :                         break;
     142           0 :                 default:
     143           0 :                         goto illegal;
     144             :                 }
     145             :                 break;
     146             :         }
     147           0 :         shost->shost_state = state;
     148           0 :         return 0;
     149             : 
     150           0 :  illegal:
     151             :         SCSI_LOG_ERROR_RECOVERY(1,
     152             :                                 shost_printk(KERN_ERR, shost,
     153             :                                              "Illegal host state transition"
     154             :                                              "%s->%s\n",
     155             :                                              scsi_host_state_name(oldstate),
     156             :                                              scsi_host_state_name(state)));
     157             :         return -EINVAL;
     158             : }
     159             : 
     160             : /**
     161             :  * scsi_remove_host - remove a scsi host
     162             :  * @shost:      a pointer to a scsi host to remove
     163             :  **/
     164           0 : void scsi_remove_host(struct Scsi_Host *shost)
     165             : {
     166           0 :         unsigned long flags;
     167             : 
     168           0 :         mutex_lock(&shost->scan_mutex);
     169           0 :         spin_lock_irqsave(shost->host_lock, flags);
     170           0 :         if (scsi_host_set_state(shost, SHOST_CANCEL))
     171           0 :                 if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) {
     172           0 :                         spin_unlock_irqrestore(shost->host_lock, flags);
     173           0 :                         mutex_unlock(&shost->scan_mutex);
     174           0 :                         return;
     175             :                 }
     176           0 :         spin_unlock_irqrestore(shost->host_lock, flags);
     177             : 
     178           0 :         scsi_autopm_get_host(shost);
     179           0 :         flush_workqueue(shost->tmf_work_q);
     180           0 :         scsi_forget_host(shost);
     181           0 :         mutex_unlock(&shost->scan_mutex);
     182           0 :         scsi_proc_host_rm(shost);
     183             : 
     184           0 :         spin_lock_irqsave(shost->host_lock, flags);
     185           0 :         if (scsi_host_set_state(shost, SHOST_DEL))
     186           0 :                 BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY));
     187           0 :         spin_unlock_irqrestore(shost->host_lock, flags);
     188             : 
     189           0 :         transport_unregister_device(&shost->shost_gendev);
     190           0 :         device_unregister(&shost->shost_dev);
     191           0 :         device_del(&shost->shost_gendev);
     192             : }
     193             : EXPORT_SYMBOL(scsi_remove_host);
     194             : 
     195             : /**
     196             :  * scsi_add_host_with_dma - add a scsi host with dma device
     197             :  * @shost:      scsi host pointer to add
     198             :  * @dev:        a struct device of type scsi class
     199             :  * @dma_dev:    dma device for the host
     200             :  *
     201             :  * Note: You rarely need to worry about this unless you're in a
     202             :  * virtualised host environments, so use the simpler scsi_add_host()
     203             :  * function instead.
     204             :  *
     205             :  * Return value: 
     206             :  *      0 on success / != 0 for error
     207             :  **/
     208           0 : int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
     209             :                            struct device *dma_dev)
     210             : {
     211           0 :         struct scsi_host_template *sht = shost->hostt;
     212           0 :         int error = -EINVAL;
     213             : 
     214           0 :         shost_printk(KERN_INFO, shost, "%s\n",
     215             :                         sht->info ? sht->info(shost) : sht->name);
     216             : 
     217           0 :         if (!shost->can_queue) {
     218           0 :                 shost_printk(KERN_ERR, shost,
     219             :                              "can_queue = 0 no longer supported\n");
     220           0 :                 goto fail;
     221             :         }
     222             : 
     223           0 :         error = scsi_init_sense_cache(shost);
     224           0 :         if (error)
     225           0 :                 goto fail;
     226             : 
     227           0 :         error = scsi_mq_setup_tags(shost);
     228           0 :         if (error)
     229           0 :                 goto fail;
     230             : 
     231           0 :         if (!shost->shost_gendev.parent)
     232           0 :                 shost->shost_gendev.parent = dev ? dev : &platform_bus;
     233           0 :         if (!dma_dev)
     234           0 :                 dma_dev = shost->shost_gendev.parent;
     235             : 
     236           0 :         shost->dma_dev = dma_dev;
     237             : 
     238             :         /*
     239             :          * Increase usage count temporarily here so that calling
     240             :          * scsi_autopm_put_host() will trigger runtime idle if there is
     241             :          * nothing else preventing suspending the device.
     242             :          */
     243           0 :         pm_runtime_get_noresume(&shost->shost_gendev);
     244           0 :         pm_runtime_set_active(&shost->shost_gendev);
     245           0 :         pm_runtime_enable(&shost->shost_gendev);
     246           0 :         device_enable_async_suspend(&shost->shost_gendev);
     247             : 
     248           0 :         error = device_add(&shost->shost_gendev);
     249           0 :         if (error)
     250           0 :                 goto out_disable_runtime_pm;
     251             : 
     252           0 :         scsi_host_set_state(shost, SHOST_RUNNING);
     253           0 :         get_device(shost->shost_gendev.parent);
     254             : 
     255           0 :         device_enable_async_suspend(&shost->shost_dev);
     256             : 
     257           0 :         error = device_add(&shost->shost_dev);
     258           0 :         if (error)
     259           0 :                 goto out_del_gendev;
     260             : 
     261           0 :         get_device(&shost->shost_gendev);
     262             : 
     263           0 :         if (shost->transportt->host_size) {
     264           0 :                 shost->shost_data = kzalloc(shost->transportt->host_size,
     265             :                                          GFP_KERNEL);
     266           0 :                 if (shost->shost_data == NULL) {
     267           0 :                         error = -ENOMEM;
     268           0 :                         goto out_del_dev;
     269             :                 }
     270             :         }
     271             : 
     272           0 :         if (shost->transportt->create_work_queue) {
     273           0 :                 snprintf(shost->work_q_name, sizeof(shost->work_q_name),
     274             :                          "scsi_wq_%d", shost->host_no);
     275           0 :                 shost->work_q = alloc_workqueue("%s",
     276             :                         WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
     277             :                         1, shost->work_q_name);
     278             : 
     279           0 :                 if (!shost->work_q) {
     280           0 :                         error = -EINVAL;
     281           0 :                         goto out_free_shost_data;
     282             :                 }
     283             :         }
     284             : 
     285           0 :         error = scsi_sysfs_add_host(shost);
     286           0 :         if (error)
     287           0 :                 goto out_destroy_host;
     288             : 
     289             :         scsi_proc_host_add(shost);
     290           0 :         scsi_autopm_put_host(shost);
     291             :         return error;
     292             : 
     293           0 :  out_destroy_host:
     294           0 :         if (shost->work_q)
     295           0 :                 destroy_workqueue(shost->work_q);
     296           0 :  out_free_shost_data:
     297           0 :         kfree(shost->shost_data);
     298           0 :  out_del_dev:
     299           0 :         device_del(&shost->shost_dev);
     300           0 :  out_del_gendev:
     301           0 :         device_del(&shost->shost_gendev);
     302           0 :  out_disable_runtime_pm:
     303           0 :         device_disable_async_suspend(&shost->shost_gendev);
     304           0 :         pm_runtime_disable(&shost->shost_gendev);
     305           0 :         pm_runtime_set_suspended(&shost->shost_gendev);
     306           0 :         pm_runtime_put_noidle(&shost->shost_gendev);
     307           0 :         scsi_mq_destroy_tags(shost);
     308             :  fail:
     309             :         return error;
     310             : }
     311             : EXPORT_SYMBOL(scsi_add_host_with_dma);
     312             : 
     313           0 : static void scsi_host_dev_release(struct device *dev)
     314             : {
     315           0 :         struct Scsi_Host *shost = dev_to_shost(dev);
     316           0 :         struct device *parent = dev->parent;
     317             : 
     318           0 :         scsi_proc_hostdir_rm(shost->hostt);
     319             : 
     320             :         /* Wait for functions invoked through call_rcu(&shost->rcu, ...) */
     321           0 :         rcu_barrier();
     322             : 
     323           0 :         if (shost->tmf_work_q)
     324           0 :                 destroy_workqueue(shost->tmf_work_q);
     325           0 :         if (shost->ehandler)
     326           0 :                 kthread_stop(shost->ehandler);
     327           0 :         if (shost->work_q)
     328           0 :                 destroy_workqueue(shost->work_q);
     329             : 
     330           0 :         if (shost->shost_state == SHOST_CREATED) {
     331             :                 /*
     332             :                  * Free the shost_dev device name here if scsi_host_alloc()
     333             :                  * and scsi_host_put() have been called but neither
     334             :                  * scsi_host_add() nor scsi_host_remove() has been called.
     335             :                  * This avoids that the memory allocated for the shost_dev
     336             :                  * name is leaked.
     337             :                  */
     338           0 :                 kfree(dev_name(&shost->shost_dev));
     339             :         }
     340             : 
     341           0 :         if (shost->tag_set.tags)
     342           0 :                 scsi_mq_destroy_tags(shost);
     343             : 
     344           0 :         kfree(shost->shost_data);
     345             : 
     346           0 :         ida_simple_remove(&host_index_ida, shost->host_no);
     347             : 
     348           0 :         if (parent)
     349           0 :                 put_device(parent);
     350           0 :         kfree(shost);
     351           0 : }
     352             : 
     353             : static struct device_type scsi_host_type = {
     354             :         .name =         "scsi_host",
     355             :         .release =      scsi_host_dev_release,
     356             : };
     357             : 
     358             : /**
     359             :  * scsi_host_alloc - register a scsi host adapter instance.
     360             :  * @sht:        pointer to scsi host template
     361             :  * @privsize:   extra bytes to allocate for driver
     362             :  *
     363             :  * Note:
     364             :  *      Allocate a new Scsi_Host and perform basic initialization.
     365             :  *      The host is not published to the scsi midlayer until scsi_add_host
     366             :  *      is called.
     367             :  *
     368             :  * Return value:
     369             :  *      Pointer to a new Scsi_Host
     370             :  **/
     371           0 : struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
     372             : {
     373           0 :         struct Scsi_Host *shost;
     374           0 :         gfp_t gfp_mask = GFP_KERNEL;
     375           0 :         int index;
     376             : 
     377           0 :         if (sht->unchecked_isa_dma && privsize)
     378           0 :                 gfp_mask |= __GFP_DMA;
     379             : 
     380           0 :         shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
     381           0 :         if (!shost)
     382             :                 return NULL;
     383             : 
     384           0 :         shost->host_lock = &shost->default_lock;
     385           0 :         spin_lock_init(shost->host_lock);
     386           0 :         shost->shost_state = SHOST_CREATED;
     387           0 :         INIT_LIST_HEAD(&shost->__devices);
     388           0 :         INIT_LIST_HEAD(&shost->__targets);
     389           0 :         INIT_LIST_HEAD(&shost->eh_cmd_q);
     390           0 :         INIT_LIST_HEAD(&shost->starved_list);
     391           0 :         init_waitqueue_head(&shost->host_wait);
     392           0 :         mutex_init(&shost->scan_mutex);
     393             : 
     394           0 :         index = ida_simple_get(&host_index_ida, 0, 0, GFP_KERNEL);
     395           0 :         if (index < 0)
     396           0 :                 goto fail_kfree;
     397           0 :         shost->host_no = index;
     398             : 
     399           0 :         shost->dma_channel = 0xff;
     400             : 
     401             :         /* These three are default values which can be overridden */
     402           0 :         shost->max_channel = 0;
     403           0 :         shost->max_id = 8;
     404           0 :         shost->max_lun = 8;
     405             : 
     406             :         /* Give each shost a default transportt */
     407           0 :         shost->transportt = &blank_transport_template;
     408             : 
     409             :         /*
     410             :          * All drivers right now should be able to handle 12 byte
     411             :          * commands.  Every so often there are requests for 16 byte
     412             :          * commands, but individual low-level drivers need to certify that
     413             :          * they actually do something sensible with such commands.
     414             :          */
     415           0 :         shost->max_cmd_len = 12;
     416           0 :         shost->hostt = sht;
     417           0 :         shost->this_id = sht->this_id;
     418           0 :         shost->can_queue = sht->can_queue;
     419           0 :         shost->sg_tablesize = sht->sg_tablesize;
     420           0 :         shost->sg_prot_tablesize = sht->sg_prot_tablesize;
     421           0 :         shost->cmd_per_lun = sht->cmd_per_lun;
     422           0 :         shost->unchecked_isa_dma = sht->unchecked_isa_dma;
     423           0 :         shost->no_write_same = sht->no_write_same;
     424           0 :         shost->host_tagset = sht->host_tagset;
     425             : 
     426           0 :         if (shost_eh_deadline == -1 || !sht->eh_host_reset_handler)
     427           0 :                 shost->eh_deadline = -1;
     428           0 :         else if ((ulong) shost_eh_deadline * HZ > INT_MAX) {
     429           0 :                 shost_printk(KERN_WARNING, shost,
     430             :                              "eh_deadline %u too large, setting to %u\n",
     431             :                              shost_eh_deadline, INT_MAX / HZ);
     432           0 :                 shost->eh_deadline = INT_MAX;
     433             :         } else
     434           0 :                 shost->eh_deadline = shost_eh_deadline * HZ;
     435             : 
     436           0 :         if (sht->supported_mode == MODE_UNKNOWN)
     437             :                 /* means we didn't set it ... default to INITIATOR */
     438           0 :                 shost->active_mode = MODE_INITIATOR;
     439             :         else
     440           0 :                 shost->active_mode = sht->supported_mode;
     441             : 
     442           0 :         if (sht->max_host_blocked)
     443           0 :                 shost->max_host_blocked = sht->max_host_blocked;
     444             :         else
     445           0 :                 shost->max_host_blocked = SCSI_DEFAULT_HOST_BLOCKED;
     446             : 
     447             :         /*
     448             :          * If the driver imposes no hard sector transfer limit, start at
     449             :          * machine infinity initially.
     450             :          */
     451           0 :         if (sht->max_sectors)
     452           0 :                 shost->max_sectors = sht->max_sectors;
     453             :         else
     454           0 :                 shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS;
     455             : 
     456           0 :         if (sht->max_segment_size)
     457           0 :                 shost->max_segment_size = sht->max_segment_size;
     458             :         else
     459           0 :                 shost->max_segment_size = BLK_MAX_SEGMENT_SIZE;
     460             : 
     461             :         /*
     462             :          * assume a 4GB boundary, if not set
     463             :          */
     464           0 :         if (sht->dma_boundary)
     465           0 :                 shost->dma_boundary = sht->dma_boundary;
     466             :         else
     467           0 :                 shost->dma_boundary = 0xffffffff;
     468             : 
     469           0 :         if (sht->virt_boundary_mask)
     470           0 :                 shost->virt_boundary_mask = sht->virt_boundary_mask;
     471             : 
     472           0 :         device_initialize(&shost->shost_gendev);
     473           0 :         dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
     474           0 :         shost->shost_gendev.bus = &scsi_bus_type;
     475           0 :         shost->shost_gendev.type = &scsi_host_type;
     476             : 
     477           0 :         device_initialize(&shost->shost_dev);
     478           0 :         shost->shost_dev.parent = &shost->shost_gendev;
     479           0 :         shost->shost_dev.class = &shost_class;
     480           0 :         dev_set_name(&shost->shost_dev, "host%d", shost->host_no);
     481           0 :         shost->shost_dev.groups = scsi_sysfs_shost_attr_groups;
     482             : 
     483           0 :         shost->ehandler = kthread_run(scsi_error_handler, shost,
     484             :                         "scsi_eh_%d", shost->host_no);
     485           0 :         if (IS_ERR(shost->ehandler)) {
     486           0 :                 shost_printk(KERN_WARNING, shost,
     487             :                         "error handler thread failed to spawn, error = %ld\n",
     488             :                         PTR_ERR(shost->ehandler));
     489           0 :                 goto fail_index_remove;
     490             :         }
     491             : 
     492           0 :         shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d",
     493             :                                         WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS,
     494             :                                            1, shost->host_no);
     495           0 :         if (!shost->tmf_work_q) {
     496           0 :                 shost_printk(KERN_WARNING, shost,
     497             :                              "failed to create tmf workq\n");
     498           0 :                 goto fail_kthread;
     499             :         }
     500             :         scsi_proc_hostdir_add(shost->hostt);
     501             :         return shost;
     502             : 
     503           0 :  fail_kthread:
     504           0 :         kthread_stop(shost->ehandler);
     505           0 :  fail_index_remove:
     506           0 :         ida_simple_remove(&host_index_ida, shost->host_no);
     507           0 :  fail_kfree:
     508           0 :         kfree(shost);
     509           0 :         return NULL;
     510             : }
     511             : EXPORT_SYMBOL(scsi_host_alloc);
     512             : 
     513           0 : static int __scsi_host_match(struct device *dev, const void *data)
     514             : {
     515           0 :         struct Scsi_Host *p;
     516           0 :         const unsigned short *hostnum = data;
     517             : 
     518           0 :         p = class_to_shost(dev);
     519           0 :         return p->host_no == *hostnum;
     520             : }
     521             : 
     522             : /**
     523             :  * scsi_host_lookup - get a reference to a Scsi_Host by host no
     524             :  * @hostnum:    host number to locate
     525             :  *
     526             :  * Return value:
     527             :  *      A pointer to located Scsi_Host or NULL.
     528             :  *
     529             :  *      The caller must do a scsi_host_put() to drop the reference
     530             :  *      that scsi_host_get() took. The put_device() below dropped
     531             :  *      the reference from class_find_device().
     532             :  **/
     533           0 : struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
     534             : {
     535           0 :         struct device *cdev;
     536           0 :         struct Scsi_Host *shost = NULL;
     537             : 
     538           0 :         cdev = class_find_device(&shost_class, NULL, &hostnum,
     539             :                                  __scsi_host_match);
     540           0 :         if (cdev) {
     541           0 :                 shost = scsi_host_get(class_to_shost(cdev));
     542           0 :                 put_device(cdev);
     543             :         }
     544           0 :         return shost;
     545             : }
     546             : EXPORT_SYMBOL(scsi_host_lookup);
     547             : 
     548             : /**
     549             :  * scsi_host_get - inc a Scsi_Host ref count
     550             :  * @shost:      Pointer to Scsi_Host to inc.
     551             :  **/
     552           0 : struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost)
     553             : {
     554           0 :         if ((shost->shost_state == SHOST_DEL) ||
     555           0 :                 !get_device(&shost->shost_gendev))
     556           0 :                 return NULL;
     557             :         return shost;
     558             : }
     559             : EXPORT_SYMBOL(scsi_host_get);
     560             : 
     561           0 : static bool scsi_host_check_in_flight(struct request *rq, void *data,
     562             :                                       bool reserved)
     563             : {
     564           0 :         int *count = data;
     565           0 :         struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
     566             : 
     567           0 :         if (test_bit(SCMD_STATE_INFLIGHT, &cmd->state))
     568           0 :                 (*count)++;
     569             : 
     570           0 :         return true;
     571             : }
     572             : 
     573             : /**
     574             :  * scsi_host_busy - Return the host busy counter
     575             :  * @shost:      Pointer to Scsi_Host to inc.
     576             :  **/
     577           0 : int scsi_host_busy(struct Scsi_Host *shost)
     578             : {
     579           0 :         int cnt = 0;
     580             : 
     581           0 :         blk_mq_tagset_busy_iter(&shost->tag_set,
     582             :                                 scsi_host_check_in_flight, &cnt);
     583           0 :         return cnt;
     584             : }
     585             : EXPORT_SYMBOL(scsi_host_busy);
     586             : 
     587             : /**
     588             :  * scsi_host_put - dec a Scsi_Host ref count
     589             :  * @shost:      Pointer to Scsi_Host to dec.
     590             :  **/
     591           0 : void scsi_host_put(struct Scsi_Host *shost)
     592             : {
     593           0 :         put_device(&shost->shost_gendev);
     594           0 : }
     595             : EXPORT_SYMBOL(scsi_host_put);
     596             : 
     597           1 : int scsi_init_hosts(void)
     598             : {
     599           1 :         return class_register(&shost_class);
     600             : }
     601             : 
     602           0 : void scsi_exit_hosts(void)
     603             : {
     604           0 :         class_unregister(&shost_class);
     605           0 :         ida_destroy(&host_index_ida);
     606           0 : }
     607             : 
     608           0 : int scsi_is_host_device(const struct device *dev)
     609             : {
     610           0 :         return dev->type == &scsi_host_type;
     611             : }
     612             : EXPORT_SYMBOL(scsi_is_host_device);
     613             : 
     614             : /**
     615             :  * scsi_queue_work - Queue work to the Scsi_Host workqueue.
     616             :  * @shost:      Pointer to Scsi_Host.
     617             :  * @work:       Work to queue for execution.
     618             :  *
     619             :  * Return value:
     620             :  *      1 - work queued for execution
     621             :  *      0 - work is already queued
     622             :  *      -EINVAL - work queue doesn't exist
     623             :  **/
     624           0 : int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work)
     625             : {
     626           0 :         if (unlikely(!shost->work_q)) {
     627           0 :                 shost_printk(KERN_ERR, shost,
     628             :                         "ERROR: Scsi host '%s' attempted to queue scsi-work, "
     629             :                         "when no workqueue created.\n", shost->hostt->name);
     630           0 :                 dump_stack();
     631             : 
     632           0 :                 return -EINVAL;
     633             :         }
     634             : 
     635           0 :         return queue_work(shost->work_q, work);
     636             : }
     637             : EXPORT_SYMBOL_GPL(scsi_queue_work);
     638             : 
     639             : /**
     640             :  * scsi_flush_work - Flush a Scsi_Host's workqueue.
     641             :  * @shost:      Pointer to Scsi_Host.
     642             :  **/
     643           0 : void scsi_flush_work(struct Scsi_Host *shost)
     644             : {
     645           0 :         if (!shost->work_q) {
     646           0 :                 shost_printk(KERN_ERR, shost,
     647             :                         "ERROR: Scsi host '%s' attempted to flush scsi-work, "
     648             :                         "when no workqueue created.\n", shost->hostt->name);
     649           0 :                 dump_stack();
     650           0 :                 return;
     651             :         }
     652             : 
     653           0 :         flush_workqueue(shost->work_q);
     654             : }
     655             : EXPORT_SYMBOL_GPL(scsi_flush_work);
     656             : 
     657           0 : static bool complete_all_cmds_iter(struct request *rq, void *data, bool rsvd)
     658             : {
     659           0 :         struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);
     660           0 :         int status = *(int *)data;
     661             : 
     662           0 :         scsi_dma_unmap(scmd);
     663           0 :         scmd->result = status << 16;
     664           0 :         scmd->scsi_done(scmd);
     665           0 :         return true;
     666             : }
     667             : 
     668             : /**
     669             :  * scsi_host_complete_all_commands - Terminate all running commands
     670             :  * @shost:      Scsi Host on which commands should be terminated
     671             :  * @status:     Status to be set for the terminated commands
     672             :  *
     673             :  * There is no protection against modification of the number
     674             :  * of outstanding commands. It is the responsibility of the
     675             :  * caller to ensure that concurrent I/O submission and/or
     676             :  * completion is stopped when calling this function.
     677             :  */
     678           0 : void scsi_host_complete_all_commands(struct Scsi_Host *shost, int status)
     679             : {
     680           0 :         blk_mq_tagset_busy_iter(&shost->tag_set, complete_all_cmds_iter,
     681             :                                 &status);
     682           0 : }
     683             : EXPORT_SYMBOL_GPL(scsi_host_complete_all_commands);
     684             : 
     685             : struct scsi_host_busy_iter_data {
     686             :         bool (*fn)(struct scsi_cmnd *, void *, bool);
     687             :         void *priv;
     688             : };
     689             : 
     690           0 : static bool __scsi_host_busy_iter_fn(struct request *req, void *priv,
     691             :                                    bool reserved)
     692             : {
     693           0 :         struct scsi_host_busy_iter_data *iter_data = priv;
     694           0 :         struct scsi_cmnd *sc = blk_mq_rq_to_pdu(req);
     695             : 
     696           0 :         return iter_data->fn(sc, iter_data->priv, reserved);
     697             : }
     698             : 
     699             : /**
     700             :  * scsi_host_busy_iter - Iterate over all busy commands
     701             :  * @shost:      Pointer to Scsi_Host.
     702             :  * @fn:         Function to call on each busy command
     703             :  * @priv:       Data pointer passed to @fn
     704             :  *
     705             :  * If locking against concurrent command completions is required
     706             :  * ithas to be provided by the caller
     707             :  **/
     708           0 : void scsi_host_busy_iter(struct Scsi_Host *shost,
     709             :                          bool (*fn)(struct scsi_cmnd *, void *, bool),
     710             :                          void *priv)
     711             : {
     712           0 :         struct scsi_host_busy_iter_data iter_data = {
     713             :                 .fn = fn,
     714             :                 .priv = priv,
     715             :         };
     716             : 
     717           0 :         blk_mq_tagset_busy_iter(&shost->tag_set, __scsi_host_busy_iter_fn,
     718             :                                 &iter_data);
     719           0 : }
     720             : EXPORT_SYMBOL_GPL(scsi_host_busy_iter);

Generated by: LCOV version 1.14