forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
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"
....@@ -226,18 +228,9 @@
226228 if (error)
227229 goto fail;
228230
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
- }
231
+ error = scsi_mq_setup_tags(shost);
232
+ if (error)
233
+ goto fail;
241234
242235 if (!shost->shost_gendev.parent)
243236 shost->shost_gendev.parent = dev ? dev : &platform_bus;
....@@ -282,27 +275,28 @@
282275 if (shost->transportt->create_work_queue) {
283276 snprintf(shost->work_q_name, sizeof(shost->work_q_name),
284277 "scsi_wq_%d", shost->host_no);
285
- shost->work_q = create_singlethread_workqueue(
286
- shost->work_q_name);
278
+ shost->work_q = alloc_workqueue("%s",
279
+ WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
280
+ 1, shost->work_q_name);
281
+
287282 if (!shost->work_q) {
288283 error = -EINVAL;
289
- goto out_free_shost_data;
284
+ goto out_del_dev;
290285 }
291286 }
292287
293288 error = scsi_sysfs_add_host(shost);
294289 if (error)
295
- goto out_destroy_host;
290
+ goto out_del_dev;
296291
297292 scsi_proc_host_add(shost);
298293 scsi_autopm_put_host(shost);
299294 return error;
300295
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);
296
+ /*
297
+ * Any host allocation in this function will be freed in
298
+ * scsi_host_dev_release().
299
+ */
306300 out_del_dev:
307301 device_del(&shost->shost_dev);
308302 out_del_gendev:
....@@ -317,8 +311,6 @@
317311 pm_runtime_disable(&shost->shost_gendev);
318312 pm_runtime_set_suspended(&shost->shost_gendev);
319313 pm_runtime_put_noidle(&shost->shost_gendev);
320
- if (shost_use_blk_mq(shost))
321
- scsi_mq_destroy_tags(shost);
322314 fail:
323315 return error;
324316 }
....@@ -352,13 +344,8 @@
352344 kfree(dev_name(&shost->shost_dev));
353345 }
354346
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
- }
347
+ if (shost->tag_set.tags)
348
+ scsi_mq_destroy_tags(shost);
362349
363350 kfree(shost->shost_data);
364351
....@@ -441,8 +428,8 @@
441428 shost->sg_prot_tablesize = sht->sg_prot_tablesize;
442429 shost->cmd_per_lun = sht->cmd_per_lun;
443430 shost->unchecked_isa_dma = sht->unchecked_isa_dma;
444
- shost->use_clustering = sht->use_clustering;
445431 shost->no_write_same = sht->no_write_same;
432
+ shost->host_tagset = sht->host_tagset;
446433
447434 if (shost_eh_deadline == -1 || !sht->eh_host_reset_handler)
448435 shost->eh_deadline = -1;
....@@ -474,6 +461,11 @@
474461 else
475462 shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS;
476463
464
+ if (sht->max_segment_size)
465
+ shost->max_segment_size = sht->max_segment_size;
466
+ else
467
+ shost->max_segment_size = BLK_MAX_SEGMENT_SIZE;
468
+
477469 /*
478470 * assume a 4GB boundary, if not set
479471 */
....@@ -482,7 +474,8 @@
482474 else
483475 shost->dma_boundary = 0xffffffff;
484476
485
- shost->use_blk_mq = scsi_use_blk_mq || shost->hostt->force_blk_mq;
477
+ if (sht->virt_boundary_mask)
478
+ shost->virt_boundary_mask = sht->virt_boundary_mask;
486479
487480 device_initialize(&shost->shost_gendev);
488481 dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
....@@ -506,7 +499,7 @@
506499 }
507500
508501 shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d",
509
- WQ_UNBOUND | WQ_MEM_RECLAIM,
502
+ WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS,
510503 1, shost->host_no);
511504 if (!shost->tmf_work_q) {
512505 shost_printk(KERN_WARNING, shost,
....@@ -575,13 +568,29 @@
575568 }
576569 EXPORT_SYMBOL(scsi_host_get);
577570
571
+static bool scsi_host_check_in_flight(struct request *rq, void *data,
572
+ bool reserved)
573
+{
574
+ int *count = data;
575
+ struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
576
+
577
+ if (test_bit(SCMD_STATE_INFLIGHT, &cmd->state))
578
+ (*count)++;
579
+
580
+ return true;
581
+}
582
+
578583 /**
579584 * scsi_host_busy - Return the host busy counter
580585 * @shost: Pointer to Scsi_Host to inc.
581586 **/
582587 int scsi_host_busy(struct Scsi_Host *shost)
583588 {
584
- return atomic_read(&shost->host_busy);
589
+ int cnt = 0;
590
+
591
+ blk_mq_tagset_busy_iter(&shost->tag_set,
592
+ scsi_host_check_in_flight, &cnt);
593
+ return cnt;
585594 }
586595 EXPORT_SYMBOL(scsi_host_busy);
587596
....@@ -654,3 +663,68 @@
654663 flush_workqueue(shost->work_q);
655664 }
656665 EXPORT_SYMBOL_GPL(scsi_flush_work);
666
+
667
+static bool complete_all_cmds_iter(struct request *rq, void *data, bool rsvd)
668
+{
669
+ struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);
670
+ int status = *(int *)data;
671
+
672
+ scsi_dma_unmap(scmd);
673
+ scmd->result = status << 16;
674
+ scmd->scsi_done(scmd);
675
+ return true;
676
+}
677
+
678
+/**
679
+ * scsi_host_complete_all_commands - Terminate all running commands
680
+ * @shost: Scsi Host on which commands should be terminated
681
+ * @status: Status to be set for the terminated commands
682
+ *
683
+ * There is no protection against modification of the number
684
+ * of outstanding commands. It is the responsibility of the
685
+ * caller to ensure that concurrent I/O submission and/or
686
+ * completion is stopped when calling this function.
687
+ */
688
+void scsi_host_complete_all_commands(struct Scsi_Host *shost, int status)
689
+{
690
+ blk_mq_tagset_busy_iter(&shost->tag_set, complete_all_cmds_iter,
691
+ &status);
692
+}
693
+EXPORT_SYMBOL_GPL(scsi_host_complete_all_commands);
694
+
695
+struct scsi_host_busy_iter_data {
696
+ bool (*fn)(struct scsi_cmnd *, void *, bool);
697
+ void *priv;
698
+};
699
+
700
+static bool __scsi_host_busy_iter_fn(struct request *req, void *priv,
701
+ bool reserved)
702
+{
703
+ struct scsi_host_busy_iter_data *iter_data = priv;
704
+ struct scsi_cmnd *sc = blk_mq_rq_to_pdu(req);
705
+
706
+ return iter_data->fn(sc, iter_data->priv, reserved);
707
+}
708
+
709
+/**
710
+ * scsi_host_busy_iter - Iterate over all busy commands
711
+ * @shost: Pointer to Scsi_Host.
712
+ * @fn: Function to call on each busy command
713
+ * @priv: Data pointer passed to @fn
714
+ *
715
+ * If locking against concurrent command completions is required
716
+ * ithas to be provided by the caller
717
+ **/
718
+void scsi_host_busy_iter(struct Scsi_Host *shost,
719
+ bool (*fn)(struct scsi_cmnd *, void *, bool),
720
+ void *priv)
721
+{
722
+ struct scsi_host_busy_iter_data iter_data = {
723
+ .fn = fn,
724
+ .priv = priv,
725
+ };
726
+
727
+ blk_mq_tagset_busy_iter(&shost->tag_set, __scsi_host_busy_iter_fn,
728
+ &iter_data);
729
+}
730
+EXPORT_SYMBOL_GPL(scsi_host_busy_iter);