hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/scsi/hosts.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * hosts.c Copyright (C) 1992 Drew Eckhardt
34 * Copyright (C) 1993, 1994, 1995 Eric Youngdale
....@@ -37,6 +38,7 @@
3738 #include <scsi/scsi_device.h>
3839 #include <scsi/scsi_host.h>
3940 #include <scsi/scsi_transport.h>
41
+#include <scsi/scsi_cmnd.h>
4042
4143 #include "scsi_priv.h"
4244 #include "scsi_logging.h"
....@@ -178,6 +180,7 @@
178180 scsi_forget_host(shost);
179181 mutex_unlock(&shost->scan_mutex);
180182 scsi_proc_host_rm(shost);
183
+ scsi_proc_hostdir_rm(shost->hostt);
181184
182185 spin_lock_irqsave(shost->host_lock, flags);
183186 if (scsi_host_set_state(shost, SHOST_DEL))
....@@ -226,18 +229,9 @@
226229 if (error)
227230 goto fail;
228231
229
- if (shost_use_blk_mq(shost)) {
230
- error = scsi_mq_setup_tags(shost);
231
- if (error)
232
- goto fail;
233
- } else {
234
- shost->bqt = blk_init_tags(shost->can_queue,
235
- shost->hostt->tag_alloc_policy);
236
- if (!shost->bqt) {
237
- error = -ENOMEM;
238
- goto fail;
239
- }
240
- }
232
+ error = scsi_mq_setup_tags(shost);
233
+ if (error)
234
+ goto fail;
241235
242236 if (!shost->shost_gendev.parent)
243237 shost->shost_gendev.parent = dev ? dev : &platform_bus;
....@@ -282,27 +276,28 @@
282276 if (shost->transportt->create_work_queue) {
283277 snprintf(shost->work_q_name, sizeof(shost->work_q_name),
284278 "scsi_wq_%d", shost->host_no);
285
- shost->work_q = create_singlethread_workqueue(
286
- shost->work_q_name);
279
+ shost->work_q = alloc_workqueue("%s",
280
+ WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
281
+ 1, shost->work_q_name);
282
+
287283 if (!shost->work_q) {
288284 error = -EINVAL;
289
- goto out_free_shost_data;
285
+ goto out_del_dev;
290286 }
291287 }
292288
293289 error = scsi_sysfs_add_host(shost);
294290 if (error)
295
- goto out_destroy_host;
291
+ goto out_del_dev;
296292
297293 scsi_proc_host_add(shost);
298294 scsi_autopm_put_host(shost);
299295 return error;
300296
301
- out_destroy_host:
302
- if (shost->work_q)
303
- destroy_workqueue(shost->work_q);
304
- out_free_shost_data:
305
- kfree(shost->shost_data);
297
+ /*
298
+ * Any host allocation in this function will be freed in
299
+ * scsi_host_dev_release().
300
+ */
306301 out_del_dev:
307302 device_del(&shost->shost_dev);
308303 out_del_gendev:
....@@ -317,8 +312,6 @@
317312 pm_runtime_disable(&shost->shost_gendev);
318313 pm_runtime_set_suspended(&shost->shost_gendev);
319314 pm_runtime_put_noidle(&shost->shost_gendev);
320
- if (shost_use_blk_mq(shost))
321
- scsi_mq_destroy_tags(shost);
322315 fail:
323316 return error;
324317 }
....@@ -329,9 +322,7 @@
329322 struct Scsi_Host *shost = dev_to_shost(dev);
330323 struct device *parent = dev->parent;
331324
332
- scsi_proc_hostdir_rm(shost->hostt);
333
-
334
- /* Wait for functions invoked through call_rcu(&shost->rcu, ...) */
325
+ /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */
335326 rcu_barrier();
336327
337328 if (shost->tmf_work_q)
....@@ -352,13 +343,8 @@
352343 kfree(dev_name(&shost->shost_dev));
353344 }
354345
355
- if (shost_use_blk_mq(shost)) {
356
- if (shost->tag_set.tags)
357
- scsi_mq_destroy_tags(shost);
358
- } else {
359
- if (shost->bqt)
360
- blk_free_tags(shost->bqt);
361
- }
346
+ if (shost->tag_set.tags)
347
+ scsi_mq_destroy_tags(shost);
362348
363349 kfree(shost->shost_data);
364350
....@@ -441,8 +427,8 @@
441427 shost->sg_prot_tablesize = sht->sg_prot_tablesize;
442428 shost->cmd_per_lun = sht->cmd_per_lun;
443429 shost->unchecked_isa_dma = sht->unchecked_isa_dma;
444
- shost->use_clustering = sht->use_clustering;
445430 shost->no_write_same = sht->no_write_same;
431
+ shost->host_tagset = sht->host_tagset;
446432
447433 if (shost_eh_deadline == -1 || !sht->eh_host_reset_handler)
448434 shost->eh_deadline = -1;
....@@ -474,6 +460,11 @@
474460 else
475461 shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS;
476462
463
+ if (sht->max_segment_size)
464
+ shost->max_segment_size = sht->max_segment_size;
465
+ else
466
+ shost->max_segment_size = BLK_MAX_SEGMENT_SIZE;
467
+
477468 /*
478469 * assume a 4GB boundary, if not set
479470 */
....@@ -482,7 +473,8 @@
482473 else
483474 shost->dma_boundary = 0xffffffff;
484475
485
- shost->use_blk_mq = scsi_use_blk_mq || shost->hostt->force_blk_mq;
476
+ if (sht->virt_boundary_mask)
477
+ shost->virt_boundary_mask = sht->virt_boundary_mask;
486478
487479 device_initialize(&shost->shost_gendev);
488480 dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
....@@ -506,7 +498,7 @@
506498 }
507499
508500 shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d",
509
- WQ_UNBOUND | WQ_MEM_RECLAIM,
501
+ WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS,
510502 1, shost->host_no);
511503 if (!shost->tmf_work_q) {
512504 shost_printk(KERN_WARNING, shost,
....@@ -575,13 +567,29 @@
575567 }
576568 EXPORT_SYMBOL(scsi_host_get);
577569
570
+static bool scsi_host_check_in_flight(struct request *rq, void *data,
571
+ bool reserved)
572
+{
573
+ int *count = data;
574
+ struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
575
+
576
+ if (test_bit(SCMD_STATE_INFLIGHT, &cmd->state))
577
+ (*count)++;
578
+
579
+ return true;
580
+}
581
+
578582 /**
579583 * scsi_host_busy - Return the host busy counter
580584 * @shost: Pointer to Scsi_Host to inc.
581585 **/
582586 int scsi_host_busy(struct Scsi_Host *shost)
583587 {
584
- return atomic_read(&shost->host_busy);
588
+ int cnt = 0;
589
+
590
+ blk_mq_tagset_busy_iter(&shost->tag_set,
591
+ scsi_host_check_in_flight, &cnt);
592
+ return cnt;
585593 }
586594 EXPORT_SYMBOL(scsi_host_busy);
587595
....@@ -654,3 +662,68 @@
654662 flush_workqueue(shost->work_q);
655663 }
656664 EXPORT_SYMBOL_GPL(scsi_flush_work);
665
+
666
+static bool complete_all_cmds_iter(struct request *rq, void *data, bool rsvd)
667
+{
668
+ struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);
669
+ int status = *(int *)data;
670
+
671
+ scsi_dma_unmap(scmd);
672
+ scmd->result = status << 16;
673
+ scmd->scsi_done(scmd);
674
+ return true;
675
+}
676
+
677
+/**
678
+ * scsi_host_complete_all_commands - Terminate all running commands
679
+ * @shost: Scsi Host on which commands should be terminated
680
+ * @status: Status to be set for the terminated commands
681
+ *
682
+ * There is no protection against modification of the number
683
+ * of outstanding commands. It is the responsibility of the
684
+ * caller to ensure that concurrent I/O submission and/or
685
+ * completion is stopped when calling this function.
686
+ */
687
+void scsi_host_complete_all_commands(struct Scsi_Host *shost, int status)
688
+{
689
+ blk_mq_tagset_busy_iter(&shost->tag_set, complete_all_cmds_iter,
690
+ &status);
691
+}
692
+EXPORT_SYMBOL_GPL(scsi_host_complete_all_commands);
693
+
694
+struct scsi_host_busy_iter_data {
695
+ bool (*fn)(struct scsi_cmnd *, void *, bool);
696
+ void *priv;
697
+};
698
+
699
+static bool __scsi_host_busy_iter_fn(struct request *req, void *priv,
700
+ bool reserved)
701
+{
702
+ struct scsi_host_busy_iter_data *iter_data = priv;
703
+ struct scsi_cmnd *sc = blk_mq_rq_to_pdu(req);
704
+
705
+ return iter_data->fn(sc, iter_data->priv, reserved);
706
+}
707
+
708
+/**
709
+ * scsi_host_busy_iter - Iterate over all busy commands
710
+ * @shost: Pointer to Scsi_Host.
711
+ * @fn: Function to call on each busy command
712
+ * @priv: Data pointer passed to @fn
713
+ *
714
+ * If locking against concurrent command completions is required
715
+ * ithas to be provided by the caller
716
+ **/
717
+void scsi_host_busy_iter(struct Scsi_Host *shost,
718
+ bool (*fn)(struct scsi_cmnd *, void *, bool),
719
+ void *priv)
720
+{
721
+ struct scsi_host_busy_iter_data iter_data = {
722
+ .fn = fn,
723
+ .priv = priv,
724
+ };
725
+
726
+ blk_mq_tagset_busy_iter(&shost->tag_set, __scsi_host_busy_iter_fn,
727
+ &iter_data);
728
+}
729
+EXPORT_SYMBOL_GPL(scsi_host_busy_iter);