From 0e881c0a4b6146b7e856735226208f48251facd8 Mon Sep 17 00:00:00 2001 From: Tuo Li Date: Fri, 30 Jun 2023 10:47:48 +0800 Subject: scsi: lpfc: Fix a possible data race in lpfc_unregister_fcf_rescan() The variable phba->fcf.fcf_flag is often protected by the lock phba->hbalock() when is accessed. Here is an example in lpfc_unregister_fcf_rescan(): spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag |= FCF_INIT_DISC; spin_unlock_irq(&phba->hbalock); However, in the same function, phba->fcf.fcf_flag is assigned with 0 without holding the lock, and thus can cause a data race: phba->fcf.fcf_flag = 0; To fix this possible data race, a lock and unlock pair is added when accessing the variable phba->fcf.fcf_flag. Reported-by: BassCheck Signed-off-by: Tuo Li Link: https://lore.kernel.org/r/20230630024748.1035993-1-islituo@gmail.com Reviewed-by: Justin Tee Reviewed-by: Laurence Oberman Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 499849b58ee4..fdd7f69d87ef 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -6944,7 +6944,9 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba) if (rc) return; /* Reset HBA FCF states after successful unregister FCF */ + spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag = 0; + spin_unlock_irq(&phba->hbalock); phba->fcf.current_rec.flag = 0; /* -- cgit From 134f66959cd0bc90a745f2eed4c10a0519d455c4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 26 Jun 2023 13:58:03 +0300 Subject: scsi: qla2xxx: Silence a static checker warning Smatch and Clang both complain that LOGIN_TEMPLATE_SIZE is more than sizeof(ha->plogi_els_payld.fl_csp). Smatch warning: drivers/scsi/qla2xxx/qla_iocb.c:3075 qla24xx_els_dcmd2_iocb() warn: '&ha->plogi_els_payld.fl_csp' sometimes too small '16' size = 112 Clang warning: include/linux/fortify-string.h:592:4: error: call to '__read_overflow2_field' declared with 'warning' attribute: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror,-Wattribute-warning] __read_overflow2_field(q_size_field, size); When I was reading this code I assumed the "- 4" meant that we were skipping the last 4 bytes but actually it turned out that we are skipping the first four bytes. I have re-written it remove the magic numbers, be more clear and silence the static checker warnings. Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/4aa0485e-766f-4b02-8d5d-c6781ea8f511@moroto.mountain Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 - drivers/scsi/qla2xxx/qla_iocb.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 95a12b4e0484..892ceba51c23 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -4461,7 +4461,6 @@ struct qla_hw_data { /* n2n */ struct fc_els_flogi plogi_els_payld; -#define LOGIN_TEMPLATE_SIZE (sizeof(struct fc_els_flogi) - 4) void *swl; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index a1675f056a5c..9c70c4e973ee 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -3073,7 +3073,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, memset(ptr, 0, sizeof(struct els_plogi_payload)); memset(resp_ptr, 0, sizeof(struct els_plogi_payload)); memcpy(elsio->u.els_plogi.els_plogi_pyld->data, - &ha->plogi_els_payld.fl_csp, LOGIN_TEMPLATE_SIZE); + (void *)&ha->plogi_els_payld + offsetof(struct fc_els_flogi, fl_csp), + sizeof(ha->plogi_els_payld) - offsetof(struct fc_els_flogi, fl_csp)); elsio->u.els_plogi.els_cmd = els_opcode; elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; -- cgit From e579b007eff3ff8d29d59d16214cd85fb9e573f7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 26 Jun 2023 13:58:47 +0300 Subject: scsi: qla2xxx: Fix error code in qla2x00_start_sp() This should be negative -EAGAIN instead of positive. The callers treat non-zero error codes the same so it doesn't really impact runtime beyond some trivial differences to debug output. Fixes: 80676d054e5a ("scsi: qla2xxx: Fix session cleanup hang") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/49866d28-4cfe-47b0-842b-78f110e61aab@moroto.mountain Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_iocb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 9c70c4e973ee..730d8609276c 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -3912,7 +3912,7 @@ qla2x00_start_sp(srb_t *sp) pkt = __qla2x00_alloc_iocbs(sp->qpair, sp); if (!pkt) { - rval = EAGAIN; + rval = -EAGAIN; ql_log(ql_log_warn, vha, 0x700c, "qla2x00_alloc_iocbs failed.\n"); goto done; -- cgit From b34c7dcaf311521f6a0edaffc157d115d386ed9c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 27 Jun 2023 16:43:22 +0200 Subject: scsi: fnic: Use vmalloc_array() and vcalloc() Use vmalloc_array() and vcalloc() to protect against multiplication overflows. The changes were done using the following Coccinelle semantic patch: // @initialize:ocaml@ @@ let rename alloc = match alloc with "vmalloc" -> "vmalloc_array" | "vzalloc" -> "vcalloc" | _ -> failwith "unknown" @@ size_t e1,e2; constant C1, C2; expression E1, E2, COUNT, x1, x2, x3; typedef u8; typedef __u8; type t = {u8,__u8,char,unsigned char}; identifier alloc = {vmalloc,vzalloc}; fresh identifier realloc = script:ocaml(alloc) { rename alloc }; @@ ( alloc(x1*x2*x3) | alloc(C1 * C2) | alloc((sizeof(t)) * (COUNT), ...) | - alloc((e1) * (e2)) + realloc(e1, e2) | - alloc((e1) * (COUNT)) + realloc(COUNT, e1) | - alloc((E1) * (E2)) + realloc(E1, E2) ) // Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20230627144339.144478-8-Julia.Lawall@inria.fr Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic_trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c index f3c3a26a1384..be0d7c57b242 100644 --- a/drivers/scsi/fnic/fnic_trace.c +++ b/drivers/scsi/fnic/fnic_trace.c @@ -465,7 +465,7 @@ int fnic_trace_buf_init(void) fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/ FNIC_ENTRY_SIZE_BYTES; - fnic_trace_buf_p = (unsigned long)vzalloc(trace_max_pages * PAGE_SIZE); + fnic_trace_buf_p = (unsigned long)vcalloc(trace_max_pages, PAGE_SIZE); if (!fnic_trace_buf_p) { printk(KERN_ERR PFX "Failed to allocate memory " "for fnic_trace_buf_p\n"); -- cgit From 04d91b783acf910ceda2af31fe969e4eb572110b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 27 Jun 2023 16:43:39 +0200 Subject: scsi: qla2xxx: Use vmalloc_array() and vcalloc() Use vmalloc_array() and vcalloc() to protect against multiplication overflows. The changes were done using the following Coccinelle semantic patch: // @initialize:ocaml@ @@ let rename alloc = match alloc with "vmalloc" -> "vmalloc_array" | "vzalloc" -> "vcalloc" | _ -> failwith "unknown" @@ size_t e1,e2; constant C1, C2; expression E1, E2, COUNT, x1, x2, x3; typedef u8; typedef __u8; type t = {u8,__u8,char,unsigned char}; identifier alloc = {vmalloc,vzalloc}; fresh identifier realloc = script:ocaml(alloc) { rename alloc }; @@ ( alloc(x1*x2*x3) | alloc(C1 * C2) | alloc((sizeof(t)) * (COUNT), ...) | - alloc((e1) * (e2)) + realloc(e1, e2) | - alloc((e1) * (COUNT)) + realloc(COUNT, e1) | - alloc((E1) * (E2)) + realloc(E1, E2) ) // Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20230627144339.144478-25-Julia.Lawall@inria.fr Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b22b0516da29..e2d51f68f747 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -8434,7 +8434,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, ql_dbg(ql_dbg_init, vha, 0x0163, "-> fwdt%u template allocate template %#x words...\n", j, risc_size); - fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + fwdt->template = vmalloc_array(risc_size, sizeof(*dcode)); if (!fwdt->template) { ql_log(ql_log_warn, vha, 0x0164, "-> fwdt%u failed allocate template.\n", j); @@ -8689,7 +8689,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) ql_dbg(ql_dbg_init, vha, 0x0173, "-> fwdt%u template allocate template %#x words...\n", j, risc_size); - fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + fwdt->template = vmalloc_array(risc_size, sizeof(*dcode)); if (!fwdt->template) { ql_log(ql_log_warn, vha, 0x0174, "-> fwdt%u failed allocate template.\n", j); -- cgit From 23815df5af5790c6e99b6bb1ffd39d509d0a7bdb Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Wed, 28 Jun 2023 17:06:38 +0200 Subject: scsi: scsi_debug: Remove dead code The ramdisk rwlocks are not used anymore. Fixes: 87c715dcde63 ("scsi: scsi_debug: Add per_host_store option") Signed-off-by: Maurizio Lombardi Link: https://lore.kernel.org/r/20230628150638.53218-1-mlombard@redhat.com Reviewed-by: Laurence Oberman Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 8c58128ad32a..9c0af50501f9 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -841,11 +841,6 @@ static int sdeb_zbc_nr_conv = DEF_ZBC_NR_CONV_ZONES; static int submit_queues = DEF_SUBMIT_QUEUES; /* > 1 for multi-queue (mq) */ static int poll_queues; /* iouring iopoll interface.*/ -static DEFINE_RWLOCK(atomic_rw); -static DEFINE_RWLOCK(atomic_rw2); - -static rwlock_t *ramdisk_lck_a[2]; - static char sdebug_proc_name[] = MY_NAME; static const char *my_name = MY_NAME; @@ -6818,9 +6813,6 @@ static int __init scsi_debug_init(void) int k, ret, hosts_to_add; int idx = -1; - ramdisk_lck_a[0] = &atomic_rw; - ramdisk_lck_a[1] = &atomic_rw2; - if (sdebug_ndelay >= 1000 * 1000 * 1000) { pr_warn("ndelay must be less than 1 second, ignored\n"); sdebug_ndelay = 0; -- cgit From ef470b862dc7e5e169167301b9862bed54d7f969 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Thu, 29 Jun 2023 17:39:09 -0700 Subject: scsi: ufs: core: Update contact email for monitor sysfs nodes Update contact email addresses for Can Guo and Asutosh Das, replace Subhash Jadavani's contact. Signed-off-by: Can Guo Link: https://lore.kernel.org/r/20230630003913.3713155-1-quic_cang@quicinc.com Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 76 +++++++++++++++--------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index d5f44fc5b9dc..e487f969a15e 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -994,7 +994,7 @@ Description: This file shows the amount of physical memory needed What: /sys/bus/platform/drivers/ufshcd/*/rpm_lvl What: /sys/bus/platform/devices/*.ufs/rpm_lvl Date: September 2014 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry could be used to set or show the UFS device runtime power management level. The current driver implementation supports 7 levels with next target states: @@ -1021,7 +1021,7 @@ Description: This entry could be used to set or show the UFS device What: /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state What: /sys/bus/platform/devices/*.ufs/rpm_target_dev_state Date: February 2018 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry shows the target power mode of an UFS device for the chosen runtime power management level. @@ -1030,7 +1030,7 @@ Description: This entry shows the target power mode of an UFS device What: /sys/bus/platform/drivers/ufshcd/*/rpm_target_link_state What: /sys/bus/platform/devices/*.ufs/rpm_target_link_state Date: February 2018 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry shows the target state of an UFS UIC link for the chosen runtime power management level. @@ -1039,7 +1039,7 @@ Description: This entry shows the target state of an UFS UIC link What: /sys/bus/platform/drivers/ufshcd/*/spm_lvl What: /sys/bus/platform/devices/*.ufs/spm_lvl Date: September 2014 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry could be used to set or show the UFS device system power management level. The current driver implementation supports 7 levels with next target states: @@ -1066,7 +1066,7 @@ Description: This entry could be used to set or show the UFS device What: /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state What: /sys/bus/platform/devices/*.ufs/spm_target_dev_state Date: February 2018 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry shows the target power mode of an UFS device for the chosen system power management level. @@ -1075,7 +1075,7 @@ Description: This entry shows the target power mode of an UFS device What: /sys/bus/platform/drivers/ufshcd/*/spm_target_link_state What: /sys/bus/platform/devices/*.ufs/spm_target_link_state Date: February 2018 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry shows the target state of an UFS UIC link for the chosen system power management level. @@ -1084,7 +1084,7 @@ Description: This entry shows the target state of an UFS UIC link What: /sys/bus/platform/drivers/ufshcd/*/monitor/monitor_enable What: /sys/bus/platform/devices/*.ufs/monitor/monitor_enable Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the status of performance monitor enablement and it can be used to start/stop the monitor. When the monitor is stopped, the performance data collected is also cleared. @@ -1092,7 +1092,7 @@ Description: This file shows the status of performance monitor enablement What: /sys/bus/platform/drivers/ufshcd/*/monitor/monitor_chunk_size What: /sys/bus/platform/devices/*.ufs/monitor/monitor_chunk_size Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file tells the monitor to focus on requests transferring data of specific chunk size (in Bytes). 0 means any chunk size. It can only be changed when monitor is disabled. @@ -1100,7 +1100,7 @@ Description: This file tells the monitor to focus on requests transferring What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_total_sectors What: /sys/bus/platform/devices/*.ufs/monitor/read_total_sectors Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how many sectors (in 512 Bytes) have been sent from device to host after monitor gets started. @@ -1109,7 +1109,7 @@ Description: This file shows how many sectors (in 512 Bytes) have been What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_total_busy What: /sys/bus/platform/devices/*.ufs/monitor/read_total_busy Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how long (in micro seconds) has been spent sending data from device to host after monitor gets started. @@ -1118,7 +1118,7 @@ Description: This file shows how long (in micro seconds) has been spent What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_nr_requests What: /sys/bus/platform/devices/*.ufs/monitor/read_nr_requests Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how many read requests have been sent after monitor gets started. @@ -1127,7 +1127,7 @@ Description: This file shows how many read requests have been sent after What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_max What: /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_max Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the maximum latency (in micro seconds) of read requests after monitor gets started. @@ -1136,7 +1136,7 @@ Description: This file shows the maximum latency (in micro seconds) of What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_min What: /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_min Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the minimum latency (in micro seconds) of read requests after monitor gets started. @@ -1145,7 +1145,7 @@ Description: This file shows the minimum latency (in micro seconds) of What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_avg What: /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_avg Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the average latency (in micro seconds) of read requests after monitor gets started. @@ -1154,7 +1154,7 @@ Description: This file shows the average latency (in micro seconds) of What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_sum What: /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_sum Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the total latency (in micro seconds) of read requests sent after monitor gets started. @@ -1163,7 +1163,7 @@ Description: This file shows the total latency (in micro seconds) of What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_total_sectors What: /sys/bus/platform/devices/*.ufs/monitor/write_total_sectors Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how many sectors (in 512 Bytes) have been sent from host to device after monitor gets started. @@ -1172,7 +1172,7 @@ Description: This file shows how many sectors (in 512 Bytes) have been sent What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_total_busy What: /sys/bus/platform/devices/*.ufs/monitor/write_total_busy Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how long (in micro seconds) has been spent sending data from host to device after monitor gets started. @@ -1181,7 +1181,7 @@ Description: This file shows how long (in micro seconds) has been spent What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_nr_requests What: /sys/bus/platform/devices/*.ufs/monitor/write_nr_requests Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how many write requests have been sent after monitor gets started. @@ -1190,7 +1190,7 @@ Description: This file shows how many write requests have been sent after What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_max What: /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_max Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the maximum latency (in micro seconds) of write requests after monitor gets started. @@ -1199,7 +1199,7 @@ Description: This file shows the maximum latency (in micro seconds) of write What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_min What: /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_min Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the minimum latency (in micro seconds) of write requests after monitor gets started. @@ -1208,7 +1208,7 @@ Description: This file shows the minimum latency (in micro seconds) of write What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_avg What: /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_avg Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the average latency (in micro seconds) of write requests after monitor gets started. @@ -1217,7 +1217,7 @@ Description: This file shows the average latency (in micro seconds) of write What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_sum What: /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_sum Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the total latency (in micro seconds) of write requests after monitor gets started. @@ -1226,7 +1226,7 @@ Description: This file shows the total latency (in micro seconds) of write What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_presv_us_en What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_presv_us_en Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows if preserve user-space was configured The file is read only. @@ -1234,7 +1234,7 @@ Description: This entry shows if preserve user-space was configured What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_shared_alloc_units What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_shared_alloc_units Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the shared allocated units of WB buffer The file is read only. @@ -1242,7 +1242,7 @@ Description: This entry shows the shared allocated units of WB buffer What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_type What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_type Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the configured WB type. 0x1 for shared buffer mode. 0x0 for dedicated buffer mode. @@ -1251,7 +1251,7 @@ Description: This entry shows the configured WB type. What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_buff_cap_adj What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_buff_cap_adj Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the total user-space decrease in shared buffer mode. The value of this parameter is 3 for TLC NAND when SLC mode @@ -1262,7 +1262,7 @@ Description: This entry shows the total user-space decrease in shared What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_alloc_units What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_max_alloc_units Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the Maximum total WriteBooster Buffer size which is supported by the entire device. @@ -1271,7 +1271,7 @@ Description: This entry shows the Maximum total WriteBooster Buffer size What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_wb_luns What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_max_wb_luns Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the maximum number of luns that can support WriteBooster. @@ -1280,7 +1280,7 @@ Description: This entry shows the maximum number of luns that can support What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_red_type What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_sup_red_type Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: The supportability of user space reduction mode and preserve user space mode. 00h: WriteBooster Buffer can be configured only in @@ -1295,7 +1295,7 @@ Description: The supportability of user space reduction mode What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_wb_type What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_sup_wb_type Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: The supportability of WriteBooster Buffer type. === ========================================================== @@ -1310,7 +1310,7 @@ Description: The supportability of WriteBooster Buffer type. What: /sys/bus/platform/drivers/ufshcd/*/flags/wb_enable What: /sys/bus/platform/devices/*.ufs/flags/wb_enable Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the status of WriteBooster. == ============================ @@ -1323,7 +1323,7 @@ Description: This entry shows the status of WriteBooster. What: /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_en What: /sys/bus/platform/devices/*.ufs/flags/wb_flush_en Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows if flush is enabled. == ================================= @@ -1336,7 +1336,7 @@ Description: This entry shows if flush is enabled. What: /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_during_h8 What: /sys/bus/platform/devices/*.ufs/flags/wb_flush_during_h8 Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: Flush WriteBooster Buffer during hibernate state. == ================================================= @@ -1351,7 +1351,7 @@ Description: Flush WriteBooster Buffer during hibernate state. What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_avail_buf What: /sys/bus/platform/devices/*.ufs/attributes/wb_avail_buf Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the amount of unused WriteBooster buffer available. @@ -1360,7 +1360,7 @@ Description: This entry shows the amount of unused WriteBooster buffer What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_cur_buf What: /sys/bus/platform/devices/*.ufs/attributes/wb_cur_buf Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the amount of unused current buffer. The file is read only. @@ -1368,7 +1368,7 @@ Description: This entry shows the amount of unused current buffer. What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_flush_status What: /sys/bus/platform/devices/*.ufs/attributes/wb_flush_status Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the flush operation status. @@ -1385,7 +1385,7 @@ Description: This entry shows the flush operation status. What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_life_time_est What: /sys/bus/platform/devices/*.ufs/attributes/wb_life_time_est Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows an indication of the WriteBooster Buffer lifetime based on the amount of performed program/erase cycles @@ -1399,7 +1399,7 @@ Description: This entry shows an indication of the WriteBooster Buffer What: /sys/class/scsi_device/*/device/unit_descriptor/wb_buf_alloc_units Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the configured size of WriteBooster buffer. 0400h corresponds to 4GB. -- cgit From 89f7ef7f2b23b2a7b8ce346c23161916eae5b15c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 30 Jun 2023 22:23:48 -0700 Subject: scsi: ufs: ufs-mediatek: Add dependency for RESET_CONTROLLER When RESET_CONTROLLER is not set, kconfig complains about missing dependencies for RESET_TI_SYSCON, so add the missing dependency just as is done above for SCSI_UFS_QCOM. Silences this kconfig warning: WARNING: unmet direct dependencies detected for RESET_TI_SYSCON Depends on [n]: RESET_CONTROLLER [=n] && HAS_IOMEM [=y] Selected by [m]: - SCSI_UFS_MEDIATEK [=m] && SCSI_UFSHCD [=y] && SCSI_UFSHCD_PLATFORM [=y] && ARCH_MEDIATEK [=y] Fixes: de48898d0cb6 ("scsi: ufs-mediatek: Create reset control device_link") Signed-off-by: Randy Dunlap Link: lore.kernel.org/r/202306020859.1wHg9AaT-lkp@intel.com Link: https://lore.kernel.org/r/20230701052348.28046-1-rdunlap@infradead.org Cc: Stanley Chu Cc: Peter Wang Cc: Paul Gazzillo Cc: Necip Fazil Yildiran Cc: linux-scsi@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mediatek@lists.infradead.org Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Reported-by: kernel test robot Signed-off-by: Martin K. Petersen --- drivers/ufs/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig index 16624ba08050..580c8d0bd8bb 100644 --- a/drivers/ufs/host/Kconfig +++ b/drivers/ufs/host/Kconfig @@ -72,6 +72,7 @@ config SCSI_UFS_QCOM config SCSI_UFS_MEDIATEK tristate "Mediatek specific hooks to UFS controller platform driver" depends on SCSI_UFSHCD_PLATFORM && ARCH_MEDIATEK + depends on RESET_CONTROLLER select PHY_MTK_UFS select RESET_TI_SYSCON help -- cgit From 47699a2b63caaa0de4841d4402627c2fdf3452a6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 3 Jul 2023 13:48:46 +0200 Subject: scsi: aacraid: Avoid -Warray-bounds warning The one-element array in aac_aifcmd is actually meant as a flexible array, and causes an overflow warning that can be avoided using the normal flex arrays: drivers/scsi/aacraid/commsup.c:1166:17: error: array index 1 is past the end of the array (that has type 'u8[1]' (aka 'unsigned char[1]'), cast to '__le32 *' (aka 'unsigned int *')) [-Werror,-Warray-bounds] (((__le32 *)aifcmd->data)[1] == cpu_to_le32(3)); ^ ~ Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20230703114851.1194510-1-arnd@kernel.org Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aacraid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 5e115e8b2ba4..7d5a155073c6 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -2617,7 +2617,7 @@ struct aac_hba_info { struct aac_aifcmd { __le32 command; /* Tell host what type of notify this is */ __le32 seqnum; /* To allow ordering of reports (if necessary) */ - u8 data[1]; /* Undefined length (from kernel viewpoint) */ + u8 data[]; /* Undefined length (from kernel viewpoint) */ }; /** -- cgit From 24befa92ed47ed2af25868412a1275602ca8f4ea Mon Sep 17 00:00:00 2001 From: Arthur Simchaev Date: Mon, 26 Jun 2023 13:33:19 +0300 Subject: scsi: ufs: core: Add support for qTimestamp attribute The new qTimestamp attribute was added to UFS 4.0 spec, in order to synchronize timestamp between device logs and the host. The spec recommends to send this attribute upon device power-on Reset/HW reset or when switching to Active state (using SSU command). Due to this attribute, the attribute's max value was extended to 8 bytes. As a result, the new definition of struct utp_upiu_query_v4_0 was added. Signed-off-by: Arthur Simchaev ----------------- Changes to v2: - Adressed Bart's comments - Add missed response variable to ufshcd_set_timestamp_attr Link: https://lore.kernel.org/r/20230626103320.8737-1-arthur.simchaev@wdc.com Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 38 ++++++++++++++++++++++++++++++++++++++ include/uapi/scsi/scsi_bsg_ufs.h | 25 +++++++++++++++++++++++++ include/ufs/ufs.h | 1 + 3 files changed, 64 insertions(+) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 358b3240b6c5..e2812911e462 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -8520,6 +8520,41 @@ out: return ret; } +static void ufshcd_set_timestamp_attr(struct ufs_hba *hba) +{ + int err; + struct ufs_query_req *request = NULL; + struct ufs_query_res *response = NULL; + struct ufs_dev_info *dev_info = &hba->dev_info; + struct utp_upiu_query_v4_0 *upiu_data; + + if (dev_info->wspecversion < 0x400) + return; + + ufshcd_hold(hba); + + mutex_lock(&hba->dev_cmd.lock); + + ufshcd_init_query(hba, &request, &response, + UPIU_QUERY_OPCODE_WRITE_ATTR, + QUERY_ATTR_IDN_TIMESTAMP, 0, 0); + + request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST; + + upiu_data = (struct utp_upiu_query_v4_0 *)&request->upiu_req; + + put_unaligned_be64(ktime_get_real_ns(), &upiu_data->osf3); + + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); + + if (err) + dev_err(hba->dev, "%s: failed to set timestamp %d\n", + __func__, err); + + mutex_unlock(&hba->dev_cmd.lock); + ufshcd_release(hba); +} + /** * ufshcd_add_lus - probe and add UFS logical units * @hba: per-adapter instance @@ -8708,6 +8743,8 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params) ufshcd_set_ufs_dev_active(hba); ufshcd_force_reset_auto_bkops(hba); + ufshcd_set_timestamp_attr(hba); + /* Gear up to HS gear if supported */ if (hba->max_pwr_info.is_valid) { /* @@ -9741,6 +9778,7 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) ret = ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE); if (ret) goto set_old_link_state; + ufshcd_set_timestamp_attr(hba); } if (ufshcd_keep_autobkops_enabled_except_suspend(hba)) diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h index 2801b65299aa..fd3f9e5ee241 100644 --- a/include/uapi/scsi/scsi_bsg_ufs.h +++ b/include/uapi/scsi/scsi_bsg_ufs.h @@ -70,6 +70,31 @@ struct utp_upiu_query { __be32 reserved[2]; }; +/** + * struct utp_upiu_query_v4_0 - upiu request buffer structure for + * query request >= UFS 4.0 spec. + * @opcode: command to perform B-0 + * @idn: a value that indicates the particular type of data B-1 + * @index: Index to further identify data B-2 + * @selector: Index to further identify data B-3 + * @osf4: spec field B-5 + * @osf5: spec field B 6,7 + * @osf6: spec field DW 8,9 + * @osf7: spec field DW 10,11 + */ +struct utp_upiu_query_v4_0 { + __u8 opcode; + __u8 idn; + __u8 index; + __u8 selector; + __u8 osf3; + __u8 osf4; + __be16 osf5; + __be32 osf6; + __be32 osf7; + __be32 reserved; +}; + /** * struct utp_upiu_cmd - Command UPIU structure * @data_transfer_len: Data Transfer Length DW-3 diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h index 4e8d6240e589..198cb391f9db 100644 --- a/include/ufs/ufs.h +++ b/include/ufs/ufs.h @@ -170,6 +170,7 @@ enum attr_idn { QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST = 0x1E, QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE = 0x1F, QUERY_ATTR_IDN_EXT_IID_EN = 0x2A, + QUERY_ATTR_IDN_TIMESTAMP = 0x30 }; /* Descriptor idn for Query requests */ -- cgit From f79846ca2f04c9744627c24034d675c88f0da3a0 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 3 Jul 2023 11:48:08 +0900 Subject: scsi: sd_zbc: Set zone limits before revalidating zones In sd_zbc_revalidate_zones(), execute blk_queue_chunk_sectors() and blk_queue_max_zone_append_sectors() to respectively set a ZBC device zone size and maximum zone append sector limit before executing blk_revalidate_disk_zones(). This is to allow the block layer zone reavlidation to check these device characteristics prior to checking all zones of the device. Since blk_queue_max_zone_append_sectors() already caps the device maximum zone append limit to the zone size and to the maximum command size, the max_append value passed to blk_queue_max_zone_append_sectors() is simplified to the maximum number of segments times the number of sectors per page. Signed-off-by: Damien Le Moal Link: https://lore.kernel.org/r/20230703024812.76778-2-dlemoal@kernel.org Reviewed-by: Bart Van Assche Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/sd_zbc.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index abbd08933ac7..a25215507668 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -831,7 +831,6 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) struct request_queue *q = disk->queue; u32 zone_blocks = sdkp->early_zone_info.zone_blocks; unsigned int nr_zones = sdkp->early_zone_info.nr_zones; - u32 max_append; int ret = 0; unsigned int flags; @@ -876,6 +875,11 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) goto unlock; } + blk_queue_chunk_sectors(q, + logical_to_sectors(sdkp->device, zone_blocks)); + blk_queue_max_zone_append_sectors(q, + q->limits.max_segments << PAGE_SECTORS_SHIFT); + ret = blk_revalidate_disk_zones(disk, sd_zbc_revalidate_zones_cb); memalloc_noio_restore(flags); @@ -888,12 +892,6 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) goto unlock; } - max_append = min_t(u32, logical_to_sectors(sdkp->device, zone_blocks), - q->limits.max_segments << PAGE_SECTORS_SHIFT); - max_append = min_t(u32, max_append, queue_max_hw_sectors(q)); - - blk_queue_max_zone_append_sectors(q, max_append); - sd_zbc_print_zones(sdkp); unlock: -- cgit From d226b0a2b683e27fce060669dc7cb8d6917b785a Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 3 Jul 2023 11:48:09 +0900 Subject: scsi: nvme: zns: Set zone limits before revalidating zones In nvme_revalidate_zones(), execute blk_queue_chunk_sectors() and blk_queue_max_zone_append_sectors() to respectively set a ZNS namespace zone size and maximum zone append sector limit before executing blk_revalidate_disk_zones(). This is to allow the block layer zone reavlidation to check these device characteristics prior to checking all zones of the device. Signed-off-by: Damien Le Moal Link: https://lore.kernel.org/r/20230703024812.76778-3-dlemoal@kernel.org Reviewed-by: Bart Van Assche Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/nvme/host/zns.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c index 12316ab51bda..ec8557810c21 100644 --- a/drivers/nvme/host/zns.c +++ b/drivers/nvme/host/zns.c @@ -10,12 +10,11 @@ int nvme_revalidate_zones(struct nvme_ns *ns) { struct request_queue *q = ns->queue; - int ret; - ret = blk_revalidate_disk_zones(ns->disk, NULL); - if (!ret) - blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append); - return ret; + blk_queue_chunk_sectors(q, ns->zsze); + blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append); + + return blk_revalidate_disk_zones(ns->disk, NULL); } static int nvme_set_max_append(struct nvme_ctrl *ctrl) -- cgit From a442b899fe17118e672647f664bf7f1dd5d7fcb0 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 3 Jul 2023 11:48:10 +0900 Subject: scsi: block: nullblk: Set zone limits before revalidating zones In null_register_zoned_dev(), execute blk_queue_chunk_sectors() and blk_queue_max_zone_append_sectors() to respectively set the zoned device zone size and maximum zone append sector limit before executing blk_revalidate_disk_zones(). This is to allow the block layer zone reavlidation to check these device characteristics prior to checking all zones of the device. Signed-off-by: Damien Le Moal Link: https://lore.kernel.org/r/20230703024812.76778-4-dlemoal@kernel.org Reviewed-by: Bart Van Assche Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/block/null_blk/zoned.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c index 635ce0648133..55c5b48bc276 100644 --- a/drivers/block/null_blk/zoned.c +++ b/drivers/block/null_blk/zoned.c @@ -162,21 +162,15 @@ int null_register_zoned_dev(struct nullb *nullb) disk_set_zoned(nullb->disk, BLK_ZONED_HM); blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q); blk_queue_required_elevator_features(q, ELEVATOR_F_ZBD_SEQ_WRITE); - - if (queue_is_mq(q)) { - int ret = blk_revalidate_disk_zones(nullb->disk, NULL); - - if (ret) - return ret; - } else { - blk_queue_chunk_sectors(q, dev->zone_size_sects); - nullb->disk->nr_zones = bdev_nr_zones(nullb->disk->part0); - } - + blk_queue_chunk_sectors(q, dev->zone_size_sects); + nullb->disk->nr_zones = bdev_nr_zones(nullb->disk->part0); blk_queue_max_zone_append_sectors(q, dev->zone_size_sects); disk_set_max_open_zones(nullb->disk, dev->zone_max_open); disk_set_max_active_zones(nullb->disk, dev->zone_max_active); + if (queue_is_mq(q)) + return blk_revalidate_disk_zones(nullb->disk, NULL); + return 0; } -- cgit From a3d96ed21507e8d70ddab6c7abc93d5e56aaeeb0 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 3 Jul 2023 11:48:11 +0900 Subject: scsi: block: virtio_blk: Set zone limits before revalidating zones In virtblk_probe_zoned_device(), execute blk_queue_chunk_sectors() and blk_queue_max_zone_append_sectors() to respectively set the zoned device zone size and maximum zone append sector limit before executing blk_revalidate_disk_zones(). This is to allow the block layer zone reavlidation to check these device characteristics prior to checking all zones of the device. Signed-off-by: Damien Le Moal Link: https://lore.kernel.org/r/20230703024812.76778-5-dlemoal@kernel.org Reviewed-by: Bart Van Assche Reviewed-by: Dmitry Fomichev Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/block/virtio_blk.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 2b918e28acaa..d6df29566370 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -781,7 +781,6 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev, { u32 v, wg; u8 model; - int ret; virtio_cread(vdev, struct virtio_blk_config, zoned.model, &model); @@ -836,6 +835,7 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev, vblk->zone_sectors); return -ENODEV; } + blk_queue_chunk_sectors(q, vblk->zone_sectors); dev_dbg(&vdev->dev, "zone sectors = %u\n", vblk->zone_sectors); if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) { @@ -844,26 +844,22 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev, blk_queue_max_discard_sectors(q, 0); } - ret = blk_revalidate_disk_zones(vblk->disk, NULL); - if (!ret) { - virtio_cread(vdev, struct virtio_blk_config, - zoned.max_append_sectors, &v); - if (!v) { - dev_warn(&vdev->dev, "zero max_append_sectors reported\n"); - return -ENODEV; - } - if ((v << SECTOR_SHIFT) < wg) { - dev_err(&vdev->dev, - "write granularity %u exceeds max_append_sectors %u limit\n", - wg, v); - return -ENODEV; - } - - blk_queue_max_zone_append_sectors(q, v); - dev_dbg(&vdev->dev, "max append sectors = %u\n", v); + virtio_cread(vdev, struct virtio_blk_config, + zoned.max_append_sectors, &v); + if (!v) { + dev_warn(&vdev->dev, "zero max_append_sectors reported\n"); + return -ENODEV; + } + if ((v << SECTOR_SHIFT) < wg) { + dev_err(&vdev->dev, + "write granularity %u exceeds max_append_sectors %u limit\n", + wg, v); + return -ENODEV; } + blk_queue_max_zone_append_sectors(q, v); + dev_dbg(&vdev->dev, "max append sectors = %u\n", v); - return ret; + return blk_revalidate_disk_zones(vblk->disk, NULL); } #else -- cgit From 03e51c4a74b91b0b1a9ca091029b0b58f014be81 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 3 Jul 2023 11:48:12 +0900 Subject: scsi: block: Improve checks in blk_revalidate_disk_zones() blk_revalidate_disk_zones() implements checks of the zones of a zoned block device, verifying that the zone size is a power of 2 number of sectors, that all zones (except possibly the last one) have the same size and that zones cover the entire addressing space of the device. While these checks are appropriate to verify that well tested hardware devices have an adequate zone configurations, they lack in certain areas which may result in issues with emulated devices implemented with user drivers such as ublk or tcmu. Specifically, this function does not check if the device driver indicated support for the mandatory zone append writes, that is, if the device max_zone_append_sectors queue limit is set to a non-zero value. Additionally, invalid zones such as a zero length zone with a start sector equal to the device capacity will not be detected and result in out of bounds use of the zone bitmaps prepared with the callback function blk_revalidate_zone_cb(). Improve blk_revalidate_disk_zones() to address these inadequate checks, relying on the fact that all device drivers supporting zoned block devices must set the device zone size (chunk_sectors queue limit) and the max_zone_append_sectors queue limit before executing this function. The check for a non-zero max_zone_append_sectors value is done in blk_revalidate_disk_zones() before executing the zone report. The zone report callback function blk_revalidate_zone_cb() is also modified to add a check that a zone start is below the device capacity. The check that the zone size is a power of 2 number of sectors is moved to blk_revalidate_disk_zones() as the zone size is already known. Similarly, the number of zones of the device can be calculated in blk_revalidate_disk_zones() before executing the zone report. The kdoc comment for blk_revalidate_disk_zones() is also updated to mention that device drivers must set the device zone size and the max_zone_append_sectors queue limit before calling this function. Signed-off-by: Damien Le Moal Link: https://lore.kernel.org/r/20230703024812.76778-6-dlemoal@kernel.org Reviewed-by: Bart Van Assche Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- block/blk-zoned.c | 86 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index fce9082384d6..da92ce0c5da9 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -448,7 +448,6 @@ struct blk_revalidate_zone_args { unsigned long *conv_zones_bitmap; unsigned long *seq_zones_wlock; unsigned int nr_zones; - sector_t zone_sectors; sector_t sector; }; @@ -462,38 +461,34 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, struct gendisk *disk = args->disk; struct request_queue *q = disk->queue; sector_t capacity = get_capacity(disk); + sector_t zone_sectors = q->limits.chunk_sectors; + + /* Check for bad zones and holes in the zone report */ + if (zone->start != args->sector) { + pr_warn("%s: Zone gap at sectors %llu..%llu\n", + disk->disk_name, args->sector, zone->start); + return -ENODEV; + } + + if (zone->start >= capacity || !zone->len) { + pr_warn("%s: Invalid zone start %llu, length %llu\n", + disk->disk_name, zone->start, zone->len); + return -ENODEV; + } /* * All zones must have the same size, with the exception on an eventual * smaller last zone. */ - if (zone->start == 0) { - if (zone->len == 0 || !is_power_of_2(zone->len)) { - pr_warn("%s: Invalid zoned device with non power of two zone size (%llu)\n", - disk->disk_name, zone->len); - return -ENODEV; - } - - args->zone_sectors = zone->len; - args->nr_zones = (capacity + zone->len - 1) >> ilog2(zone->len); - } else if (zone->start + args->zone_sectors < capacity) { - if (zone->len != args->zone_sectors) { + if (zone->start + zone->len < capacity) { + if (zone->len != zone_sectors) { pr_warn("%s: Invalid zoned device with non constant zone size\n", disk->disk_name); return -ENODEV; } - } else { - if (zone->len > args->zone_sectors) { - pr_warn("%s: Invalid zoned device with larger last zone size\n", - disk->disk_name); - return -ENODEV; - } - } - - /* Check for holes in the zone report */ - if (zone->start != args->sector) { - pr_warn("%s: Zone gap at sectors %llu..%llu\n", - disk->disk_name, args->sector, zone->start); + } else if (zone->len > zone_sectors) { + pr_warn("%s: Invalid zoned device with larger last zone size\n", + disk->disk_name); return -ENODEV; } @@ -532,11 +527,13 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, * @disk: Target disk * @update_driver_data: Callback to update driver data on the frozen disk * - * Helper function for low-level device drivers to (re) allocate and initialize - * a disk request queue zone bitmaps. This functions should normally be called - * within the disk ->revalidate method for blk-mq based drivers. For BIO based - * drivers only q->nr_zones needs to be updated so that the sysfs exposed value - * is correct. + * Helper function for low-level device drivers to check and (re) allocate and + * initialize a disk request queue zone bitmaps. This functions should normally + * be called within the disk ->revalidate method for blk-mq based drivers. + * Before calling this function, the device driver must already have set the + * device zone size (chunk_sector limit) and the max zone append limit. + * For BIO based drivers, this function cannot be used. BIO based device drivers + * only need to set disk->nr_zones so that the sysfs exposed value is correct. * If the @update_driver_data callback function is not NULL, the callback is * executed with the device request queue frozen after all zones have been * checked. @@ -545,9 +542,9 @@ int blk_revalidate_disk_zones(struct gendisk *disk, void (*update_driver_data)(struct gendisk *disk)) { struct request_queue *q = disk->queue; - struct blk_revalidate_zone_args args = { - .disk = disk, - }; + sector_t zone_sectors = q->limits.chunk_sectors; + sector_t capacity = get_capacity(disk); + struct blk_revalidate_zone_args args = { }; unsigned int noio_flag; int ret; @@ -556,13 +553,31 @@ int blk_revalidate_disk_zones(struct gendisk *disk, if (WARN_ON_ONCE(!queue_is_mq(q))) return -EIO; - if (!get_capacity(disk)) - return -EIO; + if (!capacity) + return -ENODEV; + + /* + * Checks that the device driver indicated a valid zone size and that + * the max zone append limit is set. + */ + if (!zone_sectors || !is_power_of_2(zone_sectors)) { + pr_warn("%s: Invalid non power of two zone size (%llu)\n", + disk->disk_name, zone_sectors); + return -ENODEV; + } + + if (!q->limits.max_zone_append_sectors) { + pr_warn("%s: Invalid 0 maximum zone append limit\n", + disk->disk_name); + return -ENODEV; + } /* * Ensure that all memory allocations in this context are done as if * GFP_NOIO was specified. */ + args.disk = disk; + args.nr_zones = (capacity + zone_sectors - 1) >> ilog2(zone_sectors); noio_flag = memalloc_noio_save(); ret = disk->fops->report_zones(disk, 0, UINT_MAX, blk_revalidate_zone_cb, &args); @@ -576,7 +591,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk, * If zones where reported, make sure that the entire disk capacity * has been checked. */ - if (ret > 0 && args.sector != get_capacity(disk)) { + if (ret > 0 && args.sector != capacity) { pr_warn("%s: Missing zones from sector %llu\n", disk->disk_name, args.sector); ret = -ENODEV; @@ -589,7 +604,6 @@ int blk_revalidate_disk_zones(struct gendisk *disk, */ blk_mq_freeze_queue(q); if (ret > 0) { - blk_queue_chunk_sectors(q, args.zone_sectors); disk->nr_zones = args.nr_zones; swap(disk->seq_zones_wlock, args.seq_zones_wlock); swap(disk->conv_zones_bitmap, args.conv_zones_bitmap); -- cgit