On 3/8/24 03:46, John Garry wrote:
> On 07/03/2024 20:30, Bart Van Assche wrote:
>> Commit f1437cd1e535 ("scsi: scsi_debug: Drop sdebug_queue") removed
>> the 'in_use_bm' struct member. Hence remove a reference to that struct
>> member from the procfs host info file.
>>
>> Cc: Douglas Gilbert<dgilbert@interlog.com>
>> Cc: John Garry<john.g.garry@oracle.com>
>> Fixes: f1437cd1e535 ("scsi: scsi_debug: Drop sdebug_queue")
>> Signed-off-by: Bart Van Assche<bvanassche@acm.org>
>
> Reviewed-by: John Garry <john.g.garry@oracle.com>
>
>> ---
>> drivers/scsi/scsi_debug.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
>> index acf0592d63da..36368c71221b 100644
>> --- a/drivers/scsi/scsi_debug.c
>> +++ b/drivers/scsi/scsi_debug.c
>> @@ -6516,7 +6516,7 @@ static int scsi_debug_show_info(struct seq_file
>> *m, struct Scsi_Host *host)
>> blk_mq_tagset_busy_iter(&host->tag_set,
>> sdebug_submit_queue_iter,
>> &data);
>> if (f >= 0) {
>> - seq_printf(m, " in_use_bm BUSY: %s: %d,%d\n",
>> + seq_printf(m, " BUSY: %s: %d,%d\n",
>> "first,last bits", f, l);
>
> maybe this can fit on a single line now without exceeding 80 char (which
> some people still want - I don't mind).
The most compact version of this patch I can come up with is the
following:
@@ -6384,8 +6384,8 @@ static int scsi_debug_show_info(struct seq_file
*m, struct Scsi_Host *host)
blk_mq_tagset_busy_iter(&host->tag_set, sdebug_submit_queue_iter,
&data);
if (f >= 0) {
- seq_printf(m, " in_use_bm BUSY: %s: %d,%d\n",
- "first,last bits", f, l);
+ seq_printf(m, " BUSY: first,last bits: %d,%d\n", f,
+ l);
}
}
Thanks,
Bart.
strncpy() is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We expect p_buf to be NUL-terminated based on the callsites using these transport_dump_* methods because they use the destination buf with C-string APIs like strlen() and sprintf(). memset(buf, 0, VPD_TMP_BUF_SIZE); \ transport_dump_vpd_ident_type(vpd, buf, VPD_TMP_BUF_SIZE); \ if (len + strlen(buf) >= PAGE_SIZE) \ break; \ len += sprintf(page+len, "%s", buf); \ We also do not require the NUL-padding behavior that strncpy() provides because we are manually setting the entire buffer to NUL, rendering any future padding redundant. Let's use strscpy() as it guarantees NUL-termination and doesn't NUL-pad ( and isn't deprecated :>] ). Note that we can't use the more idiomatic strscpy() usage of strscpy(dest, src, sizeof(dest)) because the size of the destination buffer is not known to the compiler. We also can't use the new 2-arg version of strscpy() from Commit e6584c3964f2f ("string: Allow 2-argument strscpy()") Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Signed-off-by: Justin Stitt <justinstitt@google.com> --- Note: build-tested only. Found with: $ rg "strncpy\(" --- drivers/target/target_core_transport.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 73d0d6133ac8..3311eb87df6d 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1112,7 +1112,7 @@ void transport_dump_vpd_proto_id( } if (p_buf) - strncpy(p_buf, buf, p_buf_len); + strscpy(p_buf, buf, p_buf_len); else pr_debug("%s", buf); } @@ -1162,7 +1162,7 @@ int transport_dump_vpd_assoc( } if (p_buf) - strncpy(p_buf, buf, p_buf_len); + strscpy(p_buf, buf, p_buf_len); else pr_debug("%s", buf); @@ -1222,7 +1222,7 @@ int transport_dump_vpd_ident_type( if (p_buf) { if (p_buf_len < strlen(buf)+1) return -EINVAL; - strncpy(p_buf, buf, p_buf_len); + strscpy(p_buf, buf, p_buf_len); } else { pr_debug("%s", buf); } @@ -1276,7 +1276,7 @@ int transport_dump_vpd_ident( } if (p_buf) - strncpy(p_buf, buf, p_buf_len); + strscpy(p_buf, buf, p_buf_len); else pr_debug("%s", buf); --- base-commit: bf3a69c6861ff4dc7892d895c87074af7bc1c400 change-id: 20240318-strncpy-drivers-target-target_core_transport-c-1950554ec04e Best regards, -- Justin Stitt <justinstitt@google.com>
On Mon, Mar 18, 2024 at 09:32:01PM +0000, Justin Stitt wrote:
> strncpy() is deprecated for use on NUL-terminated destination strings
> [1] and as such we should prefer more robust and less ambiguous string
> interfaces.
>
> We expect db_root and db_root_stage to be NUL-terminated based on its
> immediate use with pr_debug which expects a C-string argument (%s).
> Moreover, it seems NUL-padding is not required.
>
> Considering the above, a suitable replacement is `strscpy` [2] due to
> the fact that it guarantees NUL-termination on the destination buffer
> without unnecessarily NUL-padding.
>
> Additionally, we should also change snprintf() to scnprintf().
> `read_bytes` may be improperly assigned as snprintf() does NOT return
> the number of bytes written into the destination buffer, rather it
> returns the number of bytes that COULD have been written to that buffer
> if it had ample space. Conversely, scnprintf() returns the actual number
> of bytes written into the destination buffer (except the NUL-byte). This
> essentially means the ``if (!read_bytes)`` was probably never a possible
> branch.
>
> After these changes, this code is more self-describing since it uses
> string APIs that more accurately match the desired behavior.
>
> Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1]
> Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2]
> Link: https://github.com/KSPP/linux/issues/90
> Cc: linux-hardening@vger.kernel.org
> Signed-off-by: Justin Stitt <justinstitt@google.com>
Good catch on "read_bytes"!
Reviewed-by: Kees Cook <keescook@chromium.org>
--
Kees Cook
strncpy() is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We expect db_root and db_root_stage to be NUL-terminated based on its immediate use with pr_debug which expects a C-string argument (%s). Moreover, it seems NUL-padding is not required. Considering the above, a suitable replacement is `strscpy` [2] due to the fact that it guarantees NUL-termination on the destination buffer without unnecessarily NUL-padding. Additionally, we should also change snprintf() to scnprintf(). `read_bytes` may be improperly assigned as snprintf() does NOT return the number of bytes written into the destination buffer, rather it returns the number of bytes that COULD have been written to that buffer if it had ample space. Conversely, scnprintf() returns the actual number of bytes written into the destination buffer (except the NUL-byte). This essentially means the ``if (!read_bytes)`` was probably never a possible branch. After these changes, this code is more self-describing since it uses string APIs that more accurately match the desired behavior. Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Signed-off-by: Justin Stitt <justinstitt@google.com> --- Note: build-tested only. Found with: $ rg "strncpy\(" --- drivers/target/target_core_configfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index c1fbcdd16182..d78647e4f6c5 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -123,7 +123,7 @@ static ssize_t target_core_item_dbroot_store(struct config_item *item, goto unlock; } - read_bytes = snprintf(db_root_stage, DB_ROOT_LEN, "%s", page); + read_bytes = scnprintf(db_root_stage, DB_ROOT_LEN, "%s", page); if (!read_bytes) goto unlock; @@ -143,7 +143,7 @@ static ssize_t target_core_item_dbroot_store(struct config_item *item, } filp_close(fp, NULL); - strncpy(db_root, db_root_stage, read_bytes); + strscpy(db_root, db_root_stage, sizeof(db_root)); pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root); r = read_bytes; @@ -3651,7 +3651,7 @@ static void target_init_dbroot(void) { struct file *fp; - snprintf(db_root_stage, DB_ROOT_LEN, DB_ROOT_PREFERRED); + scnprintf(db_root_stage, DB_ROOT_LEN, DB_ROOT_PREFERRED); fp = filp_open(db_root_stage, O_RDONLY, 0); if (IS_ERR(fp)) { pr_err("db_root: cannot open: %s\n", db_root_stage); @@ -3664,7 +3664,7 @@ static void target_init_dbroot(void) } filp_close(fp, NULL); - strncpy(db_root, db_root_stage, DB_ROOT_LEN); + strscpy(db_root, db_root_stage, sizeof(db_root)); pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root); } --- base-commit: bf3a69c6861ff4dc7892d895c87074af7bc1c400 change-id: 20240315-strncpy-drivers-target-target_core_configfs-c-fbe862bf950a Best regards, -- Justin Stitt <justinstitt@google.com>
iscsi_sw_tcp_conn_bind does not check or cleanup previously bound sockets, nor should we allow binding the same connection twice. Signed-off-by: Khazhismel Kumykov <khazhy@google.com> --- drivers/scsi/iscsi_tcp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index e8ed60b777c6..8cf5dc203a82 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -716,6 +716,9 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, struct socket *sock; int err; + if (tcp_sw_conn->sock) + return -EINVAL; + /* lookup for existing socket */ sock = sockfd_lookup((int)transport_eph, &err); if (!sock) { -- 2.44.0.291.gc1ea87d7ee-goog
This attempts to avoid a situation where a misbehaving iscsi daemon passes a socket for a different iSCSI connection to BIND_CONN - which would result in infinite recursion and stack overflow. This will also prevent passing *other* sockets which had sk_user_data overridden, but that wouldn't have been safe anyways - since we throw away that pointer anyways. This does not cover all hypothetical scenarios where we pass bad sockets to BIND_CONN. This also papers over a different bug - we allow a daemon to call BIND_CONN twice for the same connection - which would result in, at the least, failing to uninitialize/teardown the previous socket, which will be addressed separately. Signed-off-by: Khazhismel Kumykov <khazhy@google.com> --- drivers/scsi/iscsi_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 8e14cea15f98..e8ed60b777c6 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -725,7 +725,7 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, } err = -EINVAL; - if (!sk_is_tcp(sock->sk)) + if (!sk_is_tcp(sock->sk) || sock->sk->sk_user_data) goto free_socket; err = iscsi_conn_bind(cls_session, cls_conn, is_leading); -- 2.44.0.291.gc1ea87d7ee-goog
sg_remove_sfp_usercontext() must not use sg_device_destroy() after calling scsi_device_put(). sg_device_destroy() is accessling the device queue. Which will be set to NULL if scsi_device_put() removes the last reference to the sg device. Link: https://lore.kernel.org/r/20240305150509.23896-1-Alexander@wetzel-home.de Cc: <stable@vger.kernel.org> Signed-off-by: Alexander Wetzel <Alexander@wetzel-home.de> --- This is my best shot for a real fix of the issue. I confirmed with printk's that I get the NULL pointer freeze ony when scsi_device_put() is deleting the last reference to the device. In the cases where it's not crashing there is still a reference left after the call. I don't see any obvious down side of simply swapping the calls. The alternative would by my first patch, just without the WARN_ON. Alexander --- drivers/scsi/sg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 86210e4dd0d3..80e0d1981191 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -2232,8 +2232,8 @@ sg_remove_sfp_usercontext(struct work_struct *work) "sg_remove_sfp: sfp=0x%p\n", sfp)); kfree(sfp); - scsi_device_put(sdp->device); kref_put(&sdp->d_ref, sg_device_destroy); + scsi_device_put(sdp->device); module_put(THIS_MODULE); } -- 2.44.0
>From: Prasad Pandit <pjp@fedoraproject.org>
>Fix indentation of megaraid options help text by adding
>leading spaces. Generally help text is indented by couple
>of spaces more beyond the leading tab <\t> character.
Ping..! (just checking)
---
- Prasad
The pull request you sent on Sat, 16 Mar 2024 17:58:39 -0400: > git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git scsi-misc has been merged into torvalds/linux.git: https://git.kernel.org/torvalds/c/741e9d668aa50c91e4f681511ce0e408d55dd7ce Thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/prtracker.html
Only a couple of driver updates this time (lpfc and mpt3sas) plus the usual assorted minor fixes and updates. The major core update is a set of patches moving retries out of the drivers and into the core. The patch is available here: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git scsi-misc The short changelog is: Andrew Halaney (1): scsi: ufs: qcom: Clarify comments about the initial phy_gear Arnd Bergmann (3): scsi: bfa: Fix function pointer type mismatch for state machines scsi: bfa: Fix function pointer type mismatch for hcb_qe->cbfn scsi: csiostor: Avoid function pointer casts ChanWoo Lee (3): scsi: ufs: mcq: Remove unused parameters scsi: ufs: mcq: Use ufshcd_mcq_req_to_hwq() to simplify updating hwq scsi: ufs: mcq: Add definition for REG_UFS_MEM_CFG register Colin Ian King (3): scsi: qla1280: Remove redundant assignment to variable 'mr' scsi: message: fusion: Remove redundant pointer 'hd' scsi: megaraid: Remove redundant assignment to variable 'retval' Eric Chanudet (1): scsi: ufs: qcom: Avoid re-init quirk when gears match Guixin Liu (1): scsi: mpi3mr: Use ida to manage mrioc ID Jiapeng Chong (1): scsi: fnic: Clean up some inconsistent indenting Justin Stitt (3): scsi: libfc: replace deprecated strncpy() with memcpy() scsi: lpfc: Replace deprecated strncpy() with strscpy() scsi: ibmvscsi_tgt: Replace deprecated strncpy() with strscpy() Justin Tee (17): scsi: lpfc: Copyright updates for 14.4.0.0 patches scsi: lpfc: Update lpfc version to 14.4.0.0 scsi: lpfc: Change lpfc_vport load_flag member into a bitmask scsi: lpfc: Change lpfc_vport fc_flag member into a bitmask scsi: lpfc: Protect vport fc_nodes list with an explicit spin lock scsi: lpfc: Change nlp state statistic counters into atomic_t scsi: lpfc: Remove shost_lock protection for fc_host_port shost APIs scsi: lpfc: Move handling of reset congestion statistics events scsi: lpfc: Save FPIN frequency statistics upon receipt of peer cgn notifications scsi: lpfc: Add condition to delete ndlp object after sending BLS_RJT to an ABTS scsi: lpfc: Fix failure to delete vports when discovery is in progress scsi: lpfc: Remove NLP_RCV_PLOGI early return during RSCN processing for ndlps scsi: lpfc: Allow lpfc_plogi_confirm_nport() logic to execute for Fabric nodes scsi: lpfc: Remove D_ID swap log message from trace event logger scsi: lpfc: Use sg_dma_len() API to get struct scatterlist's length scsi: lpfc: Fix possible memory leak in lpfc_rcv_padisc() scsi: lpfc: Initialize status local variable in lpfc_sli4_repost_sgl_list() Lee Jones (5): scsi: aacraid: aachba: Replace snprintf() with the safer scnprintf() variant scsi: 53c700: Remove snprintf() from sysfs call-backs and replace with sysfs_emit() scsi: 3w-xxxx: Remove snprintf() from sysfs call-backs and replace with sysfs_emit() scsi: 3w-sas: Remove snprintf() from sysfs call-backs and replace with sysfs_emit() scsi: 3w-9xxx: Remove snprintf() from sysfs call-backs and replace with sysfs_emit() Li Zhijian (5): scsi: pm8001: Convert snprintf() to sysfs_emit() scsi: isci: Convert snprintf() to sysfs_emit() scsi: ibmvscsi_tgt: Convert snprintf() to sysfs_emit() scsi: ibmvscsi: Convert snprintf() to sysfs_emit() scsi: fnic: Convert snprintf() to sysfs_emit() Lukas Bulwahn (1): scsi: core: Really include kunit tests with SCSI_LIB_KUNIT_TEST Maramaina Naresh (2): scsi: ufs: ufs-mediatek: Migrate to UFSHCD generic CPU latency PM QoS support scsi: ufs: core: Add CPU latency QoS support for UFS driver Mike Christie (19): scsi: core: Add kunit tests for scsi_check_passthrough() scsi: ufs: Have midlayer retry start stop errors scsi: sr: Have midlayer retry get_sectorsize() errors scsi: ses: Have midlayer retry scsi_execute_cmd() errors scsi: sd: Have midlayer retry read_capacity_10() errors scsi: sd: Have pr commands retry UAs scsi: core: Have SCSI midlayer retry scsi_report_lun_scan() errors scsi: core: Have midlayer retry scsi_mode_sense() UAs scsi: ch: Have midlayer retry ch_do_scsi() UAs scsi: ch: Remove unit_attention scsi: sd: Have midlayer retry sd_sync_cache() errors scsi: spi: Have midlayer retry spi_execute() UAs scsi: device_handler: rdac: Have midlayer retry send_mode_select() errors scsi: device_handler: hp_sw: Have midlayer retry scsi_execute_cmd() errors scsi: sd: Have midlayer retry sd_spinup_disk() errors scsi: sd: Use separate buf for START_STOP in sd_spinup_disk() scsi: core: Retry INQUIRY after timeout scsi: core: Have midlayer retry scsi_probe_lun() errors scsi: core: Allow passthrough to request midlayer retries Peter Wang (5): scsi: ufs: ufs-mediatek: Change default autosuspend timer scsi: core: Move autosuspend timer delay to Scsi_Host scsi: ufs: ufs-mediatek: Disable MCQ IRQ when clock off scsi: ufs: ufs-mediatek: Fix MCQ mode TM cmd timeout scsi: ufs: ufs-mediatek: Check link status after exiting hibern8 Petr Mladek (1): scsi: core: Safe warning about bad dev info string Ranjan Kumar (2): scsi: mpt3sas: Update driver version to 48.100.00.00 scsi: mpt3sas: Reload SBR without rebooting HBA Ricardo B. Marliere (6): scsi: core: Constify the struct device_type usage scsi: core: Make scsi_bus_type const scsi: target: tcm_loop: Make tcm_loop_lld_bus const scsi: scsi_debug: Make pseudo_lld_bus const scsi: iscsi: Make iscsi_flashnode_bus const scsi: fcoe: Make fcoe_bus_type const Simone Weiß (1): scsi: bfa: Remove additional unnecessary struct declarations Xiang Chen (1): scsi: hisi_sas: Remove hisi_hba->timer for v3 hw Yihang Li (3): scsi: hisi_sas: Check whether debugfs is enabled before removing or releasing it scsi: hisi_sas: Remove redundant checks for automatic debugfs dump scsi: hisi_sas: Fix a deadlock issue related to automatic dump And the diffstat: drivers/message/fusion/mptfc.c | 4 +- drivers/scsi/3w-9xxx.c | 44 +-- drivers/scsi/3w-sas.c | 36 +-- drivers/scsi/3w-xxxx.c | 44 +-- drivers/scsi/53c700.c | 2 +- drivers/scsi/Kconfig | 9 + drivers/scsi/aacraid/aachba.c | 6 +- drivers/scsi/bfa/bfa.h | 30 +- drivers/scsi/bfa/bfa_core.c | 4 +- drivers/scsi/bfa/bfa_cs.h | 21 +- drivers/scsi/bfa/bfa_fcpim.c | 51 ---- drivers/scsi/bfa/bfa_fcpim.h | 66 +++- drivers/scsi/bfa/bfa_fcs.h | 312 ++++++++++++------- drivers/scsi/bfa/bfa_fcs_fcpim.c | 23 +- drivers/scsi/bfa/bfa_fcs_lport.c | 112 ++----- drivers/scsi/bfa/bfa_fcs_rport.c | 34 ++- drivers/scsi/bfa/bfa_ioc.c | 85 +++--- drivers/scsi/bfa/bfa_ioc.h | 84 ++++-- drivers/scsi/bfa/bfa_svc.c | 72 ++--- drivers/scsi/bfa/bfa_svc.h | 115 +++++-- drivers/scsi/bfa/bfad_bsg.c | 11 +- drivers/scsi/bfa/bfad_drv.h | 31 +- drivers/scsi/ch.c | 27 +- drivers/scsi/csiostor/csio_defs.h | 18 +- drivers/scsi/csiostor/csio_lnode.c | 8 +- drivers/scsi/csiostor/csio_lnode.h | 13 - drivers/scsi/device_handler/scsi_dh_hp_sw.c | 49 ++- drivers/scsi/device_handler/scsi_dh_rdac.c | 84 +++--- drivers/scsi/fcoe/fcoe_sysfs.c | 4 +- drivers/scsi/fnic/fnic_attrs.c | 7 +- drivers/scsi/fnic/fnic_scsi.c | 4 +- drivers/scsi/hisi_sas/hisi_sas_main.c | 26 +- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 8 +- drivers/scsi/hosts.c | 2 +- drivers/scsi/ibmvscsi/ibmvfc.c | 22 +- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 24 +- drivers/scsi/isci/init.c | 2 +- drivers/scsi/libfc/fc_encode.h | 14 +- drivers/scsi/lpfc/lpfc.h | 94 +++--- drivers/scsi/lpfc/lpfc_attr.c | 107 +++---- drivers/scsi/lpfc/lpfc_bsg.c | 8 +- drivers/scsi/lpfc/lpfc_ct.c | 158 +++++----- drivers/scsi/lpfc/lpfc_debugfs.c | 14 +- drivers/scsi/lpfc/lpfc_els.c | 446 ++++++++++++---------------- drivers/scsi/lpfc/lpfc_hbadisc.c | 350 +++++++++------------- drivers/scsi/lpfc/lpfc_hw4.h | 4 +- drivers/scsi/lpfc/lpfc_init.c | 137 +++++---- drivers/scsi/lpfc/lpfc_mbox.c | 10 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 91 +++--- drivers/scsi/lpfc/lpfc_nvme.c | 20 +- drivers/scsi/lpfc/lpfc_nvmet.c | 14 +- drivers/scsi/lpfc/lpfc_scsi.c | 10 +- drivers/scsi/lpfc/lpfc_sli.c | 56 ++-- drivers/scsi/lpfc/lpfc_version.h | 6 +- drivers/scsi/lpfc/lpfc_vport.c | 69 ++--- drivers/scsi/megaraid.c | 2 +- drivers/scsi/mpi3mr/mpi3mr_os.c | 12 +- drivers/scsi/mpt3sas/mpt3sas_base.c | 99 ++++-- drivers/scsi/mpt3sas/mpt3sas_base.h | 8 +- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 54 ++++ drivers/scsi/mpt3sas/mpt3sas_ctl.h | 10 + drivers/scsi/mpt3sas/mpt3sas_scsih.c | 1 + drivers/scsi/pm8001/pm8001_ctl.c | 6 +- drivers/scsi/qla1280.c | 1 - drivers/scsi/scsi_debug.c | 4 +- drivers/scsi/scsi_devinfo.c | 6 +- drivers/scsi/scsi_lib.c | 124 +++++++- drivers/scsi/scsi_lib_test.c | 330 ++++++++++++++++++++ drivers/scsi/scsi_priv.h | 2 +- drivers/scsi/scsi_scan.c | 109 ++++--- drivers/scsi/scsi_sysfs.c | 6 +- drivers/scsi/scsi_transport_iscsi.c | 4 +- drivers/scsi/scsi_transport_spi.c | 35 +-- drivers/scsi/sd.c | 220 +++++++++----- drivers/scsi/ses.c | 66 ++-- drivers/scsi/sr.c | 38 +-- drivers/target/loopback/tcm_loop.c | 2 +- drivers/ufs/core/ufs-mcq.c | 12 +- drivers/ufs/core/ufs-sysfs.c | 49 +++ drivers/ufs/core/ufshcd.c | 90 ++++-- drivers/ufs/host/ufs-mediatek.c | 90 ++++-- drivers/ufs/host/ufs-mediatek.h | 7 +- drivers/ufs/host/ufs-qcom.c | 28 +- include/scsi/scsi_device.h | 48 +++ include/scsi/scsi_host.h | 6 +- include/ufs/ufshcd.h | 7 + include/ufs/ufshci.h | 3 + 87 files changed, 2746 insertions(+), 1835 deletions(-) create mode 100644 drivers/scsi/scsi_lib_test.c James
Hi Saurav, kernel test robot noticed the following build warnings: [auto build test WARNING on mkp-scsi/for-next] [also build test WARNING on jejb-scsi/for-next linus/master v6.8 next-20240315] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Saurav-Kashyap/qedf-Don-t-process-stag-work-during-unload-and-recovery/20240315-180830 base: https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next patch link: https://lore.kernel.org/r/20240315100600.19568-3-skashyap%40marvell.com patch subject: [PATCH 2/3] qedf: Wait for stag work during unload. config: x86_64-allmodconfig (https://download.01.org/0day-ci/archive/20240316/202403160959.uNobO4UE-lkp@intel.com/config) compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240316/202403160959.uNobO4UE-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202403160959.uNobO4UE-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/scsi/qedf/qedf_main.c:923:37: warning: variable 'qedf' is uninitialized when used here [-Wuninitialized] 923 | clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); | ^~~~ drivers/scsi/qedf/qedf_main.c:919:23: note: initialize the variable 'qedf' to silence this warning 919 | struct qedf_ctx *qedf; | ^ | = NULL 1 warning generated. vim +/qedf +923 drivers/scsi/qedf/qedf_main.c 915 916 /* Performs soft reset of qedf_ctx by simulating a link down/up */ 917 void qedf_ctx_soft_reset(struct fc_lport *lport) 918 { 919 struct qedf_ctx *qedf; 920 struct qed_link_output if_link; 921 922 if (lport->vport) { > 923 clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); 924 printk_ratelimited("Cannot issue host reset on NPIV port.\n"); 925 return; 926 } 927 928 qedf = lport_priv(lport); 929 930 qedf->flogi_pending = 0; 931 /* For host reset, essentially do a soft link up/down */ 932 atomic_set(&qedf->link_state, QEDF_LINK_DOWN); 933 QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, 934 "Queuing link down work.\n"); 935 queue_delayed_work(qedf->link_update_wq, &qedf->link_update, 936 0); 937 938 if (qedf_wait_for_upload(qedf) == false) { 939 QEDF_ERR(&qedf->dbg_ctx, "Could not upload all sessions.\n"); 940 WARN_ON(atomic_read(&qedf->num_offloads)); 941 } 942 943 /* Before setting link up query physical link state */ 944 qed_ops->common->get_link(qedf->cdev, &if_link); 945 /* Bail if the physical link is not up */ 946 if (!if_link.link_up) { 947 QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, 948 "Physical link is not up.\n"); 949 clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); 950 return; 951 } 952 /* Flush and wait to make sure link down is processed */ 953 flush_delayed_work(&qedf->link_update); 954 msleep(500); 955 956 atomic_set(&qedf->link_state, QEDF_LINK_UP); 957 qedf->vlan_id = 0; 958 QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, 959 "Queue link up work.\n"); 960 queue_delayed_work(qedf->link_update_wq, &qedf->link_update, 961 0); 962 clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); 963 } 964 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
On Fri, 2024-03-15 at 15:35 +0530, Saurav Kashyap wrote:
> Hi Martin,
>
> Please apply the qedf driver fixes to the
> scsi tree at your earliest convenience.
>
> Thanks,
> Saurav
>
> Saurav Kashyap (3):
> qedf: Don't process stag work during unload and recovery.
> qedf: Wait for stag work during unload.
> qedf: Memset qed_slowpath_params to zero before use.
>
> drivers/scsi/qedf/qedf.h | 1 +
> drivers/scsi/qedf/qedf_main.c | 43
> ++++++++++++++++++++++++++++++++++-
> 2 files changed, 43 insertions(+), 1 deletion(-)
>
This series fixed a well-reproducible kernel crash on one of our
hardware partner's systems.
For the series:
Reviewed-by: Martin Wilck <mwilck@suse.com>
Hi all, Today I was reading documentation on struct Scsi_Host, as I was interested in possible values for host_no. The documentation says that: > host_no - system wide unique number that is used for identifying this host. Issued in ascending order from 0. In the code (scsi/hosts.c: scsi_host_alloc()) host_no is set as non-error result of ida_alloc() call (as added in Commit 126a4fe010fd ("scsi: Use ida for host number management") with a good reason of reusing invalidated host_no ids). My question is about implications of using ida_alloc(). As I understand, ida does not guarantee the order of id issuing, only that id is unclaimed in the pool and is within limits (which is 0 - INT_MAX for ida_alloc). Given that, my questions are: 1) Should it be mentioned in the documentation, that host_no is now reclaimable? The current wording is not clear about it; 2) The documentation mentions > sh_list - a double linked list of pointers to all struct Scsi_Host instances (currently ordered by ascending host_no) I could not find what it would be now in the code, but it seems that maintaining such a thing ordered should be a little less trivial with reclaimable ids; 3) Does ida_alloc() ensure ascending order? Is there a possibility of some new-more-effective ida implementation in the future, that honors id uniqueness and limits, but does not guarantee any particular ordering of id issuing? If it is possible, what would it break? 4) Should host_no really be limited only by int capacity (as it is now) or maybe some additional limits would make sense? There is at least one case in the current code with a buffer overrun if huge host_no is used (which led me to the research on host_no). Any clarification on the matter would be appreciated!
Hello Quinn Tran, Commit 881eb861ca38 ("scsi: qla2xxx: Fix N2N stuck connection") from Feb 27, 2024 (linux-next), leads to the following Smatch static checker warning: drivers/scsi/qla2xxx/qla_iocb.c:3060 qla24xx_els_dcmd2_iocb() warn: missing error code here? 'qla2x00_get_sp()' failed drivers/scsi/qla2xxx/qla_iocb.c 3043 int 3044 qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, 3045 fc_port_t *fcport) 3046 { 3047 srb_t *sp; 3048 struct srb_iocb *elsio = NULL; 3049 struct qla_hw_data *ha = vha->hw; 3050 int rval = QLA_SUCCESS; ^^^^^^^^^^^^^^^^^^^^^^^ 3051 void *ptr, *resp_ptr; 3052 3053 /* Alloc SRB structure 3054 * ref: INIT 3055 */ 3056 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); 3057 if (!sp) { 3058 ql_log(ql_log_info, vha, 0x70e6, 3059 "SRB allocation failed\n"); --> 3060 goto done; This used to return -ENOMEM; Should it return QLA_FUNCTION_FAILED? 3061 } 3062 3063 fcport->flags |= FCF_ASYNC_SENT; 3064 qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_PEND); 3065 elsio = &sp->u.iocb_cmd; 3066 ql_dbg(ql_dbg_io, vha, 0x3073, 3067 "%s Enter: PLOGI portid=%06x\n", __func__, fcport->d_id.b24); 3068 3069 sp->type = SRB_ELS_DCMD; 3070 sp->name = "ELS_DCMD"; 3071 sp->fcport = fcport; 3072 qla2x00_init_async_sp(sp, ELS_DCMD_TIMEOUT + 2, 3073 qla2x00_els_dcmd2_sp_done); 3074 sp->u.iocb_cmd.timeout = qla2x00_els_dcmd2_iocb_timeout; 3075 3076 elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE; 3077 3078 ptr = elsio->u.els_plogi.els_plogi_pyld = 3079 dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.tx_size, 3080 &elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL); 3081 3082 if (!elsio->u.els_plogi.els_plogi_pyld) { 3083 rval = QLA_FUNCTION_FAILED; 3084 goto done_free_sp; 3085 } 3086 3087 resp_ptr = elsio->u.els_plogi.els_resp_pyld = 3088 dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.rx_size, 3089 &elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL); 3090 3091 if (!elsio->u.els_plogi.els_resp_pyld) { 3092 rval = QLA_FUNCTION_FAILED; 3093 goto done_free_sp; 3094 } 3095 3096 ql_dbg(ql_dbg_io, vha, 0x3073, "PLOGI %p %p\n", ptr, resp_ptr); 3097 3098 memset(ptr, 0, sizeof(struct els_plogi_payload)); 3099 memset(resp_ptr, 0, sizeof(struct els_plogi_payload)); 3100 memcpy(elsio->u.els_plogi.els_plogi_pyld->data, 3101 (void *)&ha->plogi_els_payld + offsetof(struct fc_els_flogi, fl_csp), 3102 sizeof(ha->plogi_els_payld) - offsetof(struct fc_els_flogi, fl_csp)); 3103 3104 elsio->u.els_plogi.els_cmd = els_opcode; 3105 elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; 3106 3107 if (els_opcode == ELS_DCMD_PLOGI && DBELL_ACTIVE(vha)) { 3108 struct fc_els_flogi *p = ptr; 3109 p->fl_csp.sp_features |= cpu_to_be16(FC_SP_FT_SEC); 3110 } 3111 3112 ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n"); 3113 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x0109, 3114 (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 3115 sizeof(*elsio->u.els_plogi.els_plogi_pyld)); 3116 3117 rval = qla2x00_start_sp(sp); 3118 if (rval != QLA_SUCCESS) { 3119 fcport->flags |= FCF_LOGIN_NEEDED; 3120 set_bit(RELOGIN_NEEDED, &vha->dpc_flags); 3121 goto done_free_sp; 3122 } else { 3123 ql_dbg(ql_dbg_disc, vha, 0x3074, 3124 "%s PLOGI sent, hdl=%x, loopid=%x, to port_id %06x from port_id %06x\n", 3125 sp->name, sp->handle, fcport->loop_id, 3126 fcport->d_id.b24, vha->d_id.b24); 3127 } 3128 3129 return rval; 3130 3131 done_free_sp: 3132 qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi); 3133 /* ref: INIT */ 3134 kref_put(&sp->cmd_kref, qla2x00_sp_release); 3135 done: 3136 fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); 3137 qla2x00_set_fcport_disc_state(fcport, DSC_DELETED); 3138 return rval; 3139 } regards, dan carpenter
- Memset qed_slowpath_params to zero before use. Signed-off-by: Saurav Kashyap <skashyap@marvell.com> Signed-off-by: Nilesh Javali <njavali@marvell.com> --- drivers/scsi/qedf/qedf_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index d441054dadb7..d4563d28d98f 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -3473,6 +3473,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) } /* Start the Slowpath-process */ + memset(&slowpath_params, 0, sizeof(struct qed_slowpath_params)); slowpath_params.int_mode = QED_INT_MODE_MSIX; slowpath_params.drv_major = QEDF_DRIVER_MAJOR_VER; slowpath_params.drv_minor = QEDF_DRIVER_MINOR_VER; -- 2.23.1
If stag work is already schedule and unload is called, it can lead to issues as unload cleanups the work element, wait for stag work to get completed before cleanup during unload. Signed-off-by: Saurav Kashyap <skashyap@marvell.com> Signed-off-by: Nilesh Javali <njavali@marvell.com> --- drivers/scsi/qedf/qedf.h | 1 + drivers/scsi/qedf/qedf_main.c | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h index 5058e01b65a2..98afdfe63600 100644 --- a/drivers/scsi/qedf/qedf.h +++ b/drivers/scsi/qedf/qedf.h @@ -363,6 +363,7 @@ struct qedf_ctx { #define QEDF_IN_RECOVERY 5 #define QEDF_DBG_STOP_IO 6 #define QEDF_PROBING 8 +#define QEDF_STAG_IN_PROGRESS 9 unsigned long flags; /* Miscellaneous state flags */ int fipvlan_retries; u8 num_queues; diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index e882aec86765..d441054dadb7 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -318,11 +318,18 @@ static struct fc_seq *qedf_elsct_send(struct fc_lport *lport, u32 did, */ if (resp == fc_lport_flogi_resp) { qedf->flogi_cnt++; + qedf->flogi_pending++; + + if (test_bit(QEDF_UNLOADING, &qedf->flags)) { + QEDF_ERR(&qedf->dbg_ctx, "Driver unloading\n"); + qedf->flogi_pending = 0; + } + if (qedf->flogi_pending >= QEDF_FLOGI_RETRY_CNT) { schedule_delayed_work(&qedf->stag_work, 2); return NULL; } - qedf->flogi_pending++; + return fc_elsct_send(lport, did, fp, op, qedf_flogi_resp, arg, timeout); } @@ -913,6 +920,7 @@ void qedf_ctx_soft_reset(struct fc_lport *lport) struct qed_link_output if_link; if (lport->vport) { + clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); printk_ratelimited("Cannot issue host reset on NPIV port.\n"); return; } @@ -938,6 +946,7 @@ void qedf_ctx_soft_reset(struct fc_lport *lport) if (!if_link.link_up) { QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, "Physical link is not up.\n"); + clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); return; } /* Flush and wait to make sure link down is processed */ @@ -950,6 +959,7 @@ void qedf_ctx_soft_reset(struct fc_lport *lport) "Queue link up work.\n"); queue_delayed_work(qedf->link_update_wq, &qedf->link_update, 0); + clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); } /* Reset the host by gracefully logging out and then logging back in */ @@ -3721,6 +3731,7 @@ static void __qedf_remove(struct pci_dev *pdev, int mode) { struct qedf_ctx *qedf; int rc; + int cnt = 0; if (!pdev) { QEDF_ERR(NULL, "pdev is NULL.\n"); @@ -3738,6 +3749,17 @@ static void __qedf_remove(struct pci_dev *pdev, int mode) return; } +stag_in_prog: + if (test_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags)) { + QEDF_ERR(&qedf->dbg_ctx, "Stag in progress, cnt=%d.\n", cnt); + cnt++; + + if (cnt < 5) { + msleep(500); + goto stag_in_prog; + } + } + if (mode != QEDF_MODE_RECOVERY) set_bit(QEDF_UNLOADING, &qedf->flags); @@ -4013,6 +4035,8 @@ void qedf_stag_change_work(struct work_struct *work) return; } + set_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); + printk_ratelimited("[%s]:[%s:%d]:%d: Performing software context reset.", dev_name(&qedf->pdev->dev), __func__, __LINE__, qedf->dbg_ctx.host_no); -- 2.23.1
Stag work can cause issues during unload and recovery, hence don't process it. Signed-off-by: Saurav Kashyap <skashyap@marvell.com> Signed-off-by: Nilesh Javali <njavali@marvell.com> --- drivers/scsi/qedf/qedf_main.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index a58353b7b4e8..e882aec86765 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -3997,6 +3997,22 @@ void qedf_stag_change_work(struct work_struct *work) struct qedf_ctx *qedf = container_of(work, struct qedf_ctx, stag_work.work); + if (!qedf) { + QEDF_ERR(&qedf->dbg_ctx, "qedf is NULL"); + return; + } + + if (test_bit(QEDF_IN_RECOVERY, &qedf->flags)) { + QEDF_ERR(&qedf->dbg_ctx, + "Already is in recovery, hence not calling software context reset.\n"); + return; + } + + if (test_bit(QEDF_UNLOADING, &qedf->flags)) { + QEDF_ERR(&qedf->dbg_ctx, "Driver unloading\n"); + return; + } + printk_ratelimited("[%s]:[%s:%d]:%d: Performing software context reset.", dev_name(&qedf->pdev->dev), __func__, __LINE__, qedf->dbg_ctx.host_no); -- 2.23.1
Hi Martin, Please apply the qedf driver fixes to the scsi tree at your earliest convenience. Thanks, Saurav Saurav Kashyap (3): qedf: Don't process stag work during unload and recovery. qedf: Wait for stag work during unload. qedf: Memset qed_slowpath_params to zero before use. drivers/scsi/qedf/qedf.h | 1 + drivers/scsi/qedf/qedf_main.c | 43 ++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) -- 2.23.1
From: Po-Wen Kao <powen.kao@mediatek.com> Move sip command and define to a new sip header file. Acked-by: Chun-Hung Wu <Chun-Hung.Wu@mediatek.com> Reviewed-by: Peter Wang <peter.wang@mediatek.com> Signed-off-by: Peter Wang <peter.wang@mediatek.com> Signed-off-by: Po-Wen Kao <powen.kao@mediatek.com> --- drivers/ufs/host/ufs-mediatek-sip.h | 90 +++++++++++++++++++++++++++++ drivers/ufs/host/ufs-mediatek.c | 3 +- drivers/ufs/host/ufs-mediatek.h | 79 ------------------------- 3 files changed, 92 insertions(+), 80 deletions(-) create mode 100755 drivers/ufs/host/ufs-mediatek-sip.h diff --git a/drivers/ufs/host/ufs-mediatek-sip.h b/drivers/ufs/host/ufs-mediatek-sip.h new file mode 100755 index 000000000000..35d1d5e76a2c --- /dev/null +++ b/drivers/ufs/host/ufs-mediatek-sip.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 MediaTek Inc. + */ + +#ifndef _UFS_MEDIATEK_SIP_H +#define _UFS_MEDIATEK_SIP_H + +#include <linux/soc/mediatek/mtk_sip_svc.h> + +/* + * SiP (Slicon Partner) commands + */ +#define MTK_SIP_UFS_CONTROL MTK_SIP_SMC_CMD(0x276) +#define UFS_MTK_SIP_VA09_PWR_CTRL BIT(0) +#define UFS_MTK_SIP_DEVICE_RESET BIT(1) +#define UFS_MTK_SIP_CRYPTO_CTRL BIT(2) +#define UFS_MTK_SIP_REF_CLK_NOTIFICATION BIT(3) +#define UFS_MTK_SIP_HOST_PWR_CTRL BIT(5) +#define UFS_MTK_SIP_GET_VCC_NUM BIT(6) +#define UFS_MTK_SIP_DEVICE_PWR_CTRL BIT(7) + + +/* + * Multi-VCC by Numbering + */ +enum ufs_mtk_vcc_num { + UFS_VCC_NONE = 0, + UFS_VCC_1, + UFS_VCC_2, + UFS_VCC_MAX +}; + +/* + * Host Power Control options + */ +enum { + HOST_PWR_HCI = 0, + HOST_PWR_MPHY +}; + +/* + * SMC call wrapper function + */ +struct ufs_mtk_smc_arg { + unsigned long cmd; + struct arm_smccc_res *res; + unsigned long v1; + unsigned long v2; + unsigned long v3; + unsigned long v4; + unsigned long v5; + unsigned long v6; + unsigned long v7; +}; + + +static inline void _ufs_mtk_smc(struct ufs_mtk_smc_arg s) +{ + arm_smccc_smc(MTK_SIP_UFS_CONTROL, + s.cmd, + s.v1, s.v2, s.v3, s.v4, s.v5, s.v6, s.res); +} + +#define ufs_mtk_smc(...) \ + _ufs_mtk_smc((struct ufs_mtk_smc_arg) {__VA_ARGS__}) + +/* Sip kernel interface */ +#define ufs_mtk_va09_pwr_ctrl(res, on) \ + ufs_mtk_smc(UFS_MTK_SIP_VA09_PWR_CTRL, &(res), on) + +#define ufs_mtk_crypto_ctrl(res, enable) \ + ufs_mtk_smc(UFS_MTK_SIP_CRYPTO_CTRL, &(res), enable) + +#define ufs_mtk_ref_clk_notify(on, stage, res) \ + ufs_mtk_smc(UFS_MTK_SIP_REF_CLK_NOTIFICATION, &(res), on, stage) + +#define ufs_mtk_device_reset_ctrl(high, res) \ + ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, &(res), high) + +#define ufs_mtk_host_pwr_ctrl(opt, on, res) \ + ufs_mtk_smc(UFS_MTK_SIP_HOST_PWR_CTRL, &(res), opt, on) + +#define ufs_mtk_get_vcc_num(res) \ + ufs_mtk_smc(UFS_MTK_SIP_GET_VCC_NUM, &(res)) + +#define ufs_mtk_device_pwr_ctrl(on, ufs_version, res) \ + ufs_mtk_smc(UFS_MTK_SIP_DEVICE_PWR_CTRL, &(res), on, ufs_version) + +#endif /* !_UFS_MEDIATEK_SIP_H */ diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 2ee7881533ec..bb5b11185d8a 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -20,13 +20,14 @@ #include <linux/pm_qos.h> #include <linux/regulator/consumer.h> #include <linux/reset.h> -#include <linux/soc/mediatek/mtk_sip_svc.h> #include <ufs/ufshcd.h> #include "ufshcd-pltfrm.h" #include <ufs/ufs_quirks.h> #include <ufs/unipro.h> + #include "ufs-mediatek.h" +#include "ufs-mediatek-sip.h" static int ufs_mtk_config_mcq(struct ufs_hba *hba, bool irq); diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h index 3f698af5f5ac..9226e95c4a60 100644 --- a/drivers/ufs/host/ufs-mediatek.h +++ b/drivers/ufs/host/ufs-mediatek.h @@ -8,7 +8,6 @@ #include <linux/bitops.h> #include <linux/pm_qos.h> -#include <linux/soc/mediatek/mtk_sip_svc.h> /* * MCQ define and struct @@ -100,18 +99,6 @@ enum { VS_HIB_EXIT = 13, }; -/* - * SiP commands - */ -#define MTK_SIP_UFS_CONTROL MTK_SIP_SMC_CMD(0x276) -#define UFS_MTK_SIP_VA09_PWR_CTRL BIT(0) -#define UFS_MTK_SIP_DEVICE_RESET BIT(1) -#define UFS_MTK_SIP_CRYPTO_CTRL BIT(2) -#define UFS_MTK_SIP_REF_CLK_NOTIFICATION BIT(3) -#define UFS_MTK_SIP_HOST_PWR_CTRL BIT(5) -#define UFS_MTK_SIP_GET_VCC_NUM BIT(6) -#define UFS_MTK_SIP_DEVICE_PWR_CTRL BIT(7) - /* * VS_DEBUGCLOCKENABLE */ @@ -198,70 +185,4 @@ struct ufs_mtk_host { struct ufs_mtk_mcq_intr_info mcq_intr_info[UFSHCD_MAX_Q_NR]; }; -/* - * Multi-VCC by Numbering - */ -enum ufs_mtk_vcc_num { - UFS_VCC_NONE = 0, - UFS_VCC_1, - UFS_VCC_2, - UFS_VCC_MAX -}; - -/* - * Host Power Control options - */ -enum { - HOST_PWR_HCI = 0, - HOST_PWR_MPHY -}; - -/* - * SMC call wrapper function - */ -struct ufs_mtk_smc_arg { - unsigned long cmd; - struct arm_smccc_res *res; - unsigned long v1; - unsigned long v2; - unsigned long v3; - unsigned long v4; - unsigned long v5; - unsigned long v6; - unsigned long v7; -}; - -static void _ufs_mtk_smc(struct ufs_mtk_smc_arg s) -{ - arm_smccc_smc(MTK_SIP_UFS_CONTROL, - s.cmd, s.v1, s.v2, s.v3, s.v4, s.v5, s.v6, s.res); -} - -#define ufs_mtk_smc(...) \ - _ufs_mtk_smc((struct ufs_mtk_smc_arg) {__VA_ARGS__}) - -/* - * SMC call interface - */ -#define ufs_mtk_va09_pwr_ctrl(res, on) \ - ufs_mtk_smc(UFS_MTK_SIP_VA09_PWR_CTRL, &(res), on) - -#define ufs_mtk_crypto_ctrl(res, enable) \ - ufs_mtk_smc(UFS_MTK_SIP_CRYPTO_CTRL, &(res), enable) - -#define ufs_mtk_ref_clk_notify(on, stage, res) \ - ufs_mtk_smc(UFS_MTK_SIP_REF_CLK_NOTIFICATION, &(res), on, stage) - -#define ufs_mtk_device_reset_ctrl(high, res) \ - ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, &(res), high) - -#define ufs_mtk_host_pwr_ctrl(opt, on, res) \ - ufs_mtk_smc(UFS_MTK_SIP_HOST_PWR_CTRL, &(res), opt, on) - -#define ufs_mtk_get_vcc_num(res) \ - ufs_mtk_smc(UFS_MTK_SIP_GET_VCC_NUM, &(res)) - -#define ufs_mtk_device_pwr_ctrl(on, ufs_ver, res) \ - ufs_mtk_smc(UFS_MTK_SIP_DEVICE_PWR_CTRL, &(res), on, ufs_ver) - #endif /* !_UFS_MEDIATEK_H */ -- 2.18.0
From: Po-Wen Kao <powen.kao@mediatek.com> Add new mediatek host cap UFS_MTK_CAP_DISABLE_MCQ to allow disable MCQ feature by assigning dts boolean property "mediatek,ufs-disable-mcq"" Acked-by: Chun-Hung Wu <Chun-Hung.Wu@mediatek.com> Reviewed-by: Avri Altman <avri.altman@wdc.com> Reviewed-by: Peter Wang <peter.wang@mediatek.com> Signed-off-by: Peter Wang <peter.wang@mediatek.com> Signed-off-by: Po-Wen Kao <powen.kao@mediatek.com> --- drivers/ufs/host/ufs-mediatek.c | 12 ++++++++++++ drivers/ufs/host/ufs-mediatek.h | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 25bf5a13cddd..2ee7881533ec 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -640,6 +640,9 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba) if (of_property_read_bool(np, "mediatek,ufs-tx-skew-fix")) host->caps |= UFS_MTK_CAP_TX_SKEW_FIX; + if (of_property_read_bool(np, "mediatek,ufs-disable-mcq")) + host->caps |= UFS_MTK_CAP_DISABLE_MCQ; + dev_info(hba->dev, "caps: 0x%x", host->caps); } @@ -874,6 +877,9 @@ static void ufs_mtk_init_mcq_irq(struct ufs_hba *hba) host->mcq_nr_intr = UFSHCD_MAX_Q_NR; pdev = container_of(hba->dev, struct platform_device, dev); + if (host->caps & UFS_MTK_CAP_DISABLE_MCQ) + goto failed; + for (i = 0; i < host->mcq_nr_intr; i++) { /* irq index 0 is legacy irq, sq/cq irq start from index 1 */ irq = platform_get_irq(pdev, i + 1); @@ -1585,6 +1591,12 @@ static int ufs_mtk_clk_scale_notify(struct ufs_hba *hba, bool scale_up, static int ufs_mtk_get_hba_mac(struct ufs_hba *hba) { + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + /* MCQ operation not permitted */ + if (host->caps & UFS_MTK_CAP_DISABLE_MCQ) + return -EPERM; + return MAX_SUPP_MAC; } diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h index c1acbfc5568f..3f698af5f5ac 100644 --- a/drivers/ufs/host/ufs-mediatek.h +++ b/drivers/ufs/host/ufs-mediatek.h @@ -144,6 +144,7 @@ enum ufs_mtk_host_caps { UFS_MTK_CAP_ALLOW_VCCQX_LPM = 1 << 5, UFS_MTK_CAP_PMC_VIA_FASTAUTO = 1 << 6, UFS_MTK_CAP_TX_SKEW_FIX = 1 << 7, + UFS_MTK_CAP_DISABLE_MCQ = 1 << 8, }; struct ufs_mtk_crypt_cfg { -- 2.18.0
From: Peter Wang <peter.wang@mediatek.com> This patch will reset mphy when host reset. Backup mphy setting after mphy reset control get. Restore mphy setting after mphy reset. Acked-by: Chun-Hung Wu <Chun-Hung.Wu@mediatek.com> Signed-off-by: Peter Wang <peter.wang@mediatek.com> --- drivers/ufs/host/ufs-mediatek-sip.h | 9 ++++++++- drivers/ufs/host/ufs-mediatek.c | 14 ++++++++++++++ drivers/ufs/host/ufs-mediatek.h | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/ufs/host/ufs-mediatek-sip.h b/drivers/ufs/host/ufs-mediatek-sip.h index c26513aedee3..caeb70a6ae83 100755 --- a/drivers/ufs/host/ufs-mediatek-sip.h +++ b/drivers/ufs/host/ufs-mediatek-sip.h @@ -19,7 +19,7 @@ #define UFS_MTK_SIP_SRAM_PWR_CTRL BIT(5) #define UFS_MTK_SIP_GET_VCC_NUM BIT(6) #define UFS_MTK_SIP_DEVICE_PWR_CTRL BIT(7) - +#define UFS_MTK_SIP_MPHY_CTRL BIT(8) /* * Multi-VCC by Numbering @@ -31,6 +31,10 @@ enum ufs_mtk_vcc_num { UFS_VCC_MAX }; +enum ufs_mtk_mphy_op { + UFS_MPHY_BACKUP = 0, + UFS_MPHY_RESTORE +}; /* * SMC call wrapper function @@ -80,4 +84,7 @@ static inline void _ufs_mtk_smc(struct ufs_mtk_smc_arg s) #define ufs_mtk_device_pwr_ctrl(on, ufs_version, res) \ ufs_mtk_smc(UFS_MTK_SIP_DEVICE_PWR_CTRL, &(res), on, ufs_version) +#define ufs_mtk_mphy_ctrl(op, res) \ + ufs_mtk_smc(UFS_MTK_SIP_MPHY_CTRL, &(res), op) + #endif /* !_UFS_MEDIATEK_SIP_H */ diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 90523652a6fb..a18978060c77 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -185,16 +185,23 @@ static void ufs_mtk_crypto_enable(struct ufs_hba *hba) static void ufs_mtk_host_reset(struct ufs_hba *hba) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); + struct arm_smccc_res res; reset_control_assert(host->hci_reset); reset_control_assert(host->crypto_reset); reset_control_assert(host->unipro_reset); + reset_control_assert(host->mphy_reset); usleep_range(100, 110); reset_control_deassert(host->unipro_reset); reset_control_deassert(host->crypto_reset); reset_control_deassert(host->hci_reset); + reset_control_deassert(host->mphy_reset); + + /* restore mphy setting aftre mphy reset */ + if (host->mphy_reset) + ufs_mtk_mphy_ctrl(UFS_MPHY_RESTORE, res); } static void ufs_mtk_init_reset_control(struct ufs_hba *hba, @@ -219,6 +226,8 @@ static void ufs_mtk_init_reset(struct ufs_hba *hba) "unipro_rst"); ufs_mtk_init_reset_control(hba, &host->crypto_reset, "crypto_rst"); + ufs_mtk_init_reset_control(hba, &host->mphy_reset, + "mphy_rst"); } static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba, @@ -918,6 +927,7 @@ static int ufs_mtk_init(struct ufs_hba *hba) struct device *dev = hba->dev; struct ufs_mtk_host *host; int err = 0; + struct arm_smccc_res res; host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); if (!host) { @@ -946,6 +956,10 @@ static int ufs_mtk_init(struct ufs_hba *hba) ufs_mtk_init_reset(hba); + /* backup mphy setting if mphy can reset */ + if (host->mphy_reset) + ufs_mtk_mphy_ctrl(UFS_MPHY_BACKUP, res); + /* Enable runtime autosuspend */ hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND; diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h index 9226e95c4a60..eb3744ae3a42 100644 --- a/drivers/ufs/host/ufs-mediatek.h +++ b/drivers/ufs/host/ufs-mediatek.h @@ -167,6 +167,7 @@ struct ufs_mtk_host { struct reset_control *hci_reset; struct reset_control *unipro_reset; struct reset_control *crypto_reset; + struct reset_control *mphy_reset; struct ufs_hba *hba; struct ufs_mtk_crypt_cfg *crypt; struct ufs_mtk_clk mclk; -- 2.18.0
From: Peter Wang <peter.wang@mediatek.com> Mediatek tx skew issue fix by check dts setting and vendor/model. Then set PA_TACTIVATE set 8 Acked-by: Chun-Hung Wu <Chun-Hung.Wu@mediatek.com> Reviewed-by: Avri Altman <avri.altman@wdc.com> Signed-off-by: Peter Wang <peter.wang@mediatek.com> --- drivers/ufs/host/ufs-mediatek.c | 21 +++++++++++++++++++++ drivers/ufs/host/ufs-mediatek.h | 1 + 2 files changed, 22 insertions(+) diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 147b5286ec98..25bf5a13cddd 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -119,6 +119,13 @@ static bool ufs_mtk_is_pmc_via_fastauto(struct ufs_hba *hba) return !!(host->caps & UFS_MTK_CAP_PMC_VIA_FASTAUTO); } +static bool ufs_mtk_is_tx_skew_fix(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + return (host->caps & UFS_MTK_CAP_TX_SKEW_FIX); +} + static bool ufs_mtk_is_allow_vccqx_lpm(struct ufs_hba *hba) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); @@ -630,6 +637,9 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba) if (of_property_read_bool(np, "mediatek,ufs-pmc-via-fastauto")) host->caps |= UFS_MTK_CAP_PMC_VIA_FASTAUTO; + if (of_property_read_bool(np, "mediatek,ufs-tx-skew-fix")) + host->caps |= UFS_MTK_CAP_TX_SKEW_FIX; + dev_info(hba->dev, "caps: 0x%x", host->caps); } @@ -1423,6 +1433,17 @@ static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba) if (mid == UFS_VENDOR_SAMSUNG) { ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 6); ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), 10); + } else if (mid == UFS_VENDOR_MICRON) { + /* Only for the host which have TX skew issue */ + if (ufs_mtk_is_tx_skew_fix(hba) && + (STR_PRFX_EQUAL("MT128GBCAV2U31", dev_info->model) || + STR_PRFX_EQUAL("MT256GBCAV4U31", dev_info->model) || + STR_PRFX_EQUAL("MT512GBCAV8U31", dev_info->model) || + STR_PRFX_EQUAL("MT256GBEAX4U40", dev_info->model) || + STR_PRFX_EQUAL("MT512GAYAX4U40", dev_info->model) || + STR_PRFX_EQUAL("MT001TAYAX8U40", dev_info->model))) { + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 8); + } } /* diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h index d0a5ab17860a..c1acbfc5568f 100644 --- a/drivers/ufs/host/ufs-mediatek.h +++ b/drivers/ufs/host/ufs-mediatek.h @@ -143,6 +143,7 @@ enum ufs_mtk_host_caps { */ UFS_MTK_CAP_ALLOW_VCCQX_LPM = 1 << 5, UFS_MTK_CAP_PMC_VIA_FASTAUTO = 1 << 6, + UFS_MTK_CAP_TX_SKEW_FIX = 1 << 7, }; struct ufs_mtk_crypt_cfg { -- 2.18.0
From: Peter Wang <peter.wang@mediatek.com> VSX(the upper layer of VCCQ/VCCQ2) should 1. Always set to hpm mode if ufs device is active. 2. Enter lpm mode only if ufs device is not active. VCCQX should 1. Keep hpm mode if vccq and vccq2 not set in dts. 2. Keep hpm mode if vcc not set in dts keep vcc always on. 3. Keep hpm if broken vcc keep vcc always on and not allow vccq lpm. 4. Except upper case, can enter lpm mode if ufs device is not active. Acked-by: Chun-Hung Wu <Chun-Hung.Wu@mediatek.com> Signed-off-by: Peter Wang <peter.wang@mediatek.com> --- drivers/ufs/host/ufs-mediatek.c | 41 +++++++++++++++++++++++---------- drivers/ufs/host/ufs-mediatek.h | 6 +++++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 776bca4f70c8..147b5286ec98 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -119,6 +119,13 @@ static bool ufs_mtk_is_pmc_via_fastauto(struct ufs_hba *hba) return !!(host->caps & UFS_MTK_CAP_PMC_VIA_FASTAUTO); } +static bool ufs_mtk_is_allow_vccqx_lpm(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + return (host->caps & UFS_MTK_CAP_ALLOW_VCCQX_LPM); +} + static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) { u32 tmp; @@ -1271,27 +1278,37 @@ static void ufs_mtk_vsx_set_lpm(struct ufs_hba *hba, bool lpm) static void ufs_mtk_dev_vreg_set_lpm(struct ufs_hba *hba, bool lpm) { - if (!hba->vreg_info.vccq && !hba->vreg_info.vccq2) - return; + bool skip_vccqx = false; - /* Skip if VCC is assumed always-on */ - if (!hba->vreg_info.vcc) - return; - - /* Bypass LPM when device is still active */ + /* Prevent entering LPM when device is still active */ if (lpm && ufshcd_is_ufs_dev_active(hba)) return; - /* Bypass LPM if VCC is enabled */ - if (lpm && hba->vreg_info.vcc->enabled) - return; + /* Skip vccqx lpm control and control vsx only */ + if (!hba->vreg_info.vccq && !hba->vreg_info.vccq2) + skip_vccqx = true; + + /* VCC is always-on, control vsx only */ + if (!hba->vreg_info.vcc) + skip_vccqx = true; + + /* Broken vcc keep vcc always on, most case control vsx only */ + if (lpm && hba->vreg_info.vcc && hba->vreg_info.vcc->enabled) { + /* Some device vccqx/vsx can enter lpm */ + if (ufs_mtk_is_allow_vccqx_lpm(hba)) + skip_vccqx = false; + else /* control vsx only */ + skip_vccqx = true; + } if (lpm) { - ufs_mtk_vccqx_set_lpm(hba, lpm); + if (!skip_vccqx) + ufs_mtk_vccqx_set_lpm(hba, lpm); ufs_mtk_vsx_set_lpm(hba, lpm); } else { ufs_mtk_vsx_set_lpm(hba, lpm); - ufs_mtk_vccqx_set_lpm(hba, lpm); + if (!skip_vccqx) + ufs_mtk_vccqx_set_lpm(hba, lpm); } } diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h index f76e80d91729..d0a5ab17860a 100644 --- a/drivers/ufs/host/ufs-mediatek.h +++ b/drivers/ufs/host/ufs-mediatek.h @@ -136,6 +136,12 @@ enum ufs_mtk_host_caps { UFS_MTK_CAP_VA09_PWR_CTRL = 1 << 1, UFS_MTK_CAP_DISABLE_AH8 = 1 << 2, UFS_MTK_CAP_BROKEN_VCC = 1 << 3, + + /* + * Override UFS_MTK_CAP_BROKEN_VCC's behavior to + * allow vccqx upstream to enter LPM + */ + UFS_MTK_CAP_ALLOW_VCCQX_LPM = 1 << 5, UFS_MTK_CAP_PMC_VIA_FASTAUTO = 1 << 6, }; -- 2.18.0
From: Alice Chao <alice.chao@mediatek.com> Add mtcmos control function and config. Reviewed-by: Peter Wang <peter.wang@mediatek.com> Acked-by: Chun-Hung Wu <Chun-Hung.Wu@mediatek.com> Signed-off-by: Peter Wang <peter.wang@mediatek.com> Signed-off-by: Alice Chao <alice.chao@mediatek.com> --- drivers/ufs/host/ufs-mediatek-sip.h | 4 ++++ drivers/ufs/host/ufs-mediatek.c | 35 +++++++++++++++++++++++++++++ drivers/ufs/host/ufs-mediatek.h | 2 ++ 3 files changed, 41 insertions(+) diff --git a/drivers/ufs/host/ufs-mediatek-sip.h b/drivers/ufs/host/ufs-mediatek-sip.h index caeb70a6ae83..7d17aedf6fb8 100755 --- a/drivers/ufs/host/ufs-mediatek-sip.h +++ b/drivers/ufs/host/ufs-mediatek-sip.h @@ -20,6 +20,7 @@ #define UFS_MTK_SIP_GET_VCC_NUM BIT(6) #define UFS_MTK_SIP_DEVICE_PWR_CTRL BIT(7) #define UFS_MTK_SIP_MPHY_CTRL BIT(8) +#define UFS_MTK_SIP_MTCMOS_CTRL BIT(9) /* * Multi-VCC by Numbering @@ -87,4 +88,7 @@ static inline void _ufs_mtk_smc(struct ufs_mtk_smc_arg s) #define ufs_mtk_mphy_ctrl(op, res) \ ufs_mtk_smc(UFS_MTK_SIP_MPHY_CTRL, &(res), op) +#define ufs_mtk_mtcmos_ctrl(op, res) \ + ufs_mtk_smc(UFS_MTK_SIP_MTCMOS_CTRL, &(res), op) + #endif /* !_UFS_MEDIATEK_SIP_H */ diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index a18978060c77..1629323df6cb 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -127,6 +127,13 @@ static bool ufs_mtk_is_tx_skew_fix(struct ufs_hba *hba) return (host->caps & UFS_MTK_CAP_TX_SKEW_FIX); } +static bool ufs_mtk_is_rtff_mtcmos(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + return (host->caps & UFS_MTK_CAP_RTFF_MTCMOS); +} + static bool ufs_mtk_is_allow_vccqx_lpm(struct ufs_hba *hba) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); @@ -653,6 +660,9 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba) if (of_property_read_bool(np, "mediatek,ufs-disable-mcq")) host->caps |= UFS_MTK_CAP_DISABLE_MCQ; + if (of_property_read_bool(np, "mediatek,ufs-rtff-mtcmos")) + host->caps |= UFS_MTK_CAP_RTFF_MTCMOS; + dev_info(hba->dev, "caps: 0x%x", host->caps); } @@ -993,6 +1003,15 @@ static int ufs_mtk_init(struct ufs_hba *hba) * Enable phy clocks specifically here. */ ufs_mtk_mphy_power_on(hba, true); + + if (ufs_mtk_is_rtff_mtcmos(hba)) { + /* First Restore here, to avoid backup unexpected value */ + ufs_mtk_mtcmos_ctrl(false, res); + + /* Power on to init */ + ufs_mtk_mtcmos_ctrl(true, res); + } + ufs_mtk_setup_clocks(hba, true, POST_CHANGE); host->ip_ver = ufshcd_readl(hba, REG_UFS_MTK_IP_VER); @@ -1823,6 +1842,7 @@ static void ufs_mtk_remove(struct platform_device *pdev) static int ufs_mtk_system_suspend(struct device *dev) { struct ufs_hba *hba = dev_get_drvdata(dev); + struct arm_smccc_res res; int ret; ret = ufshcd_system_suspend(dev); @@ -1831,15 +1851,22 @@ static int ufs_mtk_system_suspend(struct device *dev) ufs_mtk_dev_vreg_set_lpm(hba, true); + if (ufs_mtk_is_rtff_mtcmos(hba)) + ufs_mtk_mtcmos_ctrl(false, res); + return 0; } static int ufs_mtk_system_resume(struct device *dev) { struct ufs_hba *hba = dev_get_drvdata(dev); + struct arm_smccc_res res; ufs_mtk_dev_vreg_set_lpm(hba, false); + if (ufs_mtk_is_rtff_mtcmos(hba)) + ufs_mtk_mtcmos_ctrl(true, res); + return ufshcd_system_resume(dev); } #endif @@ -1848,6 +1875,7 @@ static int ufs_mtk_system_resume(struct device *dev) static int ufs_mtk_runtime_suspend(struct device *dev) { struct ufs_hba *hba = dev_get_drvdata(dev); + struct arm_smccc_res res; int ret = 0; ret = ufshcd_runtime_suspend(dev); @@ -1856,12 +1884,19 @@ static int ufs_mtk_runtime_suspend(struct device *dev) ufs_mtk_dev_vreg_set_lpm(hba, true); + if (ufs_mtk_is_rtff_mtcmos(hba)) + ufs_mtk_mtcmos_ctrl(false, res); + return 0; } static int ufs_mtk_runtime_resume(struct device *dev) { struct ufs_hba *hba = dev_get_drvdata(dev); + struct arm_smccc_res res; + + if (ufs_mtk_is_rtff_mtcmos(hba)) + ufs_mtk_mtcmos_ctrl(true, res); ufs_mtk_dev_vreg_set_lpm(hba, false); diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h index eb3744ae3a42..bb314e4fa293 100644 --- a/drivers/ufs/host/ufs-mediatek.h +++ b/drivers/ufs/host/ufs-mediatek.h @@ -132,6 +132,8 @@ enum ufs_mtk_host_caps { UFS_MTK_CAP_PMC_VIA_FASTAUTO = 1 << 6, UFS_MTK_CAP_TX_SKEW_FIX = 1 << 7, UFS_MTK_CAP_DISABLE_MCQ = 1 << 8, + /* Control MTCMOS with RTFF */ + UFS_MTK_CAP_RTFF_MTCMOS = 1 << 9, }; struct ufs_mtk_crypt_cfg { -- 2.18.0
From: Po-Wen Kao <powen.kao@mediatek.com> Mediatek host power include two part: 1. ufshci power, which is the main power of ufs host controller. 2. ufshci crypto sram power, which is the power of ufs crypto engine. This host power control is actually control crypto sram power. Rename it for easy maintain. Acked-by: Chun-Hung Wu <Chun-Hung.Wu@mediatek.com> Reviewed-by: Avri Altman <avri.altman@wdc.com> Reviewed-by: Peter Wang <peter.wang@mediatek.com> Signed-off-by: Peter Wang <peter.wang@mediatek.com> Signed-off-by: Po-Wen Kao <powen.kao@mediatek.com> --- drivers/ufs/host/ufs-mediatek-sip.h | 13 +++---------- drivers/ufs/host/ufs-mediatek.c | 4 ++-- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/ufs/host/ufs-mediatek-sip.h b/drivers/ufs/host/ufs-mediatek-sip.h index 35d1d5e76a2c..c26513aedee3 100755 --- a/drivers/ufs/host/ufs-mediatek-sip.h +++ b/drivers/ufs/host/ufs-mediatek-sip.h @@ -16,7 +16,7 @@ #define UFS_MTK_SIP_DEVICE_RESET BIT(1) #define UFS_MTK_SIP_CRYPTO_CTRL BIT(2) #define UFS_MTK_SIP_REF_CLK_NOTIFICATION BIT(3) -#define UFS_MTK_SIP_HOST_PWR_CTRL BIT(5) +#define UFS_MTK_SIP_SRAM_PWR_CTRL BIT(5) #define UFS_MTK_SIP_GET_VCC_NUM BIT(6) #define UFS_MTK_SIP_DEVICE_PWR_CTRL BIT(7) @@ -31,13 +31,6 @@ enum ufs_mtk_vcc_num { UFS_VCC_MAX }; -/* - * Host Power Control options - */ -enum { - HOST_PWR_HCI = 0, - HOST_PWR_MPHY -}; /* * SMC call wrapper function @@ -78,8 +71,8 @@ static inline void _ufs_mtk_smc(struct ufs_mtk_smc_arg s) #define ufs_mtk_device_reset_ctrl(high, res) \ ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, &(res), high) -#define ufs_mtk_host_pwr_ctrl(opt, on, res) \ - ufs_mtk_smc(UFS_MTK_SIP_HOST_PWR_CTRL, &(res), opt, on) +#define ufs_mtk_sram_pwr_ctrl(on, res) \ + ufs_mtk_smc(UFS_MTK_SIP_SRAM_PWR_CTRL, &(res), on) #define ufs_mtk_get_vcc_num(res) \ ufs_mtk_smc(UFS_MTK_SIP_GET_VCC_NUM, &(res)) diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index bb5b11185d8a..90523652a6fb 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -1376,7 +1376,7 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, if (ufshcd_is_link_off(hba)) ufs_mtk_device_reset_ctrl(0, res); - ufs_mtk_host_pwr_ctrl(HOST_PWR_HCI, false, res); + ufs_mtk_sram_pwr_ctrl(false, res); return 0; fail: @@ -1397,7 +1397,7 @@ static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) ufs_mtk_dev_vreg_set_lpm(hba, false); - ufs_mtk_host_pwr_ctrl(HOST_PWR_HCI, true, res); + ufs_mtk_sram_pwr_ctrl(true, res); err = ufs_mtk_mphy_power_on(hba, true); if (err) -- 2.18.0