scsi: ufs: Add support for sending NOP OUT UPIU
Subsystems (2)
PATCH 1/1 scsi: ufs: Add support for sending NOP OUT UPIU
As part of device initialization sequence, sending NOP OUT UPIU and waiting for NOP IN UPIU response is mandatory. This confirms that the device UFS Transport (UTP) layer is functional and the host can configure the device with further commands. Add support for sending NOP OUT UPIU to check the device connection path and test whether the UTP layer on the device side is functional during initialization.
--- drivers/scsi/ufs/ufshcd.c | 167 ++++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/ufs/ufshcd.h | 4 + 2 files changed, 162 insertions(+), 9 deletions(-)
drivers/scsi/ufs/ufshcd.c +158 -9
@@ -34,12 +34,21 @@*/ #include "ufshcd.h" +#include <linux/iopoll.h> +#include <linux/async.h> /* Timeout after 10 secs if UIC command hangs */ #define UIC_COMMAND_TIMEOUT (10 * HZ)/* Retry for 3 times in case of UIC failures */ #define UIC_COMMAND_RETRIES 3 +/* NOP OUT retries waiting for NOP IN response */ +#define NOP_OUT_RETRIES 10 +/* Timeout after 30 msecs if NOP OUT hangs without response */ +#define NOP_OUT_TIMEOUT 30/* msecs */ +/* Reserved tag for internal commands */ +#define INTERNAL_CMD_TAG 0 +enum {UFSHCD_MAX_CHANNEL =0 ,UFSHCD_MAX_ID =1 ,
@@ -607,7 +616,7 @@ static void ufshcd_prepare_req_desc(struct ufshcd_lrb *lrbp, u32 *upiu_flags) {struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;enum dma_data_direction cmd_dir = - lrbp->cmd->sc_data_direction; + lrbp->cmd ? lrbp->cmd->sc_data_direction :DMA_NONE ;u32 data_direction;u32 dword_0;
@@ -624,6 +633,8 @@ static void ufshcd_prepare_req_desc(struct ufshcd_lrb *lrbp, u32 *upiu_flags) dword_0 = data_direction | (lrbp->command_type <<UPIU_COMMAND_TYPE_OFFSET ); +if (lrbp->intr_cmd) + dword_0 |=UTP_REQ_DESC_INT_CMD ;/* Transfer request descriptor header fields */ req_desc->header.dword_0 =cpu_to_le32 (dword_0);
@@ -712,6 +723,18 @@ static inline void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba, } +static inline void ufshcd_prepare_utp_nop_upiu (struct ufshcd_lrb *lrbp) +{ +struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr; + +memset (ucd_req_ptr,0 ,sizeof (struct utp_upiu_req )); + +/* command descriptor fields */ + ucd_req_ptr->header.dword_0 = +UPIU_HEADER_DWORD ( +UPIU_TRANSACTION_NOP_OUT ,0 ,0 , lrbp->task_tag); +} +/** * ufshcd_compose_upiu - form UFS Protocol Information Unit(UPIU) * @hba - UFS hba
@@ -741,12 +764,14 @@ static int ufshcd_compose_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)case UTP_CMD_TYPE_SCSI :case UTP_CMD_TYPE_DEV_MANAGE :ufshcd_prepare_req_desc (lrbp, &upiu_flags); -if (lrbp->cmd && lrbp->command_type ==UTP_CMD_TYPE_SCSI ) +if (lrbp->cmd && lrbp->command_type ==UTP_CMD_TYPE_SCSI ) {ufshcd_prepare_utp_scsi_cmd_upiu (lrbp, upiu_flags); -else if (lrbp->cmd) + }else if (lrbp->cmd &&ufshcd_is_query_req (lrbp)) {ufshcd_prepare_utp_query_req_upiu (hba, lrbp, upiu_flags); -else { + }else if (!lrbp->cmd) { +ufshcd_prepare_utp_nop_upiu (lrbp); + }else {dev_err (hba->dev,"%s: Invalid UPIU request\n" , __func__); ret = -EINVAL ;
@@ -799,6 +824,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) lrbp->sense_buffer = cmd->sense_buffer; lrbp->task_tag = tag; lrbp->lun = cmd->device->lun; + lrbp->intr_cmd = false;if (ufshcd_is_query_req (lrbp)) lrbp->command_type =UTP_CMD_TYPE_DEV_MANAGE ;
@@ -1112,6 +1138,113 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)return err; } +static inline int +ufshcd_compose_nop_out_upiu (struct ufs_hba *hba,struct ufshcd_lrb *lrbp) +{ + lrbp->cmd =NULL ; + lrbp->sense_bufflen =0 ; + lrbp->sense_buffer =NULL ; + lrbp->task_tag =INTERNAL_CMD_TAG ; + lrbp->lun =0 ;/* NOP OUT is not specific to any LUN */ + lrbp->command_type =UTP_CMD_TYPE_DEV_MANAGE ; + lrbp->intr_cmd = true;/* No interrupt aggregation */ + +return ufshcd_compose_upiu (hba, lrbp); +} + +/** +* ufshcd_validate_dev_connection() - Check device connection status +* @hba: per-adapter instance +* +* Send NOP OUT UPIU and wait for NOP IN response to check whether the +* device Transport Protocol (UTP) layer is ready after a reset. +* If the UTP layer at the device side is not initialized, it may +* not respond with NOP IN UPIU within timeout of %NOP_OUT_TIMEOUT +* and we retry sending NOP OUT for %NOP_OUT_RETRIES iterations. +*/ +static int ufshcd_validate_dev_connection (struct ufs_hba *hba) +{ +int err; +struct ufshcd_lrb *lrbp; +unsigned long timeout; +unsigned long flags; +struct completion wait; +int retries =NOP_OUT_RETRIES ; + +retry: +spin_lock_irqsave (hba->host->host_lock, flags); + lrbp = &hba->lrb[INTERNAL_CMD_TAG ]; +init_completion (&wait); + + err =ufshcd_compose_nop_out_upiu (hba, lrbp); +if (err) + goto may_retry; + + lrbp->completion = &wait; +ufshcd_send_command (hba,INTERNAL_CMD_TAG ); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + timeout =wait_for_completion_timeout ( + &wait,msecs_to_jiffies (NOP_OUT_TIMEOUT )); + +spin_lock_irqsave (hba->host->host_lock, flags); +if (timeout >0 ) { +int ocs; + + ocs =ufshcd_get_tr_ocs (lrbp); +switch (ocs) { +case OCS_SUCCESS : + goto out; +default : +dev_dbg (hba->dev,"%s: OCS error %d\n" , __func__, ocs); + err = -EIO ; + goto may_retry; + } + }else { +u32 reg; + + err = -ETIMEDOUT ; + +/* clear outstanding transaction before retry */ +ufshcd_utrl_clear (hba,INTERNAL_CMD_TAG ); +__clear_bit (INTERNAL_CMD_TAG , &hba->outstanding_reqs); + +/* poll for max. 1 sec to clear door bell register by h/w */ +spin_unlock_irqrestore (hba->host->host_lock, flags); +if (readl_poll_timeout ( + hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL , + reg, !(reg &INTERNAL_CMD_TAG ),1000 ,1000 )) + retries =0 ; +spin_lock_irqsave (hba->host->host_lock, flags); + goto may_retry; + } + +may_retry: +if (retries--) { +dev_dbg (hba->dev,"%s: error %d retrying\n" , __func__, err); +spin_unlock_irqrestore (hba->host->host_lock, flags); + goto retry; + } + +out: +if (err) +dev_err (hba->dev,"%s: NOP OUT failed %d\n" , __func__, err); +spin_unlock_irqrestore (hba->host->host_lock, flags); +return err; +} + +static void ufshcd_async_device_probe (void *data,async_cookie_t cookie) +{ +int err; +struct ufs_hba *hba = data; + + err =ufshcd_validate_dev_connection (hba); +if (err) +dev_err (hba->dev,"%s failed with error %d\n" , __func__, err); +else +scsi_scan_host (hba->host); +} +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance
@@ -1166,7 +1299,6 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)scsi_unblock_requests (hba->host); hba->ufshcd_state =UFSHCD_STATE_OPERATIONAL ; -scsi_scan_host (hba->host); out:return err; }
@@ -1568,6 +1700,16 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) }/** +* ufshcd_is_nop_out_upiu() - check if the command is NOP OUT UPIU +* @lrbp: pointer to logical reference block +*/ +static inline bool ufshcd_is_nop_out_upiu (struct ufshcd_lrb *lrbp) +{ +return (be32_to_cpu (lrbp->ucd_req_ptr->header.dword_0) >>24 ) == +UPIU_TRANSACTION_NOP_OUT ; +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance */
@@ -1578,6 +1720,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)u32 tr_doorbell;int result;int index; +bool int_aggr_reset = true; lrb = hba->lrb; tr_doorbell =
@@ -1586,17 +1729,20 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)for (index =0 ; index < hba->nutrs; index++) {if (test_bit (index, &completed_reqs)) { - - result =ufshcd_transfer_rsp_status (hba, &lrb[index]); -if (lrb[index].cmd) { + result =ufshcd_transfer_rsp_status ( + hba, &lrb[index]);scsi_dma_unmap (lrb[index].cmd); lrb[index].cmd->result = result; lrb[index].cmd->scsi_done (lrb[index].cmd);/* Mark completed command as NULL in LRB */ lrb[index].cmd =NULL ; + }else if (ufshcd_is_nop_out_upiu (&lrb[index])) { +complete (lrb[index].completion); } +/* Don't reset counters for interrupt cmd */ + int_aggr_reset = lrb[index].intr_cmd ? false : true; }/* end of if */ }/* end of for */
@@ -1604,7 +1750,8 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) hba->outstanding_reqs ^= completed_reqs;/* Reset interrupt aggregation counters */ -ufshcd_config_int_aggr (hba,INT_AGGR_RESET ); +if (int_aggr_reset) +ufshcd_config_int_aggr (hba,INT_AGGR_RESET ); }/**
@@ -2098,6 +2245,8 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,dev_err (hba->dev,"Initialization failed\n" ); goto out_remove_scsi_host; } + +async_schedule (ufshcd_async_device_probe, hba); *hba_handle = hba;return 0 ;
drivers/scsi/ufs/ufshcd.h +4 -0
@@ -101,6 +101,8 @@ struct uic_command {* @command_type: SCSI, UFS, Query. * @task_tag: Task tag of the command * @lun: LUN of the command +* @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation) +* @completion: holds the state of completion (used for internal commands) */ struct ufshcd_lrb {struct utp_transfer_req_desc *utr_descriptor_ptr;
@@ -116,6 +118,8 @@ struct ufshcd_lrb {int command_type;int task_tag;unsigned int lun; +bool intr_cmd; +struct completion *completion; };/**
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation.
PATCH 1/5 scsi: ufs: move the ufshcd_hba_stop to ufshcd.c
Move the ufshcd_hba_stop from header file.
--- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-)
drivers/scsi/ufs/ufshcd.c +9 -0
@@ -285,6 +285,15 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) }/** +* ufshcd_hba_stop - Send controller to reset state +* @hba: per adapter instance +*/ +static inline void ufshcd_hba_stop (struct ufs_hba *hba) +{ +writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +} + +/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance *
drivers/scsi/ufs/ufshcd.h +0 -9
@@ -190,13 +190,4 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); -/** -* ufshcd_hba_stop - Send controller to reset state -* @hba: per adapter instance -*/ -static inline void ufshcd_hba_stop (struct ufs_hba *hba) -{ -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); -} -#endif /* End of Header */
Signature · 1 line
1.7.0.4
Re: [PATCH 1/5] scsi: ufs: move the ufshcd_hba_stop to ufshcd.c
Looks good. Reviewed-by: Subhash Jadavani <[email protected]>
Quoted 46 lines · Seungwon Jeon
Move the
ufshcd_hba_stopfrom header file.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-)drivers/scsi/ufs/ufshcd.c +9
-0@@ -285,6 +285,15 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) }/** +* ufshcd_hba_stop - Send controller to reset state +* @hba: per adapter instance +*/ +static inline void ufshcd_hba_stop (struct ufs_hba *hba) +{ +writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +} + +/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance * drivers/scsi/ufs/ufshcd.h +0
-9@@ -190,13 +190,4 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); -/** -* ufshcd_hba_stop - Send controller to reset state -* @hba: per adapter instance -*/ -static inline void ufshcd_hba_stop (struct ufs_hba *hba) -{ -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); -} -#endif /* End of Header */
[email protected]
Tested-byRe: [PATCH 1/5] scsi: ufs: move the ufshcd_hba_stop to ufshcd.c
Quoted 58 lines
Looks good. Reviewed-by: Subhash Jadavani <[email protected]>
Quoted 47 lines · Seungwon Jeon
Move the
ufshcd_hba_stopfrom header file.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-)drivers/scsi/ufs/ufshcd.c +9
-0@@ -285,6 +285,15 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) }/** +* ufshcd_hba_stop - Send controller to reset state +* @hba: per adapter instance +*/ +static inline void ufshcd_hba_stop (struct ufs_hba *hba) +{ +writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +} + +/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance *
drivers/scsi/ufs/ufshcd.h +0
-9@@ -190,13 +190,4 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); -/** -* ufshcd_hba_stop - Send controller to reset state -* @hba: per adapter instance -*/ -static inline void ufshcd_hba_stop (struct ufs_hba *hba) -{ -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); -} -Quoted 1 line
#endif /* End of Header */
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH 1/5] scsi: ufs: move the ufshcd_hba_stop to ufshcd.c
In reply to Seungwon JeonQuoted 47 lines · Seungwon Jeon
Move the
ufshcd_hba_stopfrom header file.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-)drivers/scsi/ufs/ufshcd.c +9
-0@@ -285,6 +285,15 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) }/** +* ufshcd_hba_stop - Send controller to reset state +* @hba: per adapter instance +*/ +static inline void ufshcd_hba_stop (struct ufs_hba *hba) +{ +writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +} + +/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance * drivers/scsi/ufs/ufshcd.h +0
-10@@ -190,13 +190,4 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); -/** -* ufshcd_hba_stop - Send controller to reset state -* @hba: per adapter instance -*/ -static inline void ufshcd_hba_stop (struct ufs_hba *hba) -{ -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); -} -#endif /* End of Header */ --
Quoted 3 lines
1.7.0.4
The patch doesn't apply due to the character set.
"fatal: cannot convert from ks_c_5601-1987 to UTF-8"
Signature · 1 line
~Santosh
RE: [PATCH 1/5] scsi: ufs: move the ufshcd_hba_stop to ufshcd.c
Quoted 54 lines · Santosh Y
Quoted 47 lines · Seungwon Jeon
Move the
ufshcd_hba_stopfrom header file.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-)drivers/scsi/ufs/ufshcd.c +9
-0@@ -285,6 +285,15 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) }/** +* ufshcd_hba_stop - Send controller to reset state +* @hba: per adapter instance +*/ +static inline void ufshcd_hba_stop (struct ufs_hba *hba) +{ +writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +} + +/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance * drivers/scsi/ufs/ufshcd.h +0
-10@@ -190,13 +190,4 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); -/** -* ufshcd_hba_stop - Send controller to reset state -* @hba: per adapter instance -*/ -static inline void ufshcd_hba_stop (struct ufs_hba *hba) -{ -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); -} -#endif /* End of Header */ --Quoted 3 lines
1.7.0.4
The patch doesn't apply due to the character set.
Quoted 1 line
"fatal: cannot convert from ks_c_5601-1987 to UTF-8"
Oh, I didn't see the problem.
I'll check more for resend.
Thanks,
Seungwon Jeon
Quoted 8 lines
--
~Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/5] scsi: ufs: move the ufshcd_hba_stop to ufshcd.c
In reply to Santosh YHi,
Can you please rebase the next version on top of the following patches which are the next candidates for merge?
Vinayak Holikatti (2):
ufs: Add Platform glue driver for ufshcd
ufs: Correct the expected data transfersize
Dolev Raviv (1):
scsi: ufs: add support for query requests
Thanks,
Maya
Quoted 69 lines
Quoted 51 lines · Seungwon Jeon
Move the
ufshcd_hba_stopfrom header file.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-)drivers/scsi/ufs/ufshcd.c +9
-0@@ -285,6 +285,15 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) }/** +* ufshcd_hba_stop - Send controller to reset state +* @hba: per adapter instance +*/ +static inline void ufshcd_hba_stop (struct ufs_hba *hba) +{ +writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +} + +/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance
*drivers/scsi/ufs/ufshcd.h +0
-7@@ -190,13 +190,4 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); -/** -* ufshcd_hba_stop - Send controller to reset state -* @hba: per adapter instance -*/ -static inline void ufshcd_hba_stop (struct ufs_hba *hba) -{ - writel(CONTROLLER_DISABLE, (hba->mmio_base +
REG_CONTROLLER_ENABLE));drivers/scsi/ufs/ufshcd.h +0
-3-} -#endif /* End of Header */ --Quoted 3 lines
1.7.0.4
The patch doesn't apply due to the character set.
"fatal: cannot convert from ks_c_5601-1987 to UTF-8"
--
~Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH v2 1/7 scsi: ufs: move the ufshcd_hba_stop to ufshcd.c
In reply to Seungwon JeonMove the ufshcd_hba_stop from header file.
--- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-)
drivers/scsi/ufs/ufshcd.c +9 -0
@@ -280,6 +280,15 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) }/** +* ufshcd_hba_stop - Send controller to reset state +* @hba: per adapter instance +*/ +static inline void ufshcd_hba_stop (struct ufs_hba *hba) +{ +writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +} + +/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance *
drivers/scsi/ufs/ufshcd.h +0 -9
@@ -208,13 +208,4 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); -/** -* ufshcd_hba_stop - Send controller to reset state -* @hba: per adapter instance -*/ -static inline void ufshcd_hba_stop (struct ufs_hba *hba) -{ -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); -} -#endif /* End of Header */
Signature · 1 line
1.7.0.4
Re: [PATCH v2 1/7] scsi: ufs: move the ufshcd_hba_stop to ufshcd.c
Hi,
ufshcd_pci_shutdown (in ufshcd_pci.c) is using ufshcd_hba_stop so it cannot be moved to ufshcd.c.
Sorry for missing it last time I tested, I returned ufshcd_hba_stop to ufshcd.h by mistake when I resolved conflicts of the next patch so I didn't hit the compilation errors.
Thanks,
Maya
Quoted 59 lines
Move the
ufshcd_hba_stopfrom header file.Signed-off-by Seungwon Jeon <[email protected]>Reviewed-by Subhash Jadavani <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-)drivers/scsi/ufs/ufshcd.c +9
-0@@ -280,6 +280,15 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) }/** +* ufshcd_hba_stop - Send controller to reset state +* @hba: per adapter instance +*/ +static inline void ufshcd_hba_stop (struct ufs_hba *hba) +{ +writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +} + +/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance *
drivers/scsi/ufs/ufshcd.h +0
-9@@ -208,13 +208,4 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); -/** -* ufshcd_hba_stop - Send controller to reset state -* @hba: per adapter instance -*/ -static inline void ufshcd_hba_stop (struct ufs_hba *hba) -{ -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); -} -#endif /* End of Header */
--
1.7.0.4--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
RE: [PATCH v2 1/7] scsi: ufs: move the ufshcd_hba_stop to ufshcd.c
Quoted 7 lines · Merze
Hi,
ufshcd_pci_shutdown(inufshcd_pci.c) is usingufshcd_hba_stopso it cannot be moved toufshcd.c.
Sorry for missing it last time I tested, I returnedufshcd_hba_stoptoufshcd.hby mistake when I resolved conflicts of the next patch so I didn't hit the compilation errors.
Oh, I also missed this. Thank you for informing.
I'll keep ufshcd_hba_stop function in place and
just touch for the patch of "scsi: ufs: wrap the i/o access operations".
Thanks,
Seungwon Jeon
Quoted 73 lines
Thanks,
MayaQuoted 54 lines
Move the
ufshcd_hba_stopfrom header file.Signed-off-by Seungwon Jeon <[email protected]>Reviewed-by Subhash Jadavani <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-)drivers/scsi/ufs/ufshcd.c +9
-0@@ -280,6 +280,15 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) }/** +* ufshcd_hba_stop - Send controller to reset state +* @hba: per adapter instance +*/ +static inline void ufshcd_hba_stop (struct ufs_hba *hba) +{ +writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +} + +/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance *
drivers/scsi/ufs/ufshcd.h +0
-9@@ -208,13 +208,4 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); -/** -* ufshcd_hba_stop - Send controller to reset state -* @hba: per adapter instance -*/ -static inline void ufshcd_hba_stop (struct ufs_hba *hba) -{ -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); -} -#endif /* End of Header */
--
1.7.0.4Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
Maya Erez
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v3 1/6 scsi: ufs: wrap the i/o access operations
In reply to Seungwon JeonSimplify operations with hiding mmio_base.
--- drivers/scsi/ufs/ufshcd.c | 105 +++++++++++++++++++-------------------------- drivers/scsi/ufs/ufshcd.h | 7 +++- 2 files changed, 50 insertions(+), 62 deletions(-)
drivers/scsi/ufs/ufshcd.c +44 -61
@@ -71,7 +71,7 @@ enum {*/ static inline u32 ufshcd_get_ufs_version (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UFS_VERSION ); +return ufshcd_readl (hba,REG_UFS_VERSION ); }/**
@@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(struct ufs_hba *hba)*/ static inline void ufshcd_utrl_clear (struct ufs_hba *hba,u32 pos) { -writel (~(1 << pos), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_CLEAR )); +ufshcd_writel (hba, ~(1 << pos),REG_UTP_TRANSFER_REQ_LIST_CLEAR ); }/**
@@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)*/ static inline int ufshcd_get_uic_cmd_result (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UIC_COMMAND_ARG_2 ) & +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_2 ) &MASK_UIC_COMMAND_RESULT ; }
@@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option) {switch (option) {case INT_AGGR_RESET : -writel ((INT_AGGR_ENABLE | -INT_AGGR_COUNTER_AND_TIMER_RESET ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE | +INT_AGGR_COUNTER_AND_TIMER_RESET , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ;case INT_AGGR_CONFIG : -writel ((INT_AGGR_ENABLE | -INT_AGGR_PARAM_WRITE | -INT_AGGR_COUNTER_THRESHOLD_VALUE | -INT_AGGR_TIMEOUT_VALUE ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE |INT_AGGR_PARAM_WRITE | +INT_AGGR_COUNTER_THRESHOLD_VALUE | +INT_AGGR_TIMEOUT_VALUE , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ; } }
@@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)*/ static void ufshcd_enable_run_stop_reg (struct ufs_hba *hba) { -writel (UTP_TASK_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TASK_REQ_LIST_RUN_STOP )); -writel (UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_LIST_RUN_STOP )); +ufshcd_writel (hba,UTP_TASK_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TASK_REQ_LIST_RUN_STOP ); +ufshcd_writel (hba,UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TRANSFER_REQ_LIST_RUN_STOP ); }/**
@@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)*/ static inline void ufshcd_hba_start (struct ufs_hba *hba) { -writel (CONTROLLER_ENABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_ENABLE ,REG_CONTROLLER_ENABLE ); }/**
@@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)*/ static inline int ufshcd_is_hba_active (struct ufs_hba *hba) { -return (readl (hba->mmio_base +REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; +return (ufshcd_readl (hba,REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; }/**
@@ -299,8 +293,7 @@ static inlinevoid ufshcd_send_command (struct ufs_hba *hba,unsigned int task_tag) {__set_bit (task_tag, &hba->outstanding_reqs); -writel ((1 << task_tag), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << task_tag,REG_UTP_TRANSFER_REQ_DOOR_BELL ); }/**
@@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)*/ static inline void ufshcd_hba_capabilities (struct ufs_hba *hba) { - hba->capabilities = -readl (hba->mmio_base +REG_CONTROLLER_CAPABILITIES ); + hba->capabilities =ufshcd_readl (hba,REG_CONTROLLER_CAPABILITIES );/* nutrs and nutmrs are 0 based values */ hba->nutrs = (hba->capabilities &MASK_TRANSFER_REQUESTS_SLOTS ) +1 ;
@@ -399,16 +391,13 @@ static inline void ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd) {/* Write Args */ - writel(uic_cmnd->argument1, - (hba->mmio_base + REG_UIC_COMMAND_ARG_1)); -writel (uic_cmnd->argument2, - (hba->mmio_base +REG_UIC_COMMAND_ARG_2 )); -writel (uic_cmnd->argument3, - (hba->mmio_base +REG_UIC_COMMAND_ARG_3 )); + ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1); +ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -writel ((uic_cmnd->command &COMMAND_OPCODE_MASK ), - (hba->mmio_base +REG_UIC_COMMAND )); +ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +REG_UIC_COMMAND ); }/**
@@ -460,16 +449,15 @@ static void ufshcd_int_config(struct ufs_hba *hba, u32 option) {switch (option) {case UFSHCD_INT_ENABLE : -writel (hba->int_enable_mask, - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE );break ;case UFSHCD_INT_DISABLE :if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (INTERRUPT_DISABLE_MASK_10 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , +REG_INTERRUPT_ENABLE );else -writel (INTERRUPT_DISABLE_MASK_11 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , +REG_INTERRUPT_ENABLE );break ; } }
@@ -940,7 +928,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)unsigned long flags;/* check if controller is ready to accept UIC commands */ -if (((readl (hba->mmio_base +REG_CONTROLLER_STATUS )) & +if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) ==0x0 ) {dev_err (hba->dev, "Controller not ready"
@@ -985,7 +973,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)u32 reg;/* check if device present */ - reg =readl ((hba->mmio_base +REG_CONTROLLER_STATUS )); + reg =ufshcd_readl (hba,REG_CONTROLLER_STATUS );if (!ufshcd_is_device_present (reg)) {dev_err (hba->dev,"cc: Device not present\n" ); err = -ENXIO ;
@@ -1107,14 +1095,14 @@ static int ufshcd_initialize_hba(struct ufs_hba *hba)return -EIO ;/* Configure UTRL and UTMRL base address registers */ -writel (lower_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_H )); -writel (lower_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_H )); +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H );/* Initialize unipro link startup procedure */ return ufshcd_dme_link_startup (hba);
@@ -1427,8 +1415,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)int index; lrb = hba->lrb; - tr_doorbell = -readl (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL ); + tr_doorbell =ufshcd_readl (hba,REG_UTP_TRANSFER_REQ_DOOR_BELL ); completed_reqs = tr_doorbell ^ hba->outstanding_reqs;for (index =0 ; index < hba->nutrs; index++) {
@@ -1502,9 +1489,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba) goto fatal_eh;if (hba->errors &UIC_ERROR ) { - - reg =readl (hba->mmio_base + -REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER ); + reg =ufshcd_readl (hba,REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER );if (reg &UIC_DATA_LINK_LAYER_ERROR_PA_INIT ) goto fatal_eh; }
@@ -1522,7 +1507,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba) {u32 tm_doorbell; - tm_doorbell =readl (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL ); + tm_doorbell =ufshcd_readl (hba,REG_UTP_TASK_REQ_DOOR_BELL ); hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;wake_up_interruptible (&hba->ufshcd_tm_wait_queue); }
@@ -1563,15 +1548,14 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)struct ufs_hba *hba = __hba;spin_lock (hba->host->host_lock); - intr_status =readl (hba->mmio_base +REG_INTERRUPT_STATUS ); + intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) {ufshcd_sl_intr (hba, intr_status);/* If UFSHCI 1.0 then clear interrupt status register */ if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (intr_status, - (hba->mmio_base +REG_INTERRUPT_STATUS )); +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }spin_unlock (hba->host->host_lock);
@@ -1636,8 +1620,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,/* send command to the controller */ __set_bit (free_slot, &hba->outstanding_tasks); -writel ((1 << free_slot), - (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << free_slot,REG_UTP_TASK_REQ_DOOR_BELL );spin_unlock_irqrestore (host->host_lock, flags);
drivers/scsi/ufs/ufshcd.h +6 -1
@@ -204,6 +204,11 @@ struct ufs_hba {struct ufs_query query; }; +#define ufshcd_writel (hba, val, reg) \ + writel((val), (hba)->mmio_base + (reg)) +#define ufshcd_readl (hba, reg) \ + readl((hba)->mmio_base + (reg)) +int ufshcd_init (struct device *,struct ufs_hba ** ,void __iomem * ,unsigned int );void ufshcd_remove (struct ufs_hba *);
@@ -214,7 +219,7 @@ void ufshcd_remove(struct ufs_hba *);*/ static inline void ufshcd_hba_stop (struct ufs_hba *hba) { -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_DISABLE ,REG_CONTROLLER_ENABLE ); }#endif /* End of Header */
Signature · 1 line
1.7.0.4
Re: [PATCH v3 1/6] scsi: ufs: wrap the i/o access operations
Hi James,
Can you please merge this patch on top of the query requests patch?
Thanks,
Maya
Quoted 313 lines
Simplify operations with hiding
mmio_base.Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 105 +++++++++++++++++++-------------------------- drivers/scsi/ufs/ufshcd.h | 7 +++- 2 files changed, 50 insertions(+), 62 deletions(-)drivers/scsi/ufs/ufshcd.c +2
-3@@ -71,7 +71,7 @@ enum {*/ static inline u32 ufshcd_get_ufs_version (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UFS_VERSION ); +return ufshcd_readl (hba,REG_UFS_VERSION ); }/** @@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(structufs_hba *hba) */ static inline void ufshcd_utrl_clear (struct ufs_hba *hba,u32 pos) { -writel (~(1 << pos), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_CLEAR )); +ufshcd_writel (hba, ~(1 << pos),REG_UTP_TRANSFER_REQ_LIST_CLEAR ); }/**
drivers/scsi/ufs/ufshcd.c +8
-11@@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)*/ static inline int ufshcd_get_uic_cmd_result (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UIC_COMMAND_ARG_2 ) & +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_2 ) &MASK_UIC_COMMAND_RESULT ; }@@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option) {switch (option) {case INT_AGGR_RESET : -writel ((INT_AGGR_ENABLE | -INT_AGGR_COUNTER_AND_TIMER_RESET ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE | +INT_AGGR_COUNTER_AND_TIMER_RESET , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ;case INT_AGGR_CONFIG : -writel ((INT_AGGR_ENABLE | -INT_AGGR_PARAM_WRITE | -INT_AGGR_COUNTER_THRESHOLD_VALUE | -INT_AGGR_TIMEOUT_VALUE ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE |INT_AGGR_PARAM_WRITE | +INT_AGGR_COUNTER_THRESHOLD_VALUE | +INT_AGGR_TIMEOUT_VALUE , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ; }}
drivers/scsi/ufs/ufshcd.c +4
-6@@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, intoption) */ static void ufshcd_enable_run_stop_reg (struct ufs_hba *hba) { -writel (UTP_TASK_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TASK_REQ_LIST_RUN_STOP )); -writel (UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_LIST_RUN_STOP )); +ufshcd_writel (hba,UTP_TASK_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TASK_REQ_LIST_RUN_STOP ); +ufshcd_writel (hba,UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TRANSFER_REQ_LIST_RUN_STOP ); }/**
drivers/scsi/ufs/ufshcd.c +1
-1@@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba*hba) */ static inline void ufshcd_hba_start (struct ufs_hba *hba) { -writel (CONTROLLER_ENABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_ENABLE ,REG_CONTROLLER_ENABLE ); }/**
drivers/scsi/ufs/ufshcd.c +1
-1@@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba*hba) */ static inline int ufshcd_is_hba_active (struct ufs_hba *hba) { -return (readl (hba->mmio_base +REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; +return (ufshcd_readl (hba,REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; }/**
drivers/scsi/ufs/ufshcd.c +2
-4@@ -299,8 +293,7 @@ static inlinevoid ufshcd_send_command (struct ufs_hba *hba,unsigned int task_tag) {__set_bit (task_tag, &hba->outstanding_reqs); -writel ((1 << task_tag), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << task_tag,REG_UTP_TRANSFER_REQ_DOOR_BELL ); }/** @@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba,struct ufshcd_lrb *lrbp) */ static inline void ufshcd_hba_capabilities (struct ufs_hba *hba) { - hba->capabilities = -readl (hba->mmio_base +REG_CONTROLLER_CAPABILITIES ); + hba->capabilities =ufshcd_readl (hba,REG_CONTROLLER_CAPABILITIES );/* nutrs and nutmrs are 0 based values */ drivers/scsi/ufs/ufshcd.c +5
-8hba->nutrs = (hba->capabilities &MASK_TRANSFER_REQUESTS_SLOTS ) +1 ;@@ -399,16 +391,13 @@ static inline void ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd) {/* Write Args */ - writel(uic_cmnd->argument1, - (hba->mmio_base + REG_UIC_COMMAND_ARG_1)); -writel (uic_cmnd->argument2, - (hba->mmio_base +REG_UIC_COMMAND_ARG_2 )); -writel (uic_cmnd->argument3, - (hba->mmio_base +REG_UIC_COMMAND_ARG_3 )); + ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1); +ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -writel ((uic_cmnd->command &COMMAND_OPCODE_MASK ), - (hba->mmio_base +REG_UIC_COMMAND )); +ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +REG_UIC_COMMAND ); }/**
drivers/scsi/ufs/ufshcd.c +5
-6@@ -460,16 +449,15 @@ static void ufshcd_int_config(struct ufs_hba *hba, u32 option) {switch (option) {case UFSHCD_INT_ENABLE : -writel (hba->int_enable_mask, - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE );break ;case UFSHCD_INT_DISABLE :if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (INTERRUPT_DISABLE_MASK_10 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , +REG_INTERRUPT_ENABLE );else -writel (INTERRUPT_DISABLE_MASK_11 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , +REG_INTERRUPT_ENABLE );break ; }}
drivers/scsi/ufs/ufshcd.c +1
-1@@ -940,7 +928,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)unsigned long flags;/* check if controller is ready to accept UIC commands */ -if (((readl (hba->mmio_base +REG_CONTROLLER_STATUS )) & +if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) ==0x0 ) { dev_err(hba->dev,drivers/scsi/ufs/ufshcd.c +1
-1"Controller not ready" @@ -985,7 +973,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)u32 reg;/* check if device present */ - reg =readl ((hba->mmio_base +REG_CONTROLLER_STATUS )); + reg =ufshcd_readl (hba,REG_CONTROLLER_STATUS );if (!ufshcd_is_device_present (reg)) {dev_err (hba->dev,"cc: Device not present\n" );drivers/scsi/ufs/ufshcd.c +8
-8err = -ENXIO ;@@ -1107,14 +1095,14 @@ static int ufshcd_initialize_hba(struct ufs_hba *hba)return -EIO ;/* Configure UTRL and UTMRL base address registers */ -writel (lower_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_H )); -writel (lower_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_H )); +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H );/* Initialize unipro link startup procedure */ drivers/scsi/ufs/ufshcd.c +1
-2return ufshcd_dme_link_startup (hba);@@ -1427,8 +1415,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)int index; lrb = hba->lrb; - tr_doorbell = -readl (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL ); + tr_doorbell =ufshcd_readl (hba,REG_UTP_TRANSFER_REQ_DOOR_BELL ); completed_reqs = tr_doorbell ^ hba->outstanding_reqs;drivers/scsi/ufs/ufshcd.c +4
-7for (index =0 ; index < hba->nutrs; index++) {@@ -1502,9 +1489,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba) goto fatal_eh;if (hba->errors &UIC_ERROR ) { - - reg =readl (hba->mmio_base + -REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER ); + reg =ufshcd_readl (hba,REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER );if (reg &UIC_DATA_LINK_LAYER_ERROR_PA_INIT ) goto fatal_eh; }@@ -1522,7 +1507,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba) {u32 tm_doorbell; - tm_doorbell =readl (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL ); + tm_doorbell =ufshcd_readl (hba,REG_UTP_TASK_REQ_DOOR_BELL ); hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;wake_up_interruptible (&hba->ufshcd_tm_wait_queue); }@@ -1563,15 +1548,14 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)struct ufs_hba *hba = __hba;spin_lock (hba->host->host_lock); - intr_status =readl (hba->mmio_base +REG_INTERRUPT_STATUS ); + intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) {ufshcd_sl_intr (hba, intr_status);/* If UFSHCI 1.0 then clear interrupt status register */ if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (intr_status, - (hba->mmio_base +REG_INTERRUPT_STATUS )); +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }drivers/scsi/ufs/ufshcd.c +1
-2spin_unlock (hba->host->host_lock);@@ -1636,8 +1620,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,/* send command to the controller */ __set_bit (free_slot, &hba->outstanding_tasks); -writel ((1 << free_slot), - (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << free_slot,REG_UTP_TASK_REQ_DOOR_BELL );spin_unlock_irqrestore (host->host_lock, flags);drivers/scsi/ufs/ufshcd.h +6
-2@@ -204,6 +204,11 @@ struct ufs_hba {struct ufs_query query; }; +#define ufshcd_writel (hba, val, reg) \ + writel((val), (hba)->mmio_base + (reg)) +#define ufshcd_readl (hba, reg) \ + readl((hba)->mmio_base + (reg)) +int ufshcd_init (struct device *,struct ufs_hba ** ,void __iomem * ,unsigned int );void ufshcd_remove (struct ufs_hba *);@@ -214,7 +219,7 @@ void ufshcd_remove(struct ufs_hba *);*/ static inline void ufshcd_hba_stop (struct ufs_hba *hba) { -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_DISABLE ,REG_CONTROLLER_ENABLE ); }#endif /* End of Header */ --1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v3 1/6] scsi: ufs: wrap the i/o access operations
In reply to Seungwon JeonQuoted 291 lines · Seungwon Jeon
Simplify operations with hiding
mmio_base.Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 105 +++++++++++++++++++-------------------------- drivers/scsi/ufs/ufshcd.h | 7 +++- 2 files changed, 50 insertions(+), 62 deletions(-)drivers/scsi/ufs/ufshcd.c +44
-61@@ -71,7 +71,7 @@ enum {*/ static inline u32 ufshcd_get_ufs_version (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UFS_VERSION ); +return ufshcd_readl (hba,REG_UFS_VERSION ); }/** @@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(struct ufs_hba *hba)*/ static inline void ufshcd_utrl_clear (struct ufs_hba *hba,u32 pos) { -writel (~(1 << pos), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_CLEAR )); +ufshcd_writel (hba, ~(1 << pos),REG_UTP_TRANSFER_REQ_LIST_CLEAR ); }/** @@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)*/ static inline int ufshcd_get_uic_cmd_result (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UIC_COMMAND_ARG_2 ) & +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_2 ) &MASK_UIC_COMMAND_RESULT ; }@@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option) {switch (option) {case INT_AGGR_RESET : -writel ((INT_AGGR_ENABLE | -INT_AGGR_COUNTER_AND_TIMER_RESET ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE | +INT_AGGR_COUNTER_AND_TIMER_RESET , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ;case INT_AGGR_CONFIG : -writel ((INT_AGGR_ENABLE | -INT_AGGR_PARAM_WRITE | -INT_AGGR_COUNTER_THRESHOLD_VALUE | -INT_AGGR_TIMEOUT_VALUE ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE |INT_AGGR_PARAM_WRITE | +INT_AGGR_COUNTER_THRESHOLD_VALUE | +INT_AGGR_TIMEOUT_VALUE , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ; } }@@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)*/ static void ufshcd_enable_run_stop_reg (struct ufs_hba *hba) { -writel (UTP_TASK_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TASK_REQ_LIST_RUN_STOP )); -writel (UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_LIST_RUN_STOP )); +ufshcd_writel (hba,UTP_TASK_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TASK_REQ_LIST_RUN_STOP ); +ufshcd_writel (hba,UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TRANSFER_REQ_LIST_RUN_STOP ); }/** @@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)*/ static inline void ufshcd_hba_start (struct ufs_hba *hba) { -writel (CONTROLLER_ENABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_ENABLE ,REG_CONTROLLER_ENABLE ); }/** @@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)*/ static inline int ufshcd_is_hba_active (struct ufs_hba *hba) { -return (readl (hba->mmio_base +REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; +return (ufshcd_readl (hba,REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; }/** @@ -299,8 +293,7 @@ static inlinevoid ufshcd_send_command (struct ufs_hba *hba,unsigned int task_tag) {__set_bit (task_tag, &hba->outstanding_reqs); -writel ((1 << task_tag), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << task_tag,REG_UTP_TRANSFER_REQ_DOOR_BELL ); }/** @@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)*/ static inline void ufshcd_hba_capabilities (struct ufs_hba *hba) { - hba->capabilities = -readl (hba->mmio_base +REG_CONTROLLER_CAPABILITIES ); + hba->capabilities =ufshcd_readl (hba,REG_CONTROLLER_CAPABILITIES );/* nutrs and nutmrs are 0 based values */ hba->nutrs = (hba->capabilities &MASK_TRANSFER_REQUESTS_SLOTS ) +1 ;@@ -399,16 +391,13 @@ static inline void ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd) {/* Write Args */ - writel(uic_cmnd->argument1, - (hba->mmio_base + REG_UIC_COMMAND_ARG_1)); -writel (uic_cmnd->argument2, - (hba->mmio_base +REG_UIC_COMMAND_ARG_2 )); -writel (uic_cmnd->argument3, - (hba->mmio_base +REG_UIC_COMMAND_ARG_3 )); + ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1); +ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -writel ((uic_cmnd->command &COMMAND_OPCODE_MASK ), - (hba->mmio_base +REG_UIC_COMMAND )); +ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +REG_UIC_COMMAND ); }/** @@ -460,16 +449,15 @@ static void ufshcd_int_config(struct ufs_hba *hba, u32 option) {switch (option) {case UFSHCD_INT_ENABLE : -writel (hba->int_enable_mask, - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE );break ;case UFSHCD_INT_DISABLE :if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (INTERRUPT_DISABLE_MASK_10 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , +REG_INTERRUPT_ENABLE );else -writel (INTERRUPT_DISABLE_MASK_11 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , +REG_INTERRUPT_ENABLE );break ; } }@@ -940,7 +928,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)unsigned long flags;/* check if controller is ready to accept UIC commands */ -if (((readl (hba->mmio_base +REG_CONTROLLER_STATUS )) & +if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) ==0x0 ) {dev_err (hba->dev, "Controller not ready"@@ -985,7 +973,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)u32 reg;/* check if device present */ - reg =readl ((hba->mmio_base +REG_CONTROLLER_STATUS )); + reg =ufshcd_readl (hba,REG_CONTROLLER_STATUS );if (!ufshcd_is_device_present (reg)) {dev_err (hba->dev,"cc: Device not present\n" ); err = -ENXIO ;@@ -1107,14 +1095,14 @@ static int ufshcd_initialize_hba(struct ufs_hba *hba)return -EIO ;/* Configure UTRL and UTMRL base address registers */ -writel (lower_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_H )); -writel (lower_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_H )); +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H );/* Initialize unipro link startup procedure */ return ufshcd_dme_link_startup (hba);@@ -1427,8 +1415,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)int index; lrb = hba->lrb; - tr_doorbell = -readl (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL ); + tr_doorbell =ufshcd_readl (hba,REG_UTP_TRANSFER_REQ_DOOR_BELL ); completed_reqs = tr_doorbell ^ hba->outstanding_reqs;for (index =0 ; index < hba->nutrs; index++) {@@ -1502,9 +1489,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba) goto fatal_eh;if (hba->errors &UIC_ERROR ) { - - reg =readl (hba->mmio_base + -REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER ); + reg =ufshcd_readl (hba,REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER );if (reg &UIC_DATA_LINK_LAYER_ERROR_PA_INIT ) goto fatal_eh; }@@ -1522,7 +1507,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba) {u32 tm_doorbell; - tm_doorbell =readl (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL ); + tm_doorbell =ufshcd_readl (hba,REG_UTP_TASK_REQ_DOOR_BELL ); hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;wake_up_interruptible (&hba->ufshcd_tm_wait_queue); }@@ -1563,15 +1548,14 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)struct ufs_hba *hba = __hba;spin_lock (hba->host->host_lock); - intr_status =readl (hba->mmio_base +REG_INTERRUPT_STATUS ); + intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) {ufshcd_sl_intr (hba, intr_status);/* If UFSHCI 1.0 then clear interrupt status register */ if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (intr_status, - (hba->mmio_base +REG_INTERRUPT_STATUS )); +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }spin_unlock (hba->host->host_lock);@@ -1636,8 +1620,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,/* send command to the controller */ __set_bit (free_slot, &hba->outstanding_tasks); -writel ((1 << free_slot), - (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << free_slot,REG_UTP_TASK_REQ_DOOR_BELL );spin_unlock_irqrestore (host->host_lock, flags);drivers/scsi/ufs/ufshcd.h +6
-2@@ -204,6 +204,11 @@ struct ufs_hba {struct ufs_query query; }; +#define ufshcd_writel (hba, val, reg) \ + writel((val), (hba)->mmio_base + (reg)) +#define ufshcd_readl (hba, reg) \ + readl((hba)->mmio_base + (reg)) +int ufshcd_init (struct device *,struct ufs_hba ** ,void __iomem * ,unsigned int );void ufshcd_remove (struct ufs_hba *);@@ -214,7 +219,7 @@ void ufshcd_remove(struct ufs_hba *);*/ static inline void ufshcd_hba_stop (struct ufs_hba *hba) { -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_DISABLE ,REG_CONTROLLER_ENABLE ); }#endif /* End of Header */ --
Quoted 2 lines
1.7.0.4
Still git throws the same error "fatal: cannot convert from ks_c_5601-1987 to UTF-8". Please check it for all the patches.
Signature · 1 line
~Santosh
RE: [PATCH v3 1/6] scsi: ufs: wrap the i/o access operations
Quoted 290 lines · Santosh Y
Quoted 289 lines · Seungwon Jeon
Simplify operations with hiding
mmio_base.Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 105 +++++++++++++++++++-------------------------- drivers/scsi/ufs/ufshcd.h | 7 +++- 2 files changed, 50 insertions(+), 62 deletions(-)drivers/scsi/ufs/ufshcd.c +44
-61@@ -71,7 +71,7 @@ enum {*/ static inline u32 ufshcd_get_ufs_version (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UFS_VERSION ); +return ufshcd_readl (hba,REG_UFS_VERSION ); }/** @@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(struct ufs_hba *hba)*/ static inline void ufshcd_utrl_clear (struct ufs_hba *hba,u32 pos) { -writel (~(1 << pos), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_CLEAR )); +ufshcd_writel (hba, ~(1 << pos),REG_UTP_TRANSFER_REQ_LIST_CLEAR ); }/** @@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)*/ static inline int ufshcd_get_uic_cmd_result (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UIC_COMMAND_ARG_2 ) & +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_2 ) &MASK_UIC_COMMAND_RESULT ; }@@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option) {switch (option) {case INT_AGGR_RESET : -writel ((INT_AGGR_ENABLE | -INT_AGGR_COUNTER_AND_TIMER_RESET ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE | +INT_AGGR_COUNTER_AND_TIMER_RESET , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ;case INT_AGGR_CONFIG : -writel ((INT_AGGR_ENABLE | -INT_AGGR_PARAM_WRITE | -INT_AGGR_COUNTER_THRESHOLD_VALUE | -INT_AGGR_TIMEOUT_VALUE ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE |INT_AGGR_PARAM_WRITE | +INT_AGGR_COUNTER_THRESHOLD_VALUE | +INT_AGGR_TIMEOUT_VALUE , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ; } }@@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)*/ static void ufshcd_enable_run_stop_reg (struct ufs_hba *hba) { -writel (UTP_TASK_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TASK_REQ_LIST_RUN_STOP )); -writel (UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_LIST_RUN_STOP )); +ufshcd_writel (hba,UTP_TASK_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TASK_REQ_LIST_RUN_STOP ); +ufshcd_writel (hba,UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TRANSFER_REQ_LIST_RUN_STOP ); }/** @@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)*/ static inline void ufshcd_hba_start (struct ufs_hba *hba) { -writel (CONTROLLER_ENABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_ENABLE ,REG_CONTROLLER_ENABLE ); }/** @@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)*/ static inline int ufshcd_is_hba_active (struct ufs_hba *hba) { -return (readl (hba->mmio_base +REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; +return (ufshcd_readl (hba,REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; }/** @@ -299,8 +293,7 @@ static inlinevoid ufshcd_send_command (struct ufs_hba *hba,unsigned int task_tag) {__set_bit (task_tag, &hba->outstanding_reqs); -writel ((1 << task_tag), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << task_tag,REG_UTP_TRANSFER_REQ_DOOR_BELL ); }/** @@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)*/ static inline void ufshcd_hba_capabilities (struct ufs_hba *hba) { - hba->capabilities = -readl (hba->mmio_base +REG_CONTROLLER_CAPABILITIES ); + hba->capabilities =ufshcd_readl (hba,REG_CONTROLLER_CAPABILITIES );/* nutrs and nutmrs are 0 based values */ hba->nutrs = (hba->capabilities &MASK_TRANSFER_REQUESTS_SLOTS ) +1 ;@@ -399,16 +391,13 @@ static inline void ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd) {/* Write Args */ - writel(uic_cmnd->argument1, - (hba->mmio_base + REG_UIC_COMMAND_ARG_1)); -writel (uic_cmnd->argument2, - (hba->mmio_base +REG_UIC_COMMAND_ARG_2 )); -writel (uic_cmnd->argument3, - (hba->mmio_base +REG_UIC_COMMAND_ARG_3 )); + ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1); +ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -writel ((uic_cmnd->command &COMMAND_OPCODE_MASK ), - (hba->mmio_base +REG_UIC_COMMAND )); +ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +REG_UIC_COMMAND ); }/** @@ -460,16 +449,15 @@ static void ufshcd_int_config(struct ufs_hba *hba, u32 option) {switch (option) {case UFSHCD_INT_ENABLE : -writel (hba->int_enable_mask, - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE );break ;case UFSHCD_INT_DISABLE :if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (INTERRUPT_DISABLE_MASK_10 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , +REG_INTERRUPT_ENABLE );else -writel (INTERRUPT_DISABLE_MASK_11 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , +REG_INTERRUPT_ENABLE );break ; } }@@ -940,7 +928,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)unsigned long flags;/* check if controller is ready to accept UIC commands */ -if (((readl (hba->mmio_base +REG_CONTROLLER_STATUS )) & +if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) ==0x0 ) {dev_err (hba->dev, "Controller not ready"@@ -985,7 +973,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)u32 reg;/* check if device present */ - reg =readl ((hba->mmio_base +REG_CONTROLLER_STATUS )); + reg =ufshcd_readl (hba,REG_CONTROLLER_STATUS );if (!ufshcd_is_device_present (reg)) {dev_err (hba->dev,"cc: Device not present\n" ); err = -ENXIO ;@@ -1107,14 +1095,14 @@ static int ufshcd_initialize_hba(struct ufs_hba *hba)return -EIO ;/* Configure UTRL and UTMRL base address registers */ -writel (lower_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_H )); -writel (lower_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_H )); +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H );/* Initialize unipro link startup procedure */ return ufshcd_dme_link_startup (hba);@@ -1427,8 +1415,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)int index; lrb = hba->lrb; - tr_doorbell = -readl (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL ); + tr_doorbell =ufshcd_readl (hba,REG_UTP_TRANSFER_REQ_DOOR_BELL ); completed_reqs = tr_doorbell ^ hba->outstanding_reqs;for (index =0 ; index < hba->nutrs; index++) {@@ -1502,9 +1489,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba) goto fatal_eh;if (hba->errors &UIC_ERROR ) { - - reg =readl (hba->mmio_base + -REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER ); + reg =ufshcd_readl (hba,REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER );if (reg &UIC_DATA_LINK_LAYER_ERROR_PA_INIT ) goto fatal_eh; }@@ -1522,7 +1507,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba) {u32 tm_doorbell; - tm_doorbell =readl (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL ); + tm_doorbell =ufshcd_readl (hba,REG_UTP_TASK_REQ_DOOR_BELL ); hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;wake_up_interruptible (&hba->ufshcd_tm_wait_queue); }@@ -1563,15 +1548,14 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)struct ufs_hba *hba = __hba;spin_lock (hba->host->host_lock); - intr_status =readl (hba->mmio_base +REG_INTERRUPT_STATUS ); + intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) {ufshcd_sl_intr (hba, intr_status);/* If UFSHCI 1.0 then clear interrupt status register */ if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (intr_status, - (hba->mmio_base +REG_INTERRUPT_STATUS )); +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }spin_unlock (hba->host->host_lock);@@ -1636,8 +1620,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,/* send command to the controller */ __set_bit (free_slot, &hba->outstanding_tasks); -writel ((1 << free_slot), - (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << free_slot,REG_UTP_TASK_REQ_DOOR_BELL );spin_unlock_irqrestore (host->host_lock, flags);drivers/scsi/ufs/ufshcd.h +6
-1@@ -204,6 +204,11 @@ struct ufs_hba {struct ufs_query query; }; +#define ufshcd_writel (hba, val, reg) \ + writel((val), (hba)->mmio_base + (reg)) +#define ufshcd_readl (hba, reg) \ + readl((hba)->mmio_base + (reg)) +int ufshcd_init (struct device *,struct ufs_hba ** ,void __iomem * ,unsigned int );void ufshcd_remove (struct ufs_hba *);@@ -214,7 +219,7 @@ void ufshcd_remove(struct ufs_hba *);*/ static inline void ufshcd_hba_stop (struct ufs_hba *hba) { -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_DISABLE ,REG_CONTROLLER_ENABLE ); }
Quoted 7 lines
Quoted 4 lines
drivers/scsi/ufs/ufshcd.h +0
-1#endif /* End of Header */ --1.7.0.4
Still git throws the same error "fatal: cannot convert from ks_c_5601-1987 to UTF-8". Please check it for all the patches.
Um...
Ok. Let me send test one for you, first.
Thanks,
Seungwon Jeon
Quoted 7 lines
--
~Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v3 2/6 scsi: ufs: amend interrupt configuration
In reply to Seungwon JeonIt makes interrupt setting more flexible especially for disabling. And wrong bit mask is fixed for ver 1.0. [17:16] is added for mask.
--- drivers/scsi/ufs/ufshcd.c | 84 +++++++++++++++++++++++++++++++------------- drivers/scsi/ufs/ufshcd.h | 4 +- drivers/scsi/ufs/ufshci.h | 5 ++- 3 files changed, 64 insertions(+), 29 deletions(-)
drivers/scsi/ufs/ufshcd.c +59 -25
@@ -35,6 +35,10 @@#include "ufshcd.h" +#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ + UTP_TASK_REQ_COMPL |\ + UFSHCD_ERROR_MASK) +enum {UFSHCD_MAX_CHANNEL =0 ,UFSHCD_MAX_ID =1 ,
@@ -64,6 +68,20 @@ enum { };/** +* ufshcd_get_intr_mask - Get the interrupt bit mask +* @hba - Pointer to adapter instance +* +* Returns interrupt bit mask per version +*/ +static inline u32 ufshcd_get_intr_mask (struct ufs_hba *hba) +{ +if (hba->ufs_version ==UFSHCI_VERSION_10 ) +return INTERRUPT_MASK_ALL_VER_10 ; +else +return INTERRUPT_MASK_ALL_VER_11 ; +} + +/** * ufshcd_get_ufs_version - Get the UFS version supported by the HBA * @hba - Pointer to adapter instance *
@@ -441,25 +459,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp) }/** -* ufshcd_int_config - enable/disable interrupts +* ufshcd_enable_intr - enable interrupts * @hba: per adapter instance -* @option: interrupt option +* @intrs: interrupt bits */ -static void ufshcd_int_config (struct ufs_hba *hba,u32 option) +static void ufshcd_enable_intr (struct ufs_hba *hba,u32 intrs) { -switch (option) { -case UFSHCD_INT_ENABLE : -ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE ); -break ; -case UFSHCD_INT_DISABLE : -if (hba->ufs_version ==UFSHCI_VERSION_10 ) -ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , -REG_INTERRUPT_ENABLE ); -else -ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , -REG_INTERRUPT_ENABLE ); -break ; +u32 set =ufshcd_readl (hba,REG_INTERRUPT_ENABLE ); + +if (hba->ufs_version ==UFSHCI_VERSION_10 ) { +u32 rw; + rw = set &INTERRUPT_MASK_RW_VER_10 ; + set = rw | ((set ^ intrs) & intrs); + }else { + set |= intrs; + } + +ufshcd_writel (hba, set,REG_INTERRUPT_ENABLE ); +} + +/** +* ufshcd_disable_intr - disable interrupts +* @hba: per adapter instance +* @intrs: interrupt bits +*/ +static void ufshcd_disable_intr (struct ufs_hba *hba,u32 intrs) +{ +u32 set =ufshcd_readl (hba,REG_INTERRUPT_ENABLE ); + +if (hba->ufs_version ==UFSHCI_VERSION_10 ) { +u32 rw; + rw = (set &INTERRUPT_MASK_RW_VER_10 ) & + ~(intrs &INTERRUPT_MASK_RW_VER_10 ); + set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10 ); + + }else { + set &= ~intrs; } + +ufshcd_writel (hba, set,REG_INTERRUPT_ENABLE ); }/**
@@ -946,8 +984,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) uic_cmd->argument3 =0 ;/* enable UIC related interrupts */ - hba->int_enable_mask |=UIC_COMMAND_COMPL ; -ufshcd_int_config (hba,UFSHCD_INT_ENABLE ); +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL );/* sending UIC commands to controller */ ufshcd_send_uic_command (hba, uic_cmd);
@@ -994,13 +1031,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) }/* Enable required interrupts */ - hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL | -UIC_ERROR | -UTP_TASK_REQ_COMPL | -DEVICE_FATAL_ERROR | -CONTROLLER_FATAL_ERROR | -SYSTEM_BUS_FATAL_ERROR ); -ufshcd_int_config (hba,UFSHCD_INT_ENABLE ); +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS );/* Configure interrupt aggregation */ ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG );
@@ -1828,7 +1859,7 @@ static void ufshcd_hba_free(struct ufs_hba *hba)void ufshcd_remove (struct ufs_hba *hba) {/* disable interrupts */ -ufshcd_int_config (hba,UFSHCD_INT_DISABLE ); +ufshcd_disable_intr (hba, hba->intr_mask);ufshcd_hba_stop (hba);ufshcd_hba_free (hba);
@@ -1886,6 +1917,9 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,/* Get UFS version supported by the controller */ hba->ufs_version =ufshcd_get_ufs_version (hba); +/* Get Interrupt bit mask per version */ + hba->intr_mask =ufshcd_get_intr_mask (hba); +/* Allocate memory for host memory space */ err =ufshcd_memory_alloc (hba);if (err) {
drivers/scsi/ufs/ufshcd.h +2 -2
@@ -153,7 +153,7 @@ struct ufs_query {* @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states -* @int_enable_mask: Interrupt Mask Bits +* @intr_mask: Interrupt Mask Bits * @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors
@@ -191,7 +191,7 @@ struct ufs_hba {unsigned long tm_condition;u32 ufshcd_state; -u32 int_enable_mask; +u32 intr_mask;/* Work Queues */ struct work_struct uic_workq;
drivers/scsi/ufs/ufshci.h +3 -2
@@ -232,10 +232,11 @@ enum {/* Interrupt disable masks */ enum {/* Interrupt disable mask for UFSHCI v1.0 */ -INTERRUPT_DISABLE_MASK_10 =0xFFFF , +INTERRUPT_MASK_ALL_VER_10 =0x30FFF , +INTERRUPT_MASK_RW_VER_10 =0x30000 ,/* Interrupt disable mask for UFSHCI v1.1 */ -INTERRUPT_DISABLE_MASK_11 =0x0 , +INTERRUPT_MASK_ALL_VER_11 =0x31FFF , };/*
Signature · 1 line
1.7.0.4
Re: [PATCH v3 2/6] scsi: ufs: amend interrupt configuration
Hi James,
Can you please merge this patch?
Thanks,
Maya
Quoted 206 lines
It makes interrupt setting more flexible especially for disabling. And wrong bit mask is fixed for ver 1.0. [17:16] is added for mask.
Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 84 +++++++++++++++++++++++++++++++------------- drivers/scsi/ufs/ufshcd.h | 4 +- drivers/scsi/ufs/ufshci.h | 5 ++- 3 files changed, 64 insertions(+), 29 deletions(-)drivers/scsi/ufs/ufshcd.c +54
-17@@ -35,6 +35,10 @@#include "ufshcd.h" +#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ + UTP_TASK_REQ_COMPL |\ + UFSHCD_ERROR_MASK) +enum {UFSHCD_MAX_CHANNEL =0 ,UFSHCD_MAX_ID =1 ,@@ -64,6 +68,20 @@ enum { };/** +* ufshcd_get_intr_mask - Get the interrupt bit mask +* @hba - Pointer to adapter instance +* +* Returns interrupt bit mask per version +*/ +static inline u32 ufshcd_get_intr_mask (struct ufs_hba *hba) +{ +if (hba->ufs_version ==UFSHCI_VERSION_10 ) +return INTERRUPT_MASK_ALL_VER_10 ; +else +return INTERRUPT_MASK_ALL_VER_11 ; +} + +/** * ufshcd_get_ufs_version - Get the UFS version supported by the HBA * @hba - Pointer to adapter instance * @@ -441,25 +459,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp) }/** -* ufshcd_int_config - enable/disable interrupts +* ufshcd_enable_intr - enable interrupts * @hba: per adapter instance -* @option: interrupt option +* @intrs: interrupt bits */ -static void ufshcd_int_config (struct ufs_hba *hba,u32 option) +static void ufshcd_enable_intr (struct ufs_hba *hba,u32 intrs) { -switch (option) { -case UFSHCD_INT_ENABLE : -ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE ); -break ; -case UFSHCD_INT_DISABLE : -if (hba->ufs_version ==UFSHCI_VERSION_10 ) -ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , -REG_INTERRUPT_ENABLE ); -else -ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , -REG_INTERRUPT_ENABLE ); -break ; +u32 set =ufshcd_readl (hba,REG_INTERRUPT_ENABLE ); + +if (hba->ufs_version ==UFSHCI_VERSION_10 ) { +u32 rw; + rw = set &INTERRUPT_MASK_RW_VER_10 ; + set = rw | ((set ^ intrs) & intrs); + }else { + set |= intrs; + } + +ufshcd_writel (hba, set,REG_INTERRUPT_ENABLE ); +} + +/** +* ufshcd_disable_intr - disable interrupts +* @hba: per adapter instance +* @intrs: interrupt bits +*/ +static void ufshcd_disable_intr (struct ufs_hba *hba,u32 intrs) +{ +u32 set =ufshcd_readl (hba,REG_INTERRUPT_ENABLE ); + +if (hba->ufs_version ==UFSHCI_VERSION_10 ) { +u32 rw; + rw = (set &INTERRUPT_MASK_RW_VER_10 ) & + ~(intrs &INTERRUPT_MASK_RW_VER_10 ); + set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10 ); + + }else { + set &= ~intrs; } + +ufshcd_writel (hba, set,REG_INTERRUPT_ENABLE ); }/** @@ -946,8 +984,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) uic_cmd->argument3 =0 ;/* enable UIC related interrupts */ - hba->int_enable_mask |=UIC_COMMAND_COMPL ; -ufshcd_int_config (hba,UFSHCD_INT_ENABLE ); +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL );/* sending UIC commands to controller */ drivers/scsi/ufs/ufshcd.c +1
-7ufshcd_send_uic_command (hba, uic_cmd);@@ -994,13 +1031,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) }/* Enable required interrupts */ - hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL | -UIC_ERROR | -UTP_TASK_REQ_COMPL | -DEVICE_FATAL_ERROR | -CONTROLLER_FATAL_ERROR | -SYSTEM_BUS_FATAL_ERROR ); -ufshcd_int_config (hba,UFSHCD_INT_ENABLE ); +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS );/* Configure interrupt aggregation */ drivers/scsi/ufs/ufshcd.c +4
-1ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG );@@ -1828,7 +1859,7 @@ static void ufshcd_hba_free(struct ufs_hba *hba)void ufshcd_remove (struct ufs_hba *hba) {/* disable interrupts */ -ufshcd_int_config (hba,UFSHCD_INT_DISABLE ); +ufshcd_disable_intr (hba, hba->intr_mask);ufshcd_hba_stop (hba);ufshcd_hba_free (hba);@@ -1886,6 +1917,9 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,/* Get UFS version supported by the controller */ hba->ufs_version =ufshcd_get_ufs_version (hba); +/* Get Interrupt bit mask per version */ + hba->intr_mask =ufshcd_get_intr_mask (hba); +/* Allocate memory for host memory space */ err =ufshcd_memory_alloc (hba);drivers/scsi/ufs/ufshcd.c +0
-0if (err) {drivers/scsi/ufs/ufshcd.h +2
-2@@ -153,7 +153,7 @@ struct ufs_query {* @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states -* @int_enable_mask: Interrupt Mask Bits +* @intr_mask: Interrupt Mask Bits * @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors @@ -191,7 +191,7 @@ struct ufs_hba {unsigned long tm_condition;u32 ufshcd_state; -u32 int_enable_mask; +u32 intr_mask;/* Work Queues */ struct work_struct uic_workq;drivers/scsi/ufs/ufshci.h +3
-3@@ -232,10 +232,11 @@ enum {/* Interrupt disable masks */ enum {/* Interrupt disable mask for UFSHCI v1.0 */ -INTERRUPT_DISABLE_MASK_10 =0xFFFF , +INTERRUPT_MASK_ALL_VER_10 =0x30FFF , +INTERRUPT_MASK_RW_VER_10 =0x30000 ,/* Interrupt disable mask for UFSHCI v1.1 */ -INTERRUPT_DISABLE_MASK_11 =0x0 , +INTERRUPT_MASK_ALL_VER_11 =0x31FFF , };/* -- 1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH v3 3/6 scsi: ufs: fix interrupt status clears
In reply to Seungwon JeonThere is no need to check the version to clear
the interrupt status. And the order is changed
prior to actual handling.
--- drivers/scsi/ufs/ufshcd.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-)
drivers/scsi/ufs/ufshcd.c +1 -4
@@ -1582,11 +1582,8 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba) intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) { +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS );ufshcd_sl_intr (hba, intr_status); - -/* If UFSHCI 1.0 then clear interrupt status register */ -if (hba->ufs_version ==UFSHCI_VERSION_10 ) -ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }spin_unlock (hba->host->host_lock);
Signature · 1 line
1.7.0.4
Re: [PATCH v3 3/6] scsi: ufs: fix interrupt status clears
Quoted 36 lines
There is no need to check the version to clear
the interrupt status. And the order is changed
prior to actual handling.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-)drivers/scsi/ufs/ufshcd.c +1
-4@@ -1582,11 +1582,8 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba) intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) { +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS );ufshcd_sl_intr (hba, intr_status); - -/* If UFSHCI 1.0 then clear interrupt status register */ -if (hba->ufs_version ==UFSHCI_VERSION_10 ) -ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }
spin_unlock(hba->host->host_lock);
--
1.7.0.4--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH v3 4/6 scsi: ufs: rework link start-up process
In reply to Seungwon JeonLink start-up requires long time with multiphase handshakes between UFS host and device. This affects driver's probe time. This patch let link start-up run asynchronously. Link start-up will be executed at the end of prove separately. Along with this change, the following is worked.
Defined completion time of uic command to avoid a permanent wait. Added mutex to guarantee of uic command at a time. Adapted some sequence of controller initialization after link statup according to HCI standard.
--- drivers/scsi/ufs/ufshcd.c | 287 ++++++++++++++++++++++++++++++--------------- drivers/scsi/ufs/ufshcd.h | 10 +- 2 files changed, 200 insertions(+), 97 deletions(-)
drivers/scsi/ufs/ufshcd.c +193 -94
@@ -33,11 +33,15 @@* this program. */ +#include <linux/async.h> +#include "ufshcd.h" #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) +/* UIC command timeout, unit: ms */ +#define UIC_CMD_TIMEOUT 500enum {UFSHCD_MAX_CHANNEL =0 ,
@@ -401,24 +405,115 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) }/** -* ufshcd_send_uic_command - Send UIC commands to unipro layers +* ufshcd_ready_for_uic_cmd - Check if controller is ready +* to accept UIC commands * @hba: per adapter instance -* @uic_command: UIC command +* Return true on success, else false +*/ +static inline bool ufshcd_ready_for_uic_cmd (struct ufs_hba *hba) +{ +if (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) +return true; +else +return false; +} + +/** +* ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Mutex must be held. */ static inline void -ufshcd_send_uic_command (struct ufs_hba *hba,struct uic_command *uic_cmnd) +ufshcd_dispatch_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) { + hba->active_uic_cmd = uic_cmd; +/* Write Args */ -ufshcd_writel (hba, uic_cmnd->argument1,REG_UIC_COMMAND_ARG_1 ); -ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); -ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 ); +ufshcd_writel (hba, uic_cmd->argument1,REG_UIC_COMMAND_ARG_1 ); +ufshcd_writel (hba, uic_cmd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +ufshcd_writel (hba, uic_cmd->command &COMMAND_OPCODE_MASK ,REG_UIC_COMMAND ); }/** +* ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command +* @hba: per adapter instance +* @uic_command: UIC command +* +* Must be called with mutex held. +* Returns 0 only if success. +*/ +static int +ufshcd_wait_for_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +if (wait_for_completion_timeout (&uic_cmd->done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) + ret = uic_cmd->argument2 &MASK_UIC_COMMAND_RESULT ; +else + ret = -ETIMEDOUT ; + +return ret; +} + +/** +* __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Identical to ufshcd_send_uic_cmd() expect mutex. Must be called +* with mutex held. +* Returns 0 only if success. +*/ +static int +__ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; +unsigned long flags; + +if (!ufshcd_ready_for_uic_cmd (hba)) { +dev_err (hba->dev, +"Controller not ready to accept UIC commands\n" ); +return -EIO ; + } + +init_completion (&uic_cmd->done); + +spin_lock_irqsave (hba->host->host_lock, flags); +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba, uic_cmd); + +return ret; +} + +/** +* ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Returns 0 only if success. +*/ +static int +ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, uic_cmd); +mutex_unlock (&hba->uic_cmd_mutex); + +return ret; +} + +/** * ufshcd_map_sg - Map scatter-gather list to prdt * @lrbp - pointer to local reference block *
@@ -962,34 +1057,16 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)*/ static int ufshcd_dme_link_startup (struct ufs_hba *hba) { -struct uic_command *uic_cmd; -unsigned long flags; +struct uic_command uic_cmd = {0 }; +int ret; -/* check if controller is ready to accept UIC commands */ -if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) & -UIC_COMMAND_READY ) ==0x0 ) { -dev_err (hba->dev, -"Controller not ready" -" to accept UIC commands\n" ); -return -EIO ; - } - -spin_lock_irqsave (hba->host->host_lock, flags); + uic_cmd.command =UIC_CMD_DME_LINK_STARTUP ; -/* form UIC command */ - uic_cmd = &hba->active_uic_cmd; - uic_cmd->command =UIC_CMD_DME_LINK_STARTUP ; - uic_cmd->argument1 =0 ; - uic_cmd->argument2 =0 ; - uic_cmd->argument3 =0 ; - -/* enable UIC related interrupts */ -ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); - -/* sending UIC commands to controller */ -ufshcd_send_uic_command (hba, uic_cmd); -spin_unlock_irqrestore (hba->host->host_lock, flags); -return 0 ; + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev, +"link startup: error code %d\n" , ret); +return ret; }/**
@@ -998,9 +1075,10 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)* * To bring UFS host controller to operational state, * 1. Check if device is present -* 2. Configure run-stop-registers -* 3. Enable required interrupts -* 4. Configure interrupt aggregation +* 2. Enable required interrupts +* 3. Configure interrupt aggregation +* 4. Program UTRL and UTMRL base addres +* 5. Configure run-stop-registers * * Returns 0 on success, non-zero value on failure */
@@ -1017,6 +1095,22 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } +/* Enable required interrupts */ +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); + +/* Configure interrupt aggregation */ +ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); + +/* Configure UTRL and UTMRL base address registers */ +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H ); +/* * UCRDY, UTMRLDY and UTRLRDY bits must be 1 * DEI, HEI bits must be 0
@@ -1030,17 +1124,11 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } -/* Enable required interrupts */ -ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); - -/* Configure interrupt aggregation */ -ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); -if (hba->ufshcd_state ==UFSHCD_STATE_RESET )scsi_unblock_requests (hba->host); hba->ufshcd_state =UFSHCD_STATE_OPERATIONAL ; -scsi_scan_host (hba->host); + out:return err; }
@@ -1109,34 +1197,29 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) }/** -* ufshcd_initialize_hba - start the initialization process +* ufshcd_link_startup - Initialize unipro link startup * @hba: per adapter instance * -* 1. Enable the controller via ufshcd_hba_enable. -* 2. Program the Transfer Request List Address with the starting address of -* UTRDL. -* 3. Program the Task Management Request List Address with starting address -* of UTMRDL. -* -* Returns 0 on success, non-zero value on failure. +* Returns 0 for success, non-zero in case of failure */ -static int ufshcd_initialize_hba (struct ufs_hba *hba) +static int ufshcd_link_startup (struct ufs_hba *hba) { -if (ufshcd_hba_enable (hba)) -return -EIO ; +int ret; -/* Configure UTRL and UTMRL base address registers */ -ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_H ); -ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_H ); +/* enable UIC related interrupts */ +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); + + ret =ufshcd_dme_link_startup (hba); +if (ret) + goto out; -/* Initialize unipro link startup procedure */ -return ufshcd_dme_link_startup (hba); + ret =ufshcd_make_hba_operational (hba); +if (ret) + goto out; + +out: +dev_err (hba->dev,"link startup failed %d\n" , ret); +return ret; }/**
@@ -1176,12 +1259,19 @@ static int ufshcd_do_reset(struct ufs_hba *hba) hba->outstanding_reqs =0 ; hba->outstanding_tasks =0 ; -/* start the initialization process */ -if (ufshcd_initialize_hba (hba)) { +/* Host controller enable */ +if (ufshcd_hba_enable (hba)) {dev_err (hba->dev,"Reset: Controller initialization failed\n" );return FAILED ; } + +if (ufshcd_link_startup (hba)) { +dev_err (hba->dev, +"Reset: Link start-up failed\n" ); +return FAILED ; + } +return SUCCESS ; }
@@ -1434,6 +1524,17 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) }/** +* ufshcd_uic_cmd_compl - handle completion of uic command +* @hba: per adapter instance +*/ +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +{ + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); +complete (&hba->active_uic_cmd->done); +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance */
@@ -1473,28 +1574,6 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) }/** -* ufshcd_uic_cc_handler - handle UIC command completion -* @work: pointer to a work queue structure -* -* Returns 0 on success, non-zero value on failure -*/ -static void ufshcd_uic_cc_handler (struct work_struct *work) -{ -struct ufs_hba *hba; - - hba = container_of(work, struct ufs_hba, uic_workq); - -if ((hba->active_uic_cmd.command ==UIC_CMD_DME_LINK_STARTUP ) && - !(ufshcd_get_uic_cmd_result (hba))) { - -if (ufshcd_make_hba_operational (hba)) -dev_err (hba->dev, -"cc: hba not operational state\n" ); -return ; - } -} - -/** * ufshcd_fatal_err_handler - handle fatal errors * @hba: per adapter instance */
@@ -1555,7 +1634,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)ufshcd_err_handler (hba);if (intr_status &UIC_COMMAND_COMPL ) -schedule_work (&hba->uic_workq); +ufshcd_uic_cmd_compl (hba);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);
@@ -1778,6 +1857,21 @@ out:return err; } +/** +* ufshcd_async_scan - asynchronous execution for link startup +* @data: data pointer to pass to this function +* @cookie: cookie data +*/ +static void ufshcd_async_scan (void *data,async_cookie_t cookie) +{ +struct ufs_hba *hba = (struct ufs_hba *)data; +int ret; + + ret =ufshcd_link_startup (hba); +if (!ret) +scsi_scan_host (hba->host); +} +static struct scsi_host_template ufshcd_driver_template = { .module =THIS_MODULE , .name =UFSHCD ,
@@ -1939,12 +2033,14 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,init_waitqueue_head (&hba->ufshcd_tm_wait_queue);/* Initialize work queues */ -INIT_WORK (&hba->uic_workq, ufshcd_uic_cc_handler);INIT_WORK (&hba->feh_workq, ufshcd_fatal_err_handler);/* Initialize mutex for query requests */ mutex_init (&hba->query.lock_ufs_query); +/* Initialize UIC command mutex */ +mutex_init (&hba->uic_cmd_mutex); +/* IRQ registration */ err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {
@@ -1965,14 +2061,17 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, goto out_free_irq; } -/* Initialization routine */ - err =ufshcd_initialize_hba (hba); +/* Host controller enable */ + err =ufshcd_hba_enable (hba);if (err) { -dev_err (hba->dev,"Initialization failed\n" ); +dev_err (hba->dev,"Host controller enable failed\n" ); goto out_remove_scsi_host; } + *hba_handle = hba; +async_schedule (ufshcd_async_scan, hba); +return 0 ; out_remove_scsi_host:
drivers/scsi/ufs/ufshcd.h +7 -3
@@ -51,6 +51,7 @@#include <linux/bitops.h> #include <linux/pm_runtime.h> #include <linux/clk.h> +#include <linux/completion.h> #include <asm/irq.h> #include <asm/byteorder.h>
@@ -76,6 +77,7 @@* @argument3: UIC command argument 3 * @cmd_active: Indicate if UIC command is outstanding * @result: UIC command result +* @done: UIC command completion */ struct uic_command {u32 command;
@@ -84,6 +86,7 @@ struct uic_command {u32 argument3;int cmd_active;int result; +struct completion done; };/**
@@ -150,11 +153,11 @@ struct ufs_query {* @ufs_version: UFS Version to which controller complies * @irq: Irq number of the controller * @active_uic_cmd: handle of active UIC command +* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits -* @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors * @query: query request information
@@ -186,7 +189,9 @@ struct ufs_hba {u32 ufs_version;unsigned int irq; -struct uic_command active_uic_cmd; +struct uic_command *active_uic_cmd; +struct mutex uic_cmd_mutex; +wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition;
@@ -194,7 +199,6 @@ struct ufs_hba {u32 intr_mask;/* Work Queues */ -struct work_struct uic_workq;struct work_struct feh_workq;/* HBA Errors */
Signature · 1 line
1.7.0.4
Re: [PATCH v3 4/6] scsi: ufs: rework link start-up process
Quoted 7 lines · Seungwon Jeon
Link start-up requires long time with multiphase handshakes between UFS host and device. This affects driver's probe time. This patch let link start-up run asynchronously. Link start-up will be executed at the end of prove separately. Along with this change, the following is worked.
Defined completion time of uic command to avoid a permanent wait.
We have seen a kernel crash when the timeout happens in our internal testing. This is basically because the the UIC_CMD_TIMEOUT of 500msec is less for our platform. We see UIC_COMMAND_COMPL interrupt after this timeout and since uic_cmd is freed we see a kernel crash.
[ 6.026094] ufshcd 0000:01:00.0: link startup: error code -110 [ 6.030886] ufshcd 0000:01:00.0: link startup failed -110
...
[ 6.487288] BUG: spinlock bad magic on CPU#0, swapper/0/0 [ 6.491683] Unable to handle kernel paging request at virtual address 6000012b ... [ 7.625270] [<c07c3718>] (spin_dump+0x4c/0x88) from [<c02ab9d8>] (do_raw_spin_lock+0x20/0x154) [ 7.633877] [<c02ab9d8>] (do_raw_spin_lock+0x20/0x154) from [<c07ccba4>] (_raw_spin_lock_irqsave+0x28/0x30) [ 7.643583] [<c07ccba4>] (_raw_spin_lock_irqsave+0x28/0x30) from [<c00a3c98>] (complete+0x1c/0x58) [ 7.652525] [<c00a3c98>] (complete+0x1c/0x58) from [<c03d10c4>] (ufshcd_intr+0x1a8/0x498) [ 7.660705] [<c03d10c4>] (ufshcd_intr+0x1a8/0x498) from [<c00cff48>] (handle_irq_event_percpu+0xb0/0x290) [ 7.670227] [<c00cff48>] (handle_irq_event_percpu+0xb0/0x290) from [<c00d0164>] (handle_irq_event+0x3c/0x5c) [ 7.680054] [<c00d0164>] (handle_irq_event+0x3c/0x5c) from [<c00d2c50>] (handle_fasteoi_irq+0xdc/0x148) [ 7.689424] [<c00d2c50>] (handle_fasteoi_irq+0xdc/0x148) from [<c00cf7ac>] (generic_handle_irq+0x30/0x44) [ 7.698977] [<c00cf7ac>] (generic_handle_irq+0x30/0x44) from [<c000ee40>] (handle_IRQ+0x7c/0xc0) [ 7.707736] [<c000ee40>] (handle_IRQ+0x7c/0xc0) from [<c0008620>] (gic_handle_irq+0x94/0x110) [ 7.716252] [<c0008620>] (gic_handle_irq+0x94/0x110) from
[<c07ccec0>] (__irq_svc+0x40/0x70)
Following would fix this. Please check. Also, we need to increase the timeout to say 5 secs to avoid such races.
drivers/scsi/ufs/ufshcd.c +1 -0
@@ -485,6 +485,7 @@ static int ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) { int ret; +unsigned long flags;if (wait_for_completion_timeout (&uic_cmd->done,msecs_to_jiffies (UIC_CMD_TIMEOUT )))
@@ -492,6 +493,10 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct
uic_command *uic_cmd)
else
ret = -ETIMEDOUT;
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->active_uic_cmd = NULL;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
return ret;
}
@@ -1842,7 +1847,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
*/
static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) {
- if (intr_status & UIC_COMMAND_COMPL) {
+ if (hba->active_uic_cmd && (intr_status & UIC_COMMAND_COMPL)) {
hba->active_uic_cmd->argument2 |=
ufshcd_get_uic_cmd_result(hba);
hba->active_uic_cmd->argument3 =
Quoted 503 lines
Added mutex to guarantee of uic command at a time. Adapted some sequence of controller initialization after link statup according to HCI standard.
Signed-off-by Seungwon Jeon <[email protected]>Signed-off-by Sujit Reddy Thumma <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 287 ++++++++++++++++++++++++++++++--------------- drivers/scsi/ufs/ufshcd.h | 10 +- 2 files changed, 200 insertions(+), 97 deletions(-)drivers/scsi/ufs/ufshcd.c +193
-94@@ -33,11 +33,15 @@* this program. */ +#include <linux/async.h> +#include "ufshcd.h" #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) +/* UIC command timeout, unit: ms */ +#define UIC_CMD_TIMEOUT 500enum {UFSHCD_MAX_CHANNEL =0 ,@@ -401,24 +405,115 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) }/** -* ufshcd_send_uic_command - Send UIC commands to unipro layers +* ufshcd_ready_for_uic_cmd - Check if controller is ready +* to accept UIC commands * @hba: per adapter instance -* @uic_command: UIC command +* Return true on success, else false +*/ +static inline bool ufshcd_ready_for_uic_cmd (struct ufs_hba *hba) +{ +if (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) +return true; +else +return false; +} + +/** +* ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Mutex must be held. */ static inline void -ufshcd_send_uic_command (struct ufs_hba *hba,struct uic_command *uic_cmnd) +ufshcd_dispatch_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) { + hba->active_uic_cmd = uic_cmd; +/* Write Args */ -ufshcd_writel (hba, uic_cmnd->argument1,REG_UIC_COMMAND_ARG_1 ); -ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); -ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 ); +ufshcd_writel (hba, uic_cmd->argument1,REG_UIC_COMMAND_ARG_1 ); +ufshcd_writel (hba, uic_cmd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +ufshcd_writel (hba, uic_cmd->command &COMMAND_OPCODE_MASK ,REG_UIC_COMMAND ); }/** +* ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command +* @hba: per adapter instance +* @uic_command: UIC command +* +* Must be called with mutex held. +* Returns 0 only if success. +*/ +static int +ufshcd_wait_for_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +if (wait_for_completion_timeout (&uic_cmd->done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) + ret = uic_cmd->argument2 &MASK_UIC_COMMAND_RESULT ; +else + ret = -ETIMEDOUT ; + +return ret; +} + +/** +* __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Identical to ufshcd_send_uic_cmd() expect mutex. Must be called +* with mutex held. +* Returns 0 only if success. +*/ +static int +__ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; +unsigned long flags; + +if (!ufshcd_ready_for_uic_cmd (hba)) { +dev_err (hba->dev, +"Controller not ready to accept UIC commands\n" ); +return -EIO ; + } + +init_completion (&uic_cmd->done); + +spin_lock_irqsave (hba->host->host_lock, flags); +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba, uic_cmd); + +return ret; +} + +/** +* ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Returns 0 only if success. +*/ +static int +ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, uic_cmd); +mutex_unlock (&hba->uic_cmd_mutex); + +return ret; +} + +/** * ufshcd_map_sg - Map scatter-gather list to prdt * @lrbp - pointer to local reference block * @@ -962,34 +1057,16 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)*/ static int ufshcd_dme_link_startup (struct ufs_hba *hba) { -struct uic_command *uic_cmd; -unsigned long flags; +struct uic_command uic_cmd = {0 }; +int ret; -/* check if controller is ready to accept UIC commands */ -if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) & -UIC_COMMAND_READY ) ==0x0 ) { -dev_err (hba->dev, -"Controller not ready" -" to accept UIC commands\n" ); -return -EIO ; - } - -spin_lock_irqsave (hba->host->host_lock, flags); + uic_cmd.command =UIC_CMD_DME_LINK_STARTUP ; -/* form UIC command */ - uic_cmd = &hba->active_uic_cmd; - uic_cmd->command =UIC_CMD_DME_LINK_STARTUP ; - uic_cmd->argument1 =0 ; - uic_cmd->argument2 =0 ; - uic_cmd->argument3 =0 ; - -/* enable UIC related interrupts */ -ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); - -/* sending UIC commands to controller */ -ufshcd_send_uic_command (hba, uic_cmd); -spin_unlock_irqrestore (hba->host->host_lock, flags); -return 0 ; + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev, +"link startup: error code %d\n" , ret); +return ret; }/** @@ -998,9 +1075,10 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)* * To bring UFS host controller to operational state, * 1. Check if device is present -* 2. Configure run-stop-registers -* 3. Enable required interrupts -* 4. Configure interrupt aggregation +* 2. Enable required interrupts +* 3. Configure interrupt aggregation +* 4. Program UTRL and UTMRL base addres +* 5. Configure run-stop-registers * * Returns 0 on success, non-zero value on failure */ @@ -1017,6 +1095,22 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } +/* Enable required interrupts */ +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); + +/* Configure interrupt aggregation */ +ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); + +/* Configure UTRL and UTMRL base address registers */ +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H ); +/* * UCRDY, UTMRLDY and UTRLRDY bits must be 1 * DEI, HEI bits must be 0 @@ -1030,17 +1124,11 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } -/* Enable required interrupts */ -ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); - -/* Configure interrupt aggregation */ -ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); -if (hba->ufshcd_state ==UFSHCD_STATE_RESET )scsi_unblock_requests (hba->host); hba->ufshcd_state =UFSHCD_STATE_OPERATIONAL ; -scsi_scan_host (hba->host); + out:return err; }@@ -1109,34 +1197,29 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) }/** -* ufshcd_initialize_hba - start the initialization process +* ufshcd_link_startup - Initialize unipro link startup * @hba: per adapter instance * -* 1. Enable the controller via ufshcd_hba_enable. -* 2. Program the Transfer Request List Address with the starting address of -* UTRDL. -* 3. Program the Task Management Request List Address with starting address -* of UTMRDL. -* -* Returns 0 on success, non-zero value on failure. +* Returns 0 for success, non-zero in case of failure */ -static int ufshcd_initialize_hba (struct ufs_hba *hba) +static int ufshcd_link_startup (struct ufs_hba *hba) { -if (ufshcd_hba_enable (hba)) -return -EIO ; +int ret; -/* Configure UTRL and UTMRL base address registers */ -ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_H ); -ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_H ); +/* enable UIC related interrupts */ +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); + + ret =ufshcd_dme_link_startup (hba); +if (ret) + goto out; -/* Initialize unipro link startup procedure */ -return ufshcd_dme_link_startup (hba); + ret =ufshcd_make_hba_operational (hba); +if (ret) + goto out; + +out: +dev_err (hba->dev,"link startup failed %d\n" , ret); +return ret; }/** @@ -1176,12 +1259,19 @@ static int ufshcd_do_reset(struct ufs_hba *hba) hba->outstanding_reqs =0 ; hba->outstanding_tasks =0 ; -/* start the initialization process */ -if (ufshcd_initialize_hba (hba)) { +/* Host controller enable */ +if (ufshcd_hba_enable (hba)) {dev_err (hba->dev,"Reset: Controller initialization failed\n" );return FAILED ; } + +if (ufshcd_link_startup (hba)) { +dev_err (hba->dev, +"Reset: Link start-up failed\n" ); +return FAILED ; + } +return SUCCESS ; }@@ -1434,6 +1524,17 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) }/** +* ufshcd_uic_cmd_compl - handle completion of uic command +* @hba: per adapter instance +*/ +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +{ + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); +complete (&hba->active_uic_cmd->done); +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance */ @@ -1473,28 +1574,6 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) }/** -* ufshcd_uic_cc_handler - handle UIC command completion -* @work: pointer to a work queue structure -* -* Returns 0 on success, non-zero value on failure -*/ -static void ufshcd_uic_cc_handler (struct work_struct *work) -{ -struct ufs_hba *hba; - - hba = container_of(work, struct ufs_hba, uic_workq); - -if ((hba->active_uic_cmd.command ==UIC_CMD_DME_LINK_STARTUP ) && - !(ufshcd_get_uic_cmd_result (hba))) { - -if (ufshcd_make_hba_operational (hba)) -dev_err (hba->dev, -"cc: hba not operational state\n" ); -return ; - } -} - -/** * ufshcd_fatal_err_handler - handle fatal errors * @hba: per adapter instance */ @@ -1555,7 +1634,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)ufshcd_err_handler (hba);if (intr_status &UIC_COMMAND_COMPL ) -schedule_work (&hba->uic_workq); +ufshcd_uic_cmd_compl (hba);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);@@ -1778,6 +1857,21 @@ out:return err; } +/** +* ufshcd_async_scan - asynchronous execution for link startup +* @data: data pointer to pass to this function +* @cookie: cookie data +*/ +static void ufshcd_async_scan (void *data,async_cookie_t cookie) +{ +struct ufs_hba *hba = (struct ufs_hba *)data; +int ret; + + ret =ufshcd_link_startup (hba); +if (!ret) +scsi_scan_host (hba->host); +} +static struct scsi_host_template ufshcd_driver_template = { .module =THIS_MODULE , .name =UFSHCD ,@@ -1939,12 +2033,14 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,init_waitqueue_head (&hba->ufshcd_tm_wait_queue);/* Initialize work queues */ -INIT_WORK (&hba->uic_workq, ufshcd_uic_cc_handler);INIT_WORK (&hba->feh_workq, ufshcd_fatal_err_handler);/* Initialize mutex for query requests */ mutex_init (&hba->query.lock_ufs_query); +/* Initialize UIC command mutex */ +mutex_init (&hba->uic_cmd_mutex); +/* IRQ registration */ err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {@@ -1965,14 +2061,17 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, goto out_free_irq; } -/* Initialization routine */ - err =ufshcd_initialize_hba (hba); +/* Host controller enable */ + err =ufshcd_hba_enable (hba);if (err) { -dev_err (hba->dev,"Initialization failed\n" ); +dev_err (hba->dev,"Host controller enable failed\n" ); goto out_remove_scsi_host; } + *hba_handle = hba; +async_schedule (ufshcd_async_scan, hba); +return 0 ; out_remove_scsi_host:drivers/scsi/ufs/ufshcd.h +7
-3@@ -51,6 +51,7 @@#include <linux/bitops.h> #include <linux/pm_runtime.h> #include <linux/clk.h> +#include <linux/completion.h> #include <asm/irq.h> #include <asm/byteorder.h> @@ -76,6 +77,7 @@* @argument3: UIC command argument 3 * @cmd_active: Indicate if UIC command is outstanding * @result: UIC command result +* @done: UIC command completion */ struct uic_command {u32 command;@@ -84,6 +86,7 @@ struct uic_command {u32 argument3;int cmd_active;int result; +struct completion done; };/** @@ -150,11 +153,11 @@ struct ufs_query {* @ufs_version: UFS Version to which controller complies * @irq: Irq number of the controller * @active_uic_cmd: handle of active UIC command +* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits -* @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors * @query: query request information @@ -186,7 +189,9 @@ struct ufs_hba {u32 ufs_version;unsigned int irq; -struct uic_command active_uic_cmd; +struct uic_command *active_uic_cmd; +struct mutex uic_cmd_mutex; +wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition;@@ -194,7 +199,6 @@ struct ufs_hba {u32 intr_mask;/* Work Queues */ -struct work_struct uic_workq;struct work_struct feh_workq;/* HBA Errors */
Signature · 2 lines
Regards, Sujit
Re: [PATCH v3 4/6] scsi: ufs: rework link start-up process
Hi,
The proposed fix fixes the timeout crash.
In normal operation the patch works, so after applying the fix you can add my Tested-By.
One additional minor fix that is required:
In ufshcd_link_startup the following print-out is printed in success as well:dev_err(hba->dev, "link startup failed %d\n", ret);
Please move it to the error cases only.
Thanks,
Maya
Quoted 614 lines · Seungwon Jeon
Quoted 7 lines
Link start-up requires long time with multiphase handshakes between UFS host and device. This affects driver's probe time. This patch let link start-up run asynchronously. Link start-up will be executed at the end of prove separately. Along with this change, the following is worked.
Defined completion time of uic command to avoid a permanent wait.
We have seen a kernel crash when the timeout happens in our internal testing. This is basically because the the
UIC_CMD_TIMEOUTof 500msec is less for our platform. We seeUIC_COMMAND_COMPLinterrupt after this timeout and sinceuic_cmdis freed we see a kernel crash.[ 6.026094] ufshcd 0000:01:00.0: link startup: error code -110 [ 6.030886] ufshcd 0000:01:00.0: link startup failed -110...
[ 6.487288] BUG: spinlock bad magic on CPU#0, swapper/0/0 [ 6.491683] Unable to handle kernel paging request at virtual address 6000012b ... [ 7.625270] [<c07c3718>] (spin_dump+0x4c/0x88) from [<c02ab9d8>] (do_raw_spin_lock+0x20/0x154) [ 7.633877] [<c02ab9d8>] (do_raw_spin_lock+0x20/0x154) from [<c07ccba4>] (_raw_spin_lock_irqsave+0x28/0x30) [ 7.643583] [<c07ccba4>] (_raw_spin_lock_irqsave+0x28/0x30) from [<c00a3c98>] (complete+0x1c/0x58) [ 7.652525] [<c00a3c98>] (complete+0x1c/0x58) from [<c03d10c4>] (ufshcd_intr+0x1a8/0x498) [ 7.660705] [<c03d10c4>] (ufshcd_intr+0x1a8/0x498) from [<c00cff48>] (handle_irq_event_percpu+0xb0/0x290) [ 7.670227] [<c00cff48>] (handle_irq_event_percpu+0xb0/0x290) from [<c00d0164>] (handle_irq_event+0x3c/0x5c) [ 7.680054] [<c00d0164>] (handle_irq_event+0x3c/0x5c) from [<c00d2c50>] (handle_fasteoi_irq+0xdc/0x148) [ 7.689424] [<c00d2c50>] (handle_fasteoi_irq+0xdc/0x148) from [<c00cf7ac>] (generic_handle_irq+0x30/0x44) [ 7.698977] [<c00cf7ac>] (generic_handle_irq+0x30/0x44) from [<c000ee40>] (handle_IRQ+0x7c/0xc0) [ 7.707736] [<c000ee40>] (handle_IRQ+0x7c/0xc0) from [<c0008620>] (gic_handle_irq+0x94/0x110) [ 7.716252] [<c0008620>] (gic_handle_irq+0x94/0x110) from[<
c07ccec0>] (__irq_svc+0x40/0x70)Following would fix this. Please check. Also, we need to increase the timeout to say 5 secs to avoid such races.
drivers/scsi/ufs/ufshcd.c +6
-1@@ -485,6 +485,7 @@ static int ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) { int ret; +unsigned long flags;if (wait_for_completion_timeout (&uic_cmd->done,msecs_to_jiffies (UIC_CMD_TIMEOUT )))@@ -492,6 +493,10 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) else ret = -ETIMEDOUT ; +spin_lock_irqsave (hba->host->host_lock, flags); + hba->active_uic_cmd =NULL ; +spin_unlock_irqrestore (hba->host->host_lock, flags); +return ret; }@@ -1842,7 +1847,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,struct ufshcd_lrb *lrbp) */ static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { -if (intr_status &UIC_COMMAND_COMPL ) { +if (hba->active_uic_cmd && (intr_status &UIC_COMMAND_COMPL )) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba);
hba->active_uic_cmd->argument3=Quoted 514 lines
Added mutex to guarantee of uic command at a time. Adapted some sequence of controller initialization after link statup according to HCI standard.
Signed-off-by Seungwon Jeon <[email protected]>Signed-off-by Sujit Reddy Thumma <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 287 ++++++++++++++++++++++++++++++--------------- drivers/scsi/ufs/ufshcd.h | 10 +- 2 files changed, 200 insertions(+), 97 deletions(-)drivers/scsi/ufs/ufshcd.c +38
-7@@ -33,11 +33,15 @@* this program. */ +#include <linux/async.h> +#include "ufshcd.h" #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) +/* UIC command timeout, unit: ms */ +#define UIC_CMD_TIMEOUT 500enum {UFSHCD_MAX_CHANNEL =0 ,@@ -401,24 +405,115 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) }/** -* ufshcd_send_uic_command - Send UIC commands to unipro layers +* ufshcd_ready_for_uic_cmd - Check if controller is ready +* to accept UIC commands * @hba: per adapter instance -* @uic_command: UIC command +* Return true on success, else false +*/ +static inline bool ufshcd_ready_for_uic_cmd (struct ufs_hba *hba) +{ +if (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) +return true; +else +return false; +} + +/** +* ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Mutex must be held. */ static inline void -ufshcd_send_uic_command (struct ufs_hba *hba,struct uic_command *uic_cmnd) +ufshcd_dispatch_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) { + hba->active_uic_cmd = uic_cmd; +/* Write Args */ -ufshcd_writel (hba, uic_cmnd->argument1,REG_UIC_COMMAND_ARG_1 ); -ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); -ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 ); +ufshcd_writel (hba, uic_cmd->argument1,REG_UIC_COMMAND_ARG_1 ); +ufshcd_writel (hba, uic_cmd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +ufshcd_writel (hba, uic_cmd->command &COMMAND_OPCODE_MASK ,REG_UIC_COMMAND ); }/** +* ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command +* @hba: per adapter instance +* @uic_command: UIC command +* +* Must be called with mutex held. +* Returns 0 only if success. +*/ +static int +ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command
*uic_cmd)drivers/scsi/ufs/ufshcd.c +72
-26+{ +int ret; + +if (wait_for_completion_timeout (&uic_cmd->done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) + ret = uic_cmd->argument2 &MASK_UIC_COMMAND_RESULT ; +else + ret = -ETIMEDOUT ; + +return ret; +} + +/** +* __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Identical to ufshcd_send_uic_cmd() expect mutex. Must be called +* with mutex held. +* Returns 0 only if success. +*/ +static int +__ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; +unsigned long flags; + +if (!ufshcd_ready_for_uic_cmd (hba)) { +dev_err (hba->dev, +"Controller not ready to accept UIC commands\n" ); +return -EIO ; + } + +init_completion (&uic_cmd->done); + +spin_lock_irqsave (hba->host->host_lock, flags); +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba, uic_cmd); + +return ret; +} + +/** +* ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Returns 0 only if success. +*/ +static int +ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, uic_cmd); +mutex_unlock (&hba->uic_cmd_mutex); + +return ret; +} + +/** * ufshcd_map_sg - Map scatter-gather list to prdt * @lrbp - pointer to local reference block * @@ -962,34 +1057,16 @@ static void ufshcd_host_memory_configure(structufs_hba *hba) */ static int ufshcd_dme_link_startup (struct ufs_hba *hba) { -struct uic_command *uic_cmd; -unsigned long flags; +struct uic_command uic_cmd = {0 }; +int ret; -/* check if controller is ready to accept UIC commands */ -if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) & -UIC_COMMAND_READY ) ==0x0 ) { -dev_err (hba->dev, -"Controller not ready" -" to accept UIC commands\n" ); -return -EIO ; - } - -spin_lock_irqsave (hba->host->host_lock, flags); + uic_cmd.command =UIC_CMD_DME_LINK_STARTUP ; -/* form UIC command */ - uic_cmd = &hba->active_uic_cmd; - uic_cmd->command =UIC_CMD_DME_LINK_STARTUP ; - uic_cmd->argument1 =0 ; - uic_cmd->argument2 =0 ; - uic_cmd->argument3 =0 ; - -/* enable UIC related interrupts */ -ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); - -/* sending UIC commands to controller */ -ufshcd_send_uic_command (hba, uic_cmd); -spin_unlock_irqrestore (hba->host->host_lock, flags); -return 0 ; + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev, +"link startup: error code %d\n" , ret); +return ret; }/**
drivers/scsi/ufs/ufshcd.c +4
-3@@ -998,9 +1075,10 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) * * To bring UFS host controller to operational state, * 1. Check if device is present - * 2. Configure run-stop-registers - * 3. Enable required interrupts - * 4. Configure interrupt aggregation + * 2. Enable required interrupts + * 3. Configure interrupt aggregation + * 4. Program UTRL and UTMRL base addres + * 5. Configure run-stop-registers * * Returns 0 on success, non-zero value on failure*/drivers/scsi/ufs/ufshcd.c +16
-0@@ -1017,6 +1095,22 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } +/* Enable required interrupts */ +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); + +/* Configure interrupt aggregation */ +ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); + +/* Configure UTRL and UTMRL base address registers */ +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H ); +/* * UCRDY, UTMRLDY and UTRLRDY bits must be 1 * DEI, HEI bits must be 0
drivers/scsi/ufs/ufshcd.c +1
-7@@ -1030,17 +1124,11 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } -/* Enable required interrupts */ -ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); - -/* Configure interrupt aggregation */ -ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); -if (hba->ufshcd_state ==UFSHCD_STATE_RESET )scsi_unblock_requests (hba->host); hba->ufshcd_state =UFSHCD_STATE_OPERATIONAL ; -scsi_scan_host (hba->host); + out:return err;}drivers/scsi/ufs/ufshcd.c +1
-3@@ -1109,34 +1197,29 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) }/** -* ufshcd_initialize_hba - start the initialization process +* ufshcd_link_startup - Initialize unipro link startup * @hba: per adapter instance * -* 1. Enable the controller via ufshcd_hba_enable. -* 2. Program the Transfer Request List Address with the starting address of
- * UTRDL.
- * 3. Program the Task Management Request List Address with starting address
- * of UTMRDL.
- *
- * Returns 0 on success, non-zero value on failure.
+ * Returns 0 for success, non-zero in case of failure
*/drivers/scsi/ufs/ufshcd.c +35
-16-static int ufshcd_initialize_hba (struct ufs_hba *hba) +static int ufshcd_link_startup (struct ufs_hba *hba) { -if (ufshcd_hba_enable (hba)) -return -EIO ; +int ret; -/* Configure UTRL and UTMRL base address registers */ -ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_H ); -ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_H ); +/* enable UIC related interrupts */ +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); + + ret =ufshcd_dme_link_startup (hba); +if (ret) + goto out; -/* Initialize unipro link startup procedure */ -return ufshcd_dme_link_startup (hba); + ret =ufshcd_make_hba_operational (hba); +if (ret) + goto out; + +out: +dev_err (hba->dev,"link startup failed %d\n" , ret); +return ret; }/** @@ -1176,12 +1259,19 @@ static int ufshcd_do_reset(struct ufs_hba *hba) hba->outstanding_reqs =0 ; hba->outstanding_tasks =0 ; -/* start the initialization process */ -if (ufshcd_initialize_hba (hba)) { +/* Host controller enable */ +if (ufshcd_hba_enable (hba)) {dev_err (hba->dev,"Reset: Controller initialization failed\n" );return FAILED ; } + +if (ufshcd_link_startup (hba)) { +dev_err (hba->dev, +"Reset: Link start-up failed\n" ); +return FAILED ; + } +return SUCCESS ; }@@ -1434,6 +1524,17 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) }/** +* ufshcd_uic_cmd_compl - handle completion of uic command +* @hba: per adapter instance +*/ +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +{ + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); +complete (&hba->active_uic_cmd->done); +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion
* @hba: per adapter instance
*/drivers/scsi/ufs/ufshcd.c +0
-22@@ -1473,28 +1574,6 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) }/** -* ufshcd_uic_cc_handler - handle UIC command completion -* @work: pointer to a work queue structure -* -* Returns 0 on success, non-zero value on failure -*/ -static void ufshcd_uic_cc_handler (struct work_struct *work) -{ -struct ufs_hba *hba; - - hba = container_of(work, struct ufs_hba, uic_workq); - -if ((hba->active_uic_cmd.command ==UIC_CMD_DME_LINK_STARTUP ) && - !(ufshcd_get_uic_cmd_result (hba))) { - -if (ufshcd_make_hba_operational (hba)) -dev_err (hba->dev, -"cc: hba not operational state\n" ); -return ; - } -} - -/** * ufshcd_fatal_err_handler - handle fatal errors * @hba: per adapter instance */drivers/scsi/ufs/ufshcd.c +1
-1@@ -1555,7 +1634,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)ufshcd_err_handler (hba );if (intr_status &UIC_COMMAND_COMPL ) -schedule_work (&hba->uic_workq); +ufshcd_uic_cmd_compl (hba);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler(hba);drivers/scsi/ufs/ufshcd.c +18
-1@@ -1778,6 +1857,21 @@ out:return err; } +/** +* ufshcd_async_scan - asynchronous execution for link startup +* @data: data pointer to pass to this function +* @cookie: cookie data +*/ +static void ufshcd_async_scan (void *data,async_cookie_t cookie) +{ +struct ufs_hba *hba = (struct ufs_hba *)data; +int ret; + + ret =ufshcd_link_startup (hba); +if (!ret) +scsi_scan_host (hba->host); +} +static struct scsi_host_template ufshcd_driver_template = { .module =THIS_MODULE , .name =UFSHCD ,@@ -1939,12 +2033,14 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,init_waitqueue_head (&hba->ufshcd_tm_wait_queue);/* Initialize work queues */ -INIT_WORK (&hba->uic_workq, ufshcd_uic_cc_handler);INIT_WORK (&hba->feh_workq, ufshcd_fatal_err_handler);/* Initialize mutex for query requests */ mutex_init (&hba->query.lock_ufs_query); +/* Initialize UIC command mutex */ +mutex_init (&hba->uic_cmd_mutex); +/* IRQ registration */ err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {drivers/scsi/ufs/ufshcd.c +6
-3@@ -1965,14 +2061,17 @@ int ufshcd_init(struct device *dev, structufs_hba **hba_handle, goto out_free_irq; } -/* Initialization routine */ - err =ufshcd_initialize_hba (hba); +/* Host controller enable */ + err =ufshcd_hba_enable (hba);if (err) { -dev_err (hba->dev,"Initialization failed\n" ); +dev_err (hba->dev,"Host controller enable failed\n" ); goto out_remove_scsi_host; } + *hba_handle = hba; +async_schedule (ufshcd_async_scan, hba); +return 0 ;
out_remove_scsi_host:drivers/scsi/ufs/ufshcd.h +7
-2@@ -51,6 +51,7 @@#include <linux/bitops.h> #include <linux/pm_runtime.h> #include <linux/clk.h> +#include <linux/completion.h> #include <asm/irq.h> #include <asm/byteorder.h> @@ -76,6 +77,7 @@* @argument3: UIC command argument 3 * @cmd_active: Indicate if UIC command is outstanding * @result: UIC command result +* @done: UIC command completion */ struct uic_command {u32 command;@@ -84,6 +86,7 @@ struct uic_command {u32 argument3;int cmd_active;int result; +struct completion done; };/** @@ -150,11 +153,11 @@ struct ufs_query {* @ufs_version: UFS Version to which controller complies * @irq: Irq number of the controller * @active_uic_cmd: handle of active UIC command +* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits -* @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors * @query: query request information @@ -186,7 +189,9 @@ struct ufs_hba {u32 ufs_version;unsigned int irq; -struct uic_command active_uic_cmd; +struct uic_command *active_uic_cmd; +struct mutex uic_cmd_mutex; +wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition;drivers/scsi/ufs/ufshcd.h struct ufs_hba { · line 204
Quoted 7 lines
drivers/scsi/ufs/ufshcd.h +0
-1@@ -194,7 +199,6 @@ struct ufs_hba {u32 intr_mask;/* Work Queues */ -struct work_struct uic_workq;struct work_struct feh_workq;/* HBA Errors */ --
Regards,
Sujit
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
RE: [PATCH v3 4/6] scsi: ufs: rework link start-up process
In reply to Sujit Reddy ThummaQuoted 42 lines · Sujit Reddy Thumma
Quoted 7 lines · Seungwon Jeon
Link start-up requires long time with multiphase handshakes between UFS host and device. This affects driver's probe time. This patch let link start-up run asynchronously. Link start-up will be executed at the end of prove separately. Along with this change, the following is worked.
Defined completion time of uic command to avoid a permanent wait.
We have seen a kernel crash when the timeout happens in our internal testing. This is basically because the the
UIC_CMD_TIMEOUTof 500msec is less for our platform. We seeUIC_COMMAND_COMPLinterrupt after this timeout and sinceuic_cmdis freed we see a kernel crash.[ 6.026094] ufshcd 0000:01:00.0: link startup: error code -110 [ 6.030886] ufshcd 0000:01:00.0: link startup failed -110...
[ 6.487288] BUG: spinlock bad magic on CPU#0, swapper/0/0 [ 6.491683] Unable to handle kernel paging request at virtual address 6000012b ... [ 7.625270] [<c07c3718>] (spin_dump+0x4c/0x88) from [<c02ab9d8>] (do_raw_spin_lock+0x20/0x154) [ 7.633877] [<c02ab9d8>] (do_raw_spin_lock+0x20/0x154) from [<c07ccba4>] (_raw_spin_lock_irqsave+0x28/0x30) [ 7.643583] [<c07ccba4>] (_raw_spin_lock_irqsave+0x28/0x30) from [<c00a3c98>] (complete+0x1c/0x58) [ 7.652525] [<c00a3c98>] (complete+0x1c/0x58) from [<c03d10c4>] (ufshcd_intr+0x1a8/0x498) [ 7.660705] [<c03d10c4>] (ufshcd_intr+0x1a8/0x498) from [<c00cff48>] (handle_irq_event_percpu+0xb0/0x290) [ 7.670227] [<c00cff48>] (handle_irq_event_percpu+0xb0/0x290) from [<c00d0164>] (handle_irq_event+0x3c/0x5c) [ 7.680054] [<c00d0164>] (handle_irq_event+0x3c/0x5c) from [<c00d2c50>] (handle_fasteoi_irq+0xdc/0x148) [ 7.689424] [<c00d2c50>] (handle_fasteoi_irq+0xdc/0x148) from [<c00cf7ac>] (generic_handle_irq+0x30/0x44) [ 7.698977] [<c00cf7ac>] (generic_handle_irq+0x30/0x44) from [<c000ee40>] (handle_IRQ+0x7c/0xc0) [ 7.707736] [<c000ee40>] (handle_IRQ+0x7c/0xc0) from [<c0008620>] (gic_handle_irq+0x94/0x110) [ 7.716252] [<c0008620>] (gic_handle_irq+0x94/0x110) from
Quoted 5 lines
[<
c07ccec0>] (__irq_svc+0x40/0x70)Following would fix this. Please check. Also, we need to increase the timeout to say 5 secs to avoid such races.
Thank you for test.
I have seen the completion of link startup within current timeout ever. It should be fixed for that case.
By the way, I feel 5 seconds looks like a little too long. Currently, is your platform situation with UFS in normal stage? The UNIPRO spec. mentions the 100 ms as timeout internally for link startup. Anyway, do you mean that you want to change timeout value to 5 seconds? I think it has a strong dependency with your platform.
1 sec seems proper though the worst case is considered.
Thanks,
Seungwon Jeon
Quoted 548 lines
drivers/scsi/ufs/ufshcd.c +6
-1@@ -485,6 +485,7 @@ static int ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) { int ret; +unsigned long flags;if (wait_for_completion_timeout (&uic_cmd->done,msecs_to_jiffies (UIC_CMD_TIMEOUT )))@@ -492,6 +493,10 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) else ret = -ETIMEDOUT ; +spin_lock_irqsave (hba->host->host_lock, flags); + hba->active_uic_cmd =NULL ; +spin_unlock_irqrestore (hba->host->host_lock, flags); +return ret; }@@ -1842,7 +1847,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,struct ufshcd_lrb *lrbp) */ static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { -if (intr_status &UIC_COMMAND_COMPL ) { +if (hba->active_uic_cmd && (intr_status &UIC_COMMAND_COMPL )) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba);
hba->active_uic_cmd->argument3=Quoted 496 lines
Added mutex to guarantee of uic command at a time. Adapted some sequence of controller initialization after link statup according to HCI standard.
Signed-off-by Seungwon Jeon <[email protected]>Signed-off-by Sujit Reddy Thumma <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 287 ++++++++++++++++++++++++++++++--------------- drivers/scsi/ufs/ufshcd.h | 10 +- 2 files changed, 200 insertions(+), 97 deletions(-)drivers/scsi/ufs/ufshcd.c +193
-94@@ -33,11 +33,15 @@* this program. */ +#include <linux/async.h> +#include "ufshcd.h" #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) +/* UIC command timeout, unit: ms */ +#define UIC_CMD_TIMEOUT 500enum {UFSHCD_MAX_CHANNEL =0 ,@@ -401,24 +405,115 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) }/** -* ufshcd_send_uic_command - Send UIC commands to unipro layers +* ufshcd_ready_for_uic_cmd - Check if controller is ready +* to accept UIC commands * @hba: per adapter instance -* @uic_command: UIC command +* Return true on success, else false +*/ +static inline bool ufshcd_ready_for_uic_cmd (struct ufs_hba *hba) +{ +if (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) +return true; +else +return false; +} + +/** +* ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Mutex must be held. */ static inline void -ufshcd_send_uic_command (struct ufs_hba *hba,struct uic_command *uic_cmnd) +ufshcd_dispatch_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) { + hba->active_uic_cmd = uic_cmd; +/* Write Args */ -ufshcd_writel (hba, uic_cmnd->argument1,REG_UIC_COMMAND_ARG_1 ); -ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); -ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 ); +ufshcd_writel (hba, uic_cmd->argument1,REG_UIC_COMMAND_ARG_1 ); +ufshcd_writel (hba, uic_cmd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +ufshcd_writel (hba, uic_cmd->command &COMMAND_OPCODE_MASK ,REG_UIC_COMMAND ); }/** +* ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command +* @hba: per adapter instance +* @uic_command: UIC command +* +* Must be called with mutex held. +* Returns 0 only if success. +*/ +static int +ufshcd_wait_for_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +if (wait_for_completion_timeout (&uic_cmd->done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) + ret = uic_cmd->argument2 &MASK_UIC_COMMAND_RESULT ; +else + ret = -ETIMEDOUT ; + +return ret; +} + +/** +* __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Identical to ufshcd_send_uic_cmd() expect mutex. Must be called +* with mutex held. +* Returns 0 only if success. +*/ +static int +__ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; +unsigned long flags; + +if (!ufshcd_ready_for_uic_cmd (hba)) { +dev_err (hba->dev, +"Controller not ready to accept UIC commands\n" ); +return -EIO ; + } + +init_completion (&uic_cmd->done); + +spin_lock_irqsave (hba->host->host_lock, flags); +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba, uic_cmd); + +return ret; +} + +/** +* ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Returns 0 only if success. +*/ +static int +ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, uic_cmd); +mutex_unlock (&hba->uic_cmd_mutex); + +return ret; +} + +/** * ufshcd_map_sg - Map scatter-gather list to prdt * @lrbp - pointer to local reference block * @@ -962,34 +1057,16 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)*/ static int ufshcd_dme_link_startup (struct ufs_hba *hba) { -struct uic_command *uic_cmd; -unsigned long flags; +struct uic_command uic_cmd = {0 }; +int ret; -/* check if controller is ready to accept UIC commands */ -if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) & -UIC_COMMAND_READY ) ==0x0 ) { -dev_err (hba->dev, -"Controller not ready" -" to accept UIC commands\n" ); -return -EIO ; - } - -spin_lock_irqsave (hba->host->host_lock, flags); + uic_cmd.command =UIC_CMD_DME_LINK_STARTUP ; -/* form UIC command */ - uic_cmd = &hba->active_uic_cmd; - uic_cmd->command =UIC_CMD_DME_LINK_STARTUP ; - uic_cmd->argument1 =0 ; - uic_cmd->argument2 =0 ; - uic_cmd->argument3 =0 ; - -/* enable UIC related interrupts */ -ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); - -/* sending UIC commands to controller */ -ufshcd_send_uic_command (hba, uic_cmd); -spin_unlock_irqrestore (hba->host->host_lock, flags); -return 0 ; + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev, +"link startup: error code %d\n" , ret); +return ret; }/** @@ -998,9 +1075,10 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)* * To bring UFS host controller to operational state, * 1. Check if device is present -* 2. Configure run-stop-registers -* 3. Enable required interrupts -* 4. Configure interrupt aggregation +* 2. Enable required interrupts +* 3. Configure interrupt aggregation +* 4. Program UTRL and UTMRL base addres +* 5. Configure run-stop-registers * * Returns 0 on success, non-zero value on failure */ @@ -1017,6 +1095,22 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } +/* Enable required interrupts */ +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); + +/* Configure interrupt aggregation */ +ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); + +/* Configure UTRL and UTMRL base address registers */ +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H ); +/* * UCRDY, UTMRLDY and UTRLRDY bits must be 1 * DEI, HEI bits must be 0 @@ -1030,17 +1124,11 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } -/* Enable required interrupts */ -ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); - -/* Configure interrupt aggregation */ -ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); -if (hba->ufshcd_state ==UFSHCD_STATE_RESET )scsi_unblock_requests (hba->host); hba->ufshcd_state =UFSHCD_STATE_OPERATIONAL ; -scsi_scan_host (hba->host); + out:return err; }@@ -1109,34 +1197,29 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) }/** -* ufshcd_initialize_hba - start the initialization process +* ufshcd_link_startup - Initialize unipro link startup * @hba: per adapter instance * -* 1. Enable the controller via ufshcd_hba_enable. -* 2. Program the Transfer Request List Address with the starting address of -* UTRDL. -* 3. Program the Task Management Request List Address with starting address -* of UTMRDL. -* -* Returns 0 on success, non-zero value on failure. +* Returns 0 for success, non-zero in case of failure */ -static int ufshcd_initialize_hba (struct ufs_hba *hba) +static int ufshcd_link_startup (struct ufs_hba *hba) { -if (ufshcd_hba_enable (hba)) -return -EIO ; +int ret; -/* Configure UTRL and UTMRL base address registers */ -ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_H ); -ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_H ); +/* enable UIC related interrupts */ +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); + + ret =ufshcd_dme_link_startup (hba); +if (ret) + goto out; -/* Initialize unipro link startup procedure */ -return ufshcd_dme_link_startup (hba); + ret =ufshcd_make_hba_operational (hba); +if (ret) + goto out; + +out: +dev_err (hba->dev,"link startup failed %d\n" , ret); +return ret; }/** @@ -1176,12 +1259,19 @@ static int ufshcd_do_reset(struct ufs_hba *hba) hba->outstanding_reqs =0 ; hba->outstanding_tasks =0 ; -/* start the initialization process */ -if (ufshcd_initialize_hba (hba)) { +/* Host controller enable */ +if (ufshcd_hba_enable (hba)) {dev_err (hba->dev,"Reset: Controller initialization failed\n" );return FAILED ; } + +if (ufshcd_link_startup (hba)) { +dev_err (hba->dev, +"Reset: Link start-up failed\n" ); +return FAILED ; + } +return SUCCESS ; }@@ -1434,6 +1524,17 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) }/** +* ufshcd_uic_cmd_compl - handle completion of uic command +* @hba: per adapter instance +*/ +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +{ + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); +complete (&hba->active_uic_cmd->done); +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance */ @@ -1473,28 +1574,6 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) }/** -* ufshcd_uic_cc_handler - handle UIC command completion -* @work: pointer to a work queue structure -* -* Returns 0 on success, non-zero value on failure -*/ -static void ufshcd_uic_cc_handler (struct work_struct *work) -{ -struct ufs_hba *hba; - - hba = container_of(work, struct ufs_hba, uic_workq); - -if ((hba->active_uic_cmd.command ==UIC_CMD_DME_LINK_STARTUP ) && - !(ufshcd_get_uic_cmd_result (hba))) { - -if (ufshcd_make_hba_operational (hba)) -dev_err (hba->dev, -"cc: hba not operational state\n" ); -return ; - } -} - -/** * ufshcd_fatal_err_handler - handle fatal errors * @hba: per adapter instance */ @@ -1555,7 +1634,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)ufshcd_err_handler (hba);if (intr_status &UIC_COMMAND_COMPL ) -schedule_work (&hba->uic_workq); +ufshcd_uic_cmd_compl (hba);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);@@ -1778,6 +1857,21 @@ out:return err; } +/** +* ufshcd_async_scan - asynchronous execution for link startup +* @data: data pointer to pass to this function +* @cookie: cookie data +*/ +static void ufshcd_async_scan (void *data,async_cookie_t cookie) +{ +struct ufs_hba *hba = (struct ufs_hba *)data; +int ret; + + ret =ufshcd_link_startup (hba); +if (!ret) +scsi_scan_host (hba->host); +} +static struct scsi_host_template ufshcd_driver_template = { .module =THIS_MODULE , .name =UFSHCD ,@@ -1939,12 +2033,14 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,init_waitqueue_head (&hba->ufshcd_tm_wait_queue);/* Initialize work queues */ -INIT_WORK (&hba->uic_workq, ufshcd_uic_cc_handler);INIT_WORK (&hba->feh_workq, ufshcd_fatal_err_handler);/* Initialize mutex for query requests */ mutex_init (&hba->query.lock_ufs_query); +/* Initialize UIC command mutex */ +mutex_init (&hba->uic_cmd_mutex); +/* IRQ registration */ err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {@@ -1965,14 +2061,17 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, goto out_free_irq; } -/* Initialization routine */ - err =ufshcd_initialize_hba (hba); +/* Host controller enable */ + err =ufshcd_hba_enable (hba);if (err) { -dev_err (hba->dev,"Initialization failed\n" ); +dev_err (hba->dev,"Host controller enable failed\n" ); goto out_remove_scsi_host; } + *hba_handle = hba; +async_schedule (ufshcd_async_scan, hba); +return 0 ; out_remove_scsi_host:drivers/scsi/ufs/ufshcd.h +7
-2@@ -51,6 +51,7 @@#include <linux/bitops.h> #include <linux/pm_runtime.h> #include <linux/clk.h> +#include <linux/completion.h> #include <asm/irq.h> #include <asm/byteorder.h> @@ -76,6 +77,7 @@* @argument3: UIC command argument 3 * @cmd_active: Indicate if UIC command is outstanding * @result: UIC command result +* @done: UIC command completion */ struct uic_command {u32 command;@@ -84,6 +86,7 @@ struct uic_command {u32 argument3;int cmd_active;int result; +struct completion done; };/** @@ -150,11 +153,11 @@ struct ufs_query {* @ufs_version: UFS Version to which controller complies * @irq: Irq number of the controller * @active_uic_cmd: handle of active UIC command +* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits -* @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors * @query: query request information @@ -186,7 +189,9 @@ struct ufs_hba {u32 ufs_version;unsigned int irq; -struct uic_command active_uic_cmd; +struct uic_command *active_uic_cmd; +struct mutex uic_cmd_mutex; +wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition;drivers/scsi/ufs/ufshcd.h struct ufs_hba { · line 204
Quoted 7 lines
drivers/scsi/ufs/ufshcd.h +0
-1@@ -194,7 +199,6 @@ struct ufs_hba {u32 intr_mask;/* Work Queues */ -struct work_struct uic_workq;struct work_struct feh_workq;/* HBA Errors */ --
Regards,
Sujit
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v3 4/6] scsi: ufs: rework link start-up process
Quoted 60 lines · Sujit Reddy Thumma
Quoted 42 lines · Seungwon Jeon
Quoted 7 lines
Link start-up requires long time with multiphase handshakes between UFS host and device. This affects driver's probe time. This patch let link start-up run asynchronously. Link start-up will be executed at the end of prove separately. Along with this change, the following is worked.
Defined completion time of uic command to avoid a permanent wait.
We have seen a kernel crash when the timeout happens in our internal testing. This is basically because the the
UIC_CMD_TIMEOUTof 500msec is less for our platform. We seeUIC_COMMAND_COMPLinterrupt after this timeout and sinceuic_cmdis freed we see a kernel crash.[ 6.026094] ufshcd 0000:01:00.0: link startup: error code -110 [ 6.030886] ufshcd 0000:01:00.0: link startup failed -110...
[ 6.487288] BUG: spinlock bad magic on CPU#0, swapper/0/0 [ 6.491683] Unable to handle kernel paging request at virtual address 6000012b ... [ 7.625270] [<c07c3718>] (spin_dump+0x4c/0x88) from [<c02ab9d8>] (do_raw_spin_lock+0x20/0x154) [ 7.633877] [<c02ab9d8>] (do_raw_spin_lock+0x20/0x154) from [<c07ccba4>] (_raw_spin_lock_irqsave+0x28/0x30) [ 7.643583] [<c07ccba4>] (_raw_spin_lock_irqsave+0x28/0x30) from [<c00a3c98>] (complete+0x1c/0x58) [ 7.652525] [<c00a3c98>] (complete+0x1c/0x58) from [<c03d10c4>] (ufshcd_intr+0x1a8/0x498) [ 7.660705] [<c03d10c4>] (ufshcd_intr+0x1a8/0x498) from [<c00cff48>] (handle_irq_event_percpu+0xb0/0x290) [ 7.670227] [<c00cff48>] (handle_irq_event_percpu+0xb0/0x290) from [<c00d0164>] (handle_irq_event+0x3c/0x5c) [ 7.680054] [<c00d0164>] (handle_irq_event+0x3c/0x5c) from [<c00d2c50>] (handle_fasteoi_irq+0xdc/0x148) [ 7.689424] [<c00d2c50>] (handle_fasteoi_irq+0xdc/0x148) from [<c00cf7ac>] (generic_handle_irq+0x30/0x44) [ 7.698977] [<c00cf7ac>] (generic_handle_irq+0x30/0x44) from [<c000ee40>] (handle_IRQ+0x7c/0xc0) [ 7.707736] [<c000ee40>] (handle_IRQ+0x7c/0xc0) from [<c0008620>] (gic_handle_irq+0x94/0x110) [ 7.716252] [<c0008620>] (gic_handle_irq+0x94/0x110) fromQuoted 5 lines
[<
c07ccec0>] (__irq_svc+0x40/0x70)Following would fix this. Please check. Also, we need to increase the timeout to say 5 secs to avoid such races.
Thank you for test.
I have seen the completion of link startup within current timeout ever. It should be fixed for that case.
By the way, I feel 5 seconds looks like a little too long. Currently, is your platform situation with UFS in normal stage? The UNIPRO spec. mentions the 100 ms as timeout internally for link startup.
Anyway, do you mean that you want to change timeout value to 5 seconds? I think it has a strong dependency with your platform.
1 sec seems proper though the worst case is considered.
Quoted 2 lines
Thanks,
Seungwon Jeon
I agree, you can keep a timeout of 500ms. I got the timeout due to a unipro issue and not due to low timeout value.
Thanks,
Maya
Quoted 576 lines
Quoted 560 lines
drivers/scsi/ufs/ufshcd.c +1
-0@@ -485,6 +485,7 @@ static int ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) { int ret; +unsigned long flags; if (wait_for_completion_timeout(&uic_cmd->done,drivers/scsi/ufs/ufshcd.c +5
-1msecs_to_jiffies(UIC_CMD_TIMEOUT)))@@ -492,6 +493,10 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) else ret = -ETIMEDOUT ; +spin_lock_irqsave (hba->host->host_lock, flags); + hba->active_uic_cmd =NULL ; +spin_unlock_irqrestore (hba->host->host_lock, flags); +return ret; }@@ -1842,7 +1847,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,struct ufshcd_lrb *lrbp) */ static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { -if (intr_status &UIC_COMMAND_COMPL ) { +if (hba->active_uic_cmd && (intr_status &UIC_COMMAND_COMPL )) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba);
hba->active_uic_cmd->argument3=Quoted 8 lines
Added mutex to guarantee of uic command at a time. Adapted some sequence of controller initialization after link statup according to HCI standard.
Signed-off-by Seungwon Jeon <[email protected]>Signed-off-by Sujit Reddy Thumma <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 287++++++++++++++++++++++++++++++---------------
drivers/scsi/ufs/ufshcd.c static inline void
Quoted 24 lines
drivers/scsi/ufs/ufshcd.h | 10 +- 2 files changed, 200 insertions(+), 97 deletions(-)drivers/scsi/ufs/ufshcd.c +4
-0@@ -33,11 +33,15 @@* this program. */ +#include <linux/async.h> +#include "ufshcd.h" #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) +/* UIC command timeout, unit: ms */ +#define UIC_CMD_TIMEOUT 500enum {UFSHCD_MAX_CHANNEL =0 ,@@ -401,24 +405,115 @@ static inline void
ufshcd_hba_capabilities(struct ufs_hba *hba)Quoted 17 lines
drivers/scsi/ufs/ufshcd.c +11
-2}/** -* ufshcd_send_uic_command - Send UIC commands to unipro layers +* ufshcd_ready_for_uic_cmd - Check if controller is ready +* to accept UIC commands * @hba: per adapter instance -* @uic_command: UIC command +* Return true on success, else false +*/ +static inline bool ufshcd_ready_for_uic_cmd (struct ufs_hba *hba) +{ +if (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) +return true; +else +return false; +}drivers/scsi/ufs/ufshcd.c static inline void · line 409
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +7
-1+ +/** +* ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Mutex must be held. */ static inline void -ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command
*uic_cmnd)drivers/scsi/ufs/ufshcd.c static inline void · line 429
Quoted 1 line
drivers/scsi/ufs/ufshcd.c +1
-0+ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command
*uic_cmd)Quoted 17 lines
drivers/scsi/ufs/ufshcd.c +6
-4{ + hba->active_uic_cmd = uic_cmd; +/* Write Args */ -ufshcd_writel (hba, uic_cmnd->argument1,REG_UIC_COMMAND_ARG_1 ); -ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); -ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 ); +ufshcd_writel (hba, uic_cmd->argument1,REG_UIC_COMMAND_ARG_1 ); +ufshcd_writel (hba, uic_cmd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +ufshcd_writel (hba, uic_cmd->command &COMMAND_OPCODE_MASK ,REG_UIC_COMMAND ); }drivers/scsi/ufs/ufshcd.c static inline void · line 452
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +9
-0/** +* ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command +* @hba: per adapter instance +* @uic_command: UIC command +* +* Must be called with mutex held. +* Returns 0 only if success. +*/ +static int +ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command
*uic_cmd)Quoted 13 lines
drivers/scsi/ufs/ufshcd.c +13
-0+{ +int ret; + +if (wait_for_completion_timeout (&uic_cmd->done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) + ret = uic_cmd->argument2 &MASK_UIC_COMMAND_RESULT ; +else + ret = -ETIMEDOUT ; + +return ret; +} + +/** drivers/scsi/ufs/ufshcd.c static inline void · line 475
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +10
-0+* __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Identical to ufshcd_send_uic_cmd() expect mutex. Must be called +* with mutex held. +* Returns 0 only if success. +*/ +static int +__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command
*uic_cmd)drivers/scsi/ufs/ufshcd.c static void ufshcd_host_memory_configure(struct
Quoted 45 lines
drivers/scsi/ufs/ufshcd.c +41
-0+{ +int ret; +unsigned long flags; + +if (!ufshcd_ready_for_uic_cmd (hba)) { +dev_err (hba->dev, +"Controller not ready to accept UIC commands\n" ); +return -EIO ; + } + +init_completion (&uic_cmd->done); + +spin_lock_irqsave (hba->host->host_lock, flags); +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba, uic_cmd); + +return ret; +} + +/** +* ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Returns 0 only if success. +*/ +static int +ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, uic_cmd); +mutex_unlock (&hba->uic_cmd_mutex); + +return ret; +} + +/** * ufshcd_map_sg - Map scatter-gather list to prdt * @lrbp - pointer to local reference block * @@ -962,34 +1057,16 @@ static void ufshcd_host_memory_configure(struct
ufs_hba*hba)drivers/scsi/ufs/ufshcd.c static int ufshcd_dme_link_startup(struct
Quoted 43 lines
drivers/scsi/ufs/ufshcd.c +8
-26*/ static int ufshcd_dme_link_startup (struct ufs_hba *hba) { -struct uic_command *uic_cmd; -unsigned long flags; +struct uic_command uic_cmd = {0 }; +int ret; -/* check if controller is ready to accept UIC commands */ -if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) & -UIC_COMMAND_READY ) ==0x0 ) { -dev_err (hba->dev, -"Controller not ready" -" to accept UIC commands\n" ); -return -EIO ; - } - -spin_lock_irqsave (hba->host->host_lock, flags); + uic_cmd.command =UIC_CMD_DME_LINK_STARTUP ; -/* form UIC command */ - uic_cmd = &hba->active_uic_cmd; - uic_cmd->command =UIC_CMD_DME_LINK_STARTUP ; - uic_cmd->argument1 =0 ; - uic_cmd->argument2 =0 ; - uic_cmd->argument3 =0 ; - -/* enable UIC related interrupts */ -ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); - -/* sending UIC commands to controller */ -ufshcd_send_uic_command (hba, uic_cmd); -spin_unlock_irqrestore (hba->host->host_lock, flags); -return 0 ; + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev, +"link startup: error code %d\n" , ret); +return ret; }/** @@ -998,9 +1075,10 @@ static int ufshcd_dme_link_startup(struct
ufs_hba*hba)drivers/scsi/ufs/ufshcd.c static int ufshcd_make_hba_operational(struct
Quoted 14 lines
drivers/scsi/ufs/ufshcd.c +4
-3* * To bring UFS host controller to operational state, * 1. Check if device is present -* 2. Configure run-stop-registers -* 3. Enable required interrupts -* 4. Configure interrupt aggregation +* 2. Enable required interrupts +* 3. Configure interrupt aggregation +* 4. Program UTRL and UTMRL base addres +* 5. Configure run-stop-registers * * Returns 0 on success, non-zero value on failure */ @@ -1017,6 +1095,22 @@ static int ufshcd_make_hba_operational(struct
ufs_hba*hba)drivers/scsi/ufs/ufshcd.c static int ufshcd_make_hba_operational(struct
Quoted 23 lines
drivers/scsi/ufs/ufshcd.c +16
-0goto out; } +/* Enable required interrupts */ +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); + +/* Configure interrupt aggregation */ +ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); + +/* Configure UTRL and UTMRL base address registers */ +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H ); +/* * UCRDY, UTMRLDY and UTRLRDY bits must be 1 * DEI, HEI bits must be 0 @@ -1030,17 +1124,11 @@ static int ufshcd_make_hba_operational(struct
ufs_hba*hba)drivers/scsi/ufs/ufshcd.c static int ufshcd_hba_enable(struct ufs_hba
Quoted 19 lines
drivers/scsi/ufs/ufshcd.c +1
-7goto out; } -/* Enable required interrupts */ -ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); - -/* Configure interrupt aggregation */ -ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); -if (hba->ufshcd_state ==UFSHCD_STATE_RESET )scsi_unblock_requests (hba->host); hba->ufshcd_state =UFSHCD_STATE_OPERATIONAL ; -scsi_scan_host (hba->host); + out:return err; }@@ -1109,34 +1197,29 @@ static int ufshcd_hba_enable(struct ufs_hba*hba)
drivers/scsi/ufs/ufshcd.c static int ufshcd_hba_enable(struct ufs_hba · line 1116
Quoted 9 lines
drivers/scsi/ufs/ufshcd.c +1
-3}/** -* ufshcd_initialize_hba - start the initialization process +* ufshcd_link_startup - Initialize unipro link startup * @hba: per adapter instance * -* 1. Enable the controller via ufshcd_hba_enable. -* 2. Program the Transfer Request List Address with the starting address of
drivers/scsi/ufs/ufshcd.c static int ufshcd_hba_enable(struct ufs_hba · line 1118
Quoted 2 lines
drivers/scsi/ufs/ufshcd.c +0
-2-* UTRDL. -* 3. Program the Task Management Request List Address with starting address
drivers/scsi/ufs/ufshcd.c static int ufshcd_do_reset(struct ufs_hba
Quoted 41 lines
drivers/scsi/ufs/ufshcd.c +16
-17-* of UTMRDL. -* -* Returns 0 on success, non-zero value on failure. +* Returns 0 for success, non-zero in case of failure */ -static int ufshcd_initialize_hba (struct ufs_hba *hba) +static int ufshcd_link_startup (struct ufs_hba *hba) { -if (ufshcd_hba_enable (hba)) -return -EIO ; +int ret; -/* Configure UTRL and UTMRL base address registers */ -ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_H ); -ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_H ); +/* enable UIC related interrupts */ +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); + + ret =ufshcd_dme_link_startup (hba); +if (ret) + goto out; -/* Initialize unipro link startup procedure */ -return ufshcd_dme_link_startup (hba); + ret =ufshcd_make_hba_operational (hba); +if (ret) + goto out; + +out: +dev_err (hba->dev,"link startup failed %d\n" , ret); +return ret; }/** @@ -1176,12 +1259,19 @@ static int ufshcd_do_reset(struct ufs_hba*hba)
drivers/scsi/ufs/ufshcd.c ufshcd_transfer_rsp_status(struct ufs_hba *hba,
Quoted 22 lines
drivers/scsi/ufs/ufshcd.c +9
-2hba->outstanding_reqs =0 ; hba->outstanding_tasks =0 ; -/* start the initialization process */ -if (ufshcd_initialize_hba (hba)) { +/* Host controller enable */ +if (ufshcd_hba_enable (hba)) {dev_err (hba->dev,"Reset: Controller initialization failed\n" );return FAILED ; } + +if (ufshcd_link_startup (hba)) { +dev_err (hba->dev, +"Reset: Link start-up failed\n" ); +return FAILED ; + } +return SUCCESS ; }@@ -1434,6 +1524,17 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,struct
ufshcd_lrb*lrbp)Quoted 5 lines
drivers/scsi/ufs/ufshcd.c +2
-0}/** +* ufshcd_uic_cmd_compl - handle completion of uic command +* @hba: per adapter instance drivers/scsi/ufs/ufshcd.c ufshcd_transfer_rsp_status(struct ufs_hba *hba, · line 1538
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +9
-0+*/ +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +{ + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); +complete (&hba->active_uic_cmd->done); +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion
drivers/scsi/ufs/ufshcd.c static void ufshcd_transfer_req_compl(struct
Quoted 3 lines
drivers/scsi/ufs/ufshcd.c +0
-0* @hba: per adapter instance */ @@ -1473,28 +1574,6 @@ static void ufshcd_transfer_req_compl(struct
ufs_hba*hba)drivers/scsi/ufs/ufshcd.c static void ufshcd_sl_intr(struct ufs_hba *hba,
Quoted 29 lines
drivers/scsi/ufs/ufshcd.c +0
-22}/** -* ufshcd_uic_cc_handler - handle UIC command completion -* @work: pointer to a work queue structure -* -* Returns 0 on success, non-zero value on failure -*/ -static void ufshcd_uic_cc_handler (struct work_struct *work) -{ -struct ufs_hba *hba; - - hba = container_of(work, struct ufs_hba, uic_workq); - -if ((hba->active_uic_cmd.command ==UIC_CMD_DME_LINK_STARTUP ) && - !(ufshcd_get_uic_cmd_result (hba))) { - -if (ufshcd_make_hba_operational (hba)) -dev_err (hba->dev, -"cc: hba not operational state\n" ); -return ; - } -} - -/** * ufshcd_fatal_err_handler - handle fatal errors * @hba: per adapter instance */ @@ -1555,7 +1634,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba,u32
intr_status)drivers/scsi/ufs/ufshcd.c int ufshcd_init(struct device *dev, struct
Quoted 31 lines
drivers/scsi/ufs/ufshcd.c +16
-1ufshcd_err_handler (hba);if (intr_status &UIC_COMMAND_COMPL ) -schedule_work (&hba->uic_workq); +ufshcd_uic_cmd_compl (hba);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);@@ -1778,6 +1857,21 @@ out:return err; } +/** +* ufshcd_async_scan - asynchronous execution for link startup +* @data: data pointer to pass to this function +* @cookie: cookie data +*/ +static void ufshcd_async_scan (void *data,async_cookie_t cookie) +{ +struct ufs_hba *hba = (struct ufs_hba *)data; +int ret; + + ret =ufshcd_link_startup (hba); +if (!ret) +scsi_scan_host (hba->host); +} +static struct scsi_host_template ufshcd_driver_template = { .module =THIS_MODULE , .name =UFSHCD ,@@ -1939,12 +2033,14 @@ int ufshcd_init(struct device *dev, struct
ufs_hba**hba_handle,drivers/scsi/ufs/ufshcd.c int ufshcd_init(struct device *dev, struct
Quoted 16 lines
drivers/scsi/ufs/ufshcd.c +3
-1init_waitqueue_head (&hba->ufshcd_tm_wait_queue);/* Initialize work queues */ -INIT_WORK (&hba->uic_workq, ufshcd_uic_cc_handler);INIT_WORK (&hba->feh_workq, ufshcd_fatal_err_handler);/* Initialize mutex for query requests */ mutex_init (&hba->query.lock_ufs_query); +/* Initialize UIC command mutex */ +mutex_init (&hba->uic_cmd_mutex); +/* IRQ registration */ err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {@@ -1965,14 +2061,17 @@ int ufshcd_init(struct device *dev, struct
ufs_hba**hba_handle,Quoted 79 lines
drivers/scsi/ufs/ufshcd.c +6
-3goto out_free_irq; } -/* Initialization routine */ - err =ufshcd_initialize_hba (hba); +/* Host controller enable */ + err =ufshcd_hba_enable (hba);if (err) { -dev_err (hba->dev,"Initialization failed\n" ); +dev_err (hba->dev,"Host controller enable failed\n" ); goto out_remove_scsi_host; } + *hba_handle = hba; +async_schedule (ufshcd_async_scan, hba); +return 0 ; out_remove_scsi_host:drivers/scsi/ufs/ufshcd.h +7
-3@@ -51,6 +51,7 @@#include <linux/bitops.h> #include <linux/pm_runtime.h> #include <linux/clk.h> +#include <linux/completion.h> #include <asm/irq.h> #include <asm/byteorder.h> @@ -76,6 +77,7 @@* @argument3: UIC command argument 3 * @cmd_active: Indicate if UIC command is outstanding * @result: UIC command result +* @done: UIC command completion */ struct uic_command {u32 command;@@ -84,6 +86,7 @@ struct uic_command {u32 argument3;int cmd_active;int result; +struct completion done; };/** @@ -150,11 +153,11 @@ struct ufs_query {* @ufs_version: UFS Version to which controller complies * @irq: Irq number of the controller * @active_uic_cmd: handle of active UIC command +* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits -* @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors * @query: query request information @@ -186,7 +189,9 @@ struct ufs_hba {u32 ufs_version;unsigned int irq; -struct uic_command active_uic_cmd; +struct uic_command *active_uic_cmd; +struct mutex uic_cmd_mutex; +wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition;@@ -194,7 +199,6 @@ struct ufs_hba {u32 intr_mask;/* Work Queues */ -struct work_struct uic_workq;struct work_struct feh_workq;Quoted 10 lines
drivers/scsi/ufs/ufshcd.h struct ufs_hba { · line 204
Quoted 2 lines
drivers/scsi/ufs/ufshcd.h +0
-0/* HBA Errors */ --
Regards,
Sujit
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH v3 5/6 scsi: ufs: add dme configuration primitives
In reply to Seungwon JeonImplements to support Get and Set operation of the DME. And along with these operations, IDs of Attribute are added. It is used to configure the behavior of the UNIPRO.
--- drivers/scsi/ufs/ufshcd.c | 84 +++++++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.h | 30 ++++++++++ drivers/scsi/ufs/ufshci.h | 4 ++ drivers/scsi/ufs/unipro.h | 130 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 248 insertions(+), 0 deletions(-) create mode 100644 drivers/scsi/ufs/unipro.h
drivers/scsi/ufs/ufshcd.c +84 -0
@@ -191,6 +191,18 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }/** +* ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command +* @hba: Pointer to adapter instance +* +* This function gets UIC command argument3 +* Returns 0 on success, non zero value on error +*/ +static inline u32 ufshcd_get_dme_attr_val (struct ufs_hba *hba) +{ +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_3 ); +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance
@@ -1070,6 +1082,76 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) }/** +* ufshcd_dme_xxx_set - UIC command for DME_SET, DME_PEER_SET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @attr_set: attribute set type as uic command argument2 +* @mib_val: setting value as uic command argument3 +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-set" , +"dme-peer-set" + }; +const char *set = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_SET :UIC_CMD_DME_SET ; + uic_cmd.argument1 = attr_sel; + uic_cmd.argument2 =UIC_ARG_ATTR_SET (attr_set); + uic_cmd.argument3 = mib_val; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); + +dev_dbg (hba->dev,"%s: error code %d\n" , set, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_set); + +/** +* ufshcd_dme_xxx_get - UIC command for DME_GET, DME_PEER_GET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @mib_val: the value of the attribute as returned by the UIC command +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-get" , +"dme-peer-get" + }; +const char *get = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_GET :UIC_CMD_DME_GET ; + uic_cmd.argument1 = attr_sel; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); + +if (mib_val) + *mib_val = uic_cmd.argument3; + +dev_dbg (hba->dev,"%s: error code %d\n" , get, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance *
@@ -1531,6 +1613,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba);complete (&hba->active_uic_cmd->done); }
drivers/scsi/ufs/ufshcd.h +30 -0
@@ -217,6 +217,11 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); +extern int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer); +extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer); +/** * ufshcd_hba_stop - Send controller to reset state * @hba: per adapter instance
@@ -226,4 +231,29 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba) ufshcd_writel(hba, CONTROLLER_DISABLE, REG_CONTROLLER_ENABLE); } +/* UIC command interfaces for DME primitives */ +static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,1 ); +} + +static inline int ufshcd_dme_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,1 ); +} +#endif /* End of Header */
drivers/scsi/ufs/ufshci.h +4 -0
@@ -191,6 +191,10 @@ enum {#define CONFIG_RESULT_CODE_MASK 0xFF#define GENERIC_ERROR_CODE_MASK 0xFF +#define UIC_ARG_MIB_SEL (attr, sel) ((((attr) & 0xFFFF) << 16) |\ + ((sel) & 0xFFFF)) +#define UIC_ARG_ATTR_SET (type) (((type) & 0xFF) << 16) +/* UIC Commands */ enum {UIC_CMD_DME_GET =0x01 ,
drivers/scsi/ufs/unipro.h new file +130 -0
130 lines not on this page · raw message
Signature · 1 line
1.7.0.4
Re: [PATCH v3 5/6] scsi: ufs: add dme configuration primitives
Quoted 119 lines
/**
+ *ufshcd_dme_xxx_set- UIC command forDME_SET,DME_PEER_SET
+ * @hba: per adapter instance
+ * @attr_sel: uic command argument1
+ * @attr_set: attribute set type as uic command argument2
+ * @mib_val: setting value as uic command argument3
+ * @peer: indicate wherter peer or non-peer
+ *
+ * Returns 0 on success, non-zero value on failure
+ */drivers/scsi/ufs/ufshcd.c +63
-0+int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-set" , +"dme-peer-set" + }; +const char *set = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_SET :UIC_CMD_DME_SET ; + uic_cmd.argument1 = attr_sel; + uic_cmd.argument2 =UIC_ARG_ATTR_SET (attr_set); + uic_cmd.argument3 = mib_val; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); + +dev_dbg (hba->dev,"%s: error code %d\n" , set, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_set); + +/** +* ufshcd_dme_xxx_get - UIC command for DME_GET, DME_PEER_GET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @mib_val: the value of the attribute as returned by the UIC command +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-get" , +"dme-peer-get" + }; +const char *get = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_GET :UIC_CMD_DME_GET ; + uic_cmd.argument1 = attr_sel; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); + +if (mib_val) + *mib_val = uic_cmd.argument3; + +dev_dbg (hba->dev,"%s: error code %d\n" , get, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance * @@ -1531,6 +1613,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba);complete (&hba->active_uic_cmd->done); }drivers/scsi/ufs/ufshcd.h +20
-0@@ -217,6 +217,11 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); +extern int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer); +extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer); +/** * ufshcd_hba_stop - Send controller to reset state * @hba: per adapter instance @@ -226,4 +231,29 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba)ufshcd_writel (hba,CONTROLLER_DISABLE ,REG_CONTROLLER_ENABLE ); } +/* UIC command interfaces for DME primitives */ +static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,1 ); +} + +static inline int ufshcd_dme_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val)
drivers/scsi/ufs/ufshcd.h static inline void ufshcd_hba_stop(struct ufs_hba *hba) · line 258
Quoted 10 lines
drivers/scsi/ufs/ufshcd.h +10
-0+{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,1 ); +} +
ufshcd_dme_xxx_get/set() are being used to configure attributes. So it is better to rename them as ufshcd_dme_attr_get/set().
Signature · 1 line
~Santosh
PATCH v3 6/6 scsi: ufs: add dme control primitives
In reply to Seungwon JeonImplements to support the following operations. Currently, this patch doesn't introduce DME_ENABLE and DME_RESET because host controller's HCE enable contains these roles.
DME_POWERON{OFF}, DME_HIBERNATE_ENTER{EXIT}, DME_ENDPOINTRESET.
--- drivers/scsi/ufs/ufshcd.c | 132 ++++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/ufs/ufshcd.h | 26 +++++++++ drivers/scsi/ufs/ufshci.h | 15 +++++ 3 files changed, 165 insertions(+), 8 deletions(-)
drivers/scsi/ufs/ufshcd.c +124 -8
@@ -39,6 +39,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)/* UIC command timeout, unit: ms */ #define UIC_CMD_TIMEOUT 500
@@ -203,6 +204,18 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) }/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance
@@ -1152,6 +1165,103 @@ int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel,EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get);/** +* ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* @on: indicate wherter power_on or power_off +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-power-off" , +"dme-power-on" + }; +const char *power = action[!!on]; +int ret; + + uic_cmd.command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: error code %d\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* @enter: indicate wherter hibernation enter or exit +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-hibernate-exit" , +"dme-hibernate-enter" + }; +const char *hibern8 = action[!!enter]; +u8 status; +int ret; + + uic_cmd.command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + +mutex_lock (&hba->uic_cmd_mutex); +init_completion (&hba->hibern8_done); + ret =__ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: error code %d\n" , hibern8, ret); + goto out; + } + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +mutex_unlock (&hba->uic_cmd_mutex); +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); + +/** +* ufshcd_dme_endpt_reset - UIC command for DME_ENDPOINTRESET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_endpt_reset (struct ufs_hba *hba) +{ +struct uic_command uic_cmd = {0 }; +int ret; + + uic_cmd.command =UIC_CMD_DME_END_PT_RST ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"endpoint reset: error code %d\n" , ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_endpt_reset); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance *
@@ -1608,14 +1718,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)/** * ufshcd_uic_cmd_compl - handle completion of uic command * @hba: per adapter instance +* @intr_status: interrupt status generated by the controller */ -static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { - hba->active_uic_cmd->argument2 |= -ufshcd_get_uic_cmd_result (hba); - hba->active_uic_cmd->argument3 = -ufshcd_get_dme_attr_val (hba); -complete (&hba->active_uic_cmd->done); +if (intr_status &UIC_COMMAND_COMPL ) { + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba); +complete (&hba->active_uic_cmd->done); + } + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/**
@@ -1717,8 +1833,8 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) -ufshcd_uic_cmd_compl (hba); +if (intr_status &UFSHCD_UIC_MASK ) +ufshcd_uic_cmd_compl (hba, intr_status);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);
drivers/scsi/ufs/ufshcd.h +26 -0
@@ -156,6 +156,7 @@ struct ufs_query {* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @feh_workq: Work queue for fatal controller error handling
@@ -195,6 +196,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;
@@ -221,6 +224,9 @@ extern int ufshcd_dme_xxx_set(struct ufs_hba *hba, u32 attr_sel, u8 attr_set, u32 mib_val, u8 peer);extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter); +extern int ufshcd_dme_endpt_reset (struct ufs_hba *hba);/** * ufshcd_hba_stop - Send controller to reset state
@@ -256,4 +262,24 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, return ufshcd_dme_xxx_get(hba, attr_sel, mib_val, 1); } +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,0 ); +} +#endif /* End of Header */
drivers/scsi/ufs/ufshci.h +15 -0
@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\
@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0
Signature · 1 line
1.7.0.4
Re: [PATCH v3 6/6] scsi: ufs: add dme control primitives
Quoted 66 lines
/**
+ *ufshcd_dme_power_xxx- UIC command forDME_POWERON,DME_POWEROFF
+ * @hba: per adapter instance
+ * @on: indicate wherterpower_onorpower_off
+ *
+ * Returns 0 on success, non-zero value on failure
+ */drivers/scsi/ufs/ufshcd.c +59
-0+int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-power-off" , +"dme-power-on" + }; +const char *power = action[!!on]; +int ret; + + uic_cmd.command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: error code %d\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* @enter: indicate wherter hibernation enter or exit +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-hibernate-exit" , +"dme-hibernate-enter" + }; +const char *hibern8 = action[!!enter]; +u8 status; +int ret; + + uic_cmd.command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + +mutex_lock (&hba->uic_cmd_mutex); +init_completion (&hba->hibern8_done); + ret =__ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: error code %d\n" , hibern8, ret); + goto out; + } + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + }
drivers/scsi/ufs/ufshcd.c int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel, · line 1242
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +10
-0+ }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +mutex_unlock (&hba->uic_cmd_mutex); +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); +
power/hibernate functions can also be renamed as ufshcd_dme_power/hibernate_config(struct ufs_hba *hba, bool enable/enter) or similar instead of xxx.
Signature · 1 line
~Santosh
RE: [PATCH v3 6/6] scsi: ufs: add dme control primitives
Quoted 73 lines · Santosh Y
Quoted 73 lines
/**
+ *ufshcd_dme_power_xxx- UIC command forDME_POWERON,DME_POWEROFF
+ * @hba: per adapter instance
+ * @on: indicate wherterpower_onorpower_off
+ *
+ * Returns 0 on success, non-zero value on failure
+ */drivers/scsi/ufs/ufshcd.c +66
-0+int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-power-off" , +"dme-power-on" + }; +const char *power = action[!!on]; +int ret; + + uic_cmd.command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: error code %d\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* @enter: indicate wherter hibernation enter or exit +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-hibernate-exit" , +"dme-hibernate-enter" + }; +const char *hibern8 = action[!!enter]; +u8 status; +int ret; + + uic_cmd.command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + +mutex_lock (&hba->uic_cmd_mutex); +init_completion (&hba->hibern8_done); + ret =__ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: error code %d\n" , hibern8, ret); + goto out; + } + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +mutex_unlock (&hba->uic_cmd_mutex); +return ret;
Quoted 8 lines
drivers/scsi/ufs/ufshcd.c int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel, · line 1242
Quoted 3 lines
drivers/scsi/ufs/ufshcd.c +3
-0+} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); +power/hibernate functions can also be renamed as ufshcd_dme_power/hibernate_config(struct
ufs_hba*hba, bool enable/enter) or similar instead of xxx.
Ok, I'll change the names including dme_get/set.
If you have further views, please let me know.
Thanks,
Seungwon Jeon
Quoted 8 lines
--
~Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v4 1/6 scsi: ufs: wrap the i/o access operations
In reply to Seungwon JeonSimplify operations with hiding mmio_base.
--- drivers/scsi/ufs/ufshcd.c | 105 +++++++++++++++++++-------------------------- drivers/scsi/ufs/ufshcd.h | 7 +++- 2 files changed, 50 insertions(+), 62 deletions(-)
drivers/scsi/ufs/ufshcd.c +44 -61
@@ -71,7 +71,7 @@ enum {*/ static inline u32 ufshcd_get_ufs_version (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UFS_VERSION ); +return ufshcd_readl (hba,REG_UFS_VERSION ); }/**
@@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(struct ufs_hba *hba)*/ static inline void ufshcd_utrl_clear (struct ufs_hba *hba,u32 pos) { -writel (~(1 << pos), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_CLEAR )); +ufshcd_writel (hba, ~(1 << pos),REG_UTP_TRANSFER_REQ_LIST_CLEAR ); }/**
@@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)*/ static inline int ufshcd_get_uic_cmd_result (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UIC_COMMAND_ARG_2 ) & +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_2 ) &MASK_UIC_COMMAND_RESULT ; }
@@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option) {switch (option) {case INT_AGGR_RESET : -writel ((INT_AGGR_ENABLE | -INT_AGGR_COUNTER_AND_TIMER_RESET ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE | +INT_AGGR_COUNTER_AND_TIMER_RESET , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ;case INT_AGGR_CONFIG : -writel ((INT_AGGR_ENABLE | -INT_AGGR_PARAM_WRITE | -INT_AGGR_COUNTER_THRESHOLD_VALUE | -INT_AGGR_TIMEOUT_VALUE ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE |INT_AGGR_PARAM_WRITE | +INT_AGGR_COUNTER_THRESHOLD_VALUE | +INT_AGGR_TIMEOUT_VALUE , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ; } }
@@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)*/ static void ufshcd_enable_run_stop_reg (struct ufs_hba *hba) { -writel (UTP_TASK_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TASK_REQ_LIST_RUN_STOP )); -writel (UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_LIST_RUN_STOP )); +ufshcd_writel (hba,UTP_TASK_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TASK_REQ_LIST_RUN_STOP ); +ufshcd_writel (hba,UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TRANSFER_REQ_LIST_RUN_STOP ); }/**
@@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)*/ static inline void ufshcd_hba_start (struct ufs_hba *hba) { -writel (CONTROLLER_ENABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_ENABLE ,REG_CONTROLLER_ENABLE ); }/**
@@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)*/ static inline int ufshcd_is_hba_active (struct ufs_hba *hba) { -return (readl (hba->mmio_base +REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; +return (ufshcd_readl (hba,REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; }/**
@@ -299,8 +293,7 @@ static inlinevoid ufshcd_send_command (struct ufs_hba *hba,unsigned int task_tag) {__set_bit (task_tag, &hba->outstanding_reqs); -writel ((1 << task_tag), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << task_tag,REG_UTP_TRANSFER_REQ_DOOR_BELL ); }/**
@@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)*/ static inline void ufshcd_hba_capabilities (struct ufs_hba *hba) { - hba->capabilities = -readl (hba->mmio_base +REG_CONTROLLER_CAPABILITIES ); + hba->capabilities =ufshcd_readl (hba,REG_CONTROLLER_CAPABILITIES );/* nutrs and nutmrs are 0 based values */ hba->nutrs = (hba->capabilities &MASK_TRANSFER_REQUESTS_SLOTS ) +1 ;
@@ -399,16 +391,13 @@ static inline void ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd) {/* Write Args */ - writel(uic_cmnd->argument1, - (hba->mmio_base + REG_UIC_COMMAND_ARG_1)); -writel (uic_cmnd->argument2, - (hba->mmio_base +REG_UIC_COMMAND_ARG_2 )); -writel (uic_cmnd->argument3, - (hba->mmio_base +REG_UIC_COMMAND_ARG_3 )); + ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1); +ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -writel ((uic_cmnd->command &COMMAND_OPCODE_MASK ), - (hba->mmio_base +REG_UIC_COMMAND )); +ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +REG_UIC_COMMAND ); }/**
@@ -460,16 +449,15 @@ static void ufshcd_int_config(struct ufs_hba *hba, u32 option) {switch (option) {case UFSHCD_INT_ENABLE : -writel (hba->int_enable_mask, - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE );break ;case UFSHCD_INT_DISABLE :if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (INTERRUPT_DISABLE_MASK_10 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , +REG_INTERRUPT_ENABLE );else -writel (INTERRUPT_DISABLE_MASK_11 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , +REG_INTERRUPT_ENABLE );break ; } }
@@ -940,7 +928,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)unsigned long flags;/* check if controller is ready to accept UIC commands */ -if (((readl (hba->mmio_base +REG_CONTROLLER_STATUS )) & +if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) ==0x0 ) {dev_err (hba->dev, "Controller not ready"
@@ -985,7 +973,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)u32 reg;/* check if device present */ - reg =readl ((hba->mmio_base +REG_CONTROLLER_STATUS )); + reg =ufshcd_readl (hba,REG_CONTROLLER_STATUS );if (!ufshcd_is_device_present (reg)) {dev_err (hba->dev,"cc: Device not present\n" ); err = -ENXIO ;
@@ -1107,14 +1095,14 @@ static int ufshcd_initialize_hba(struct ufs_hba *hba)return -EIO ;/* Configure UTRL and UTMRL base address registers */ -writel (lower_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_H )); -writel (lower_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_H )); +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H );/* Initialize unipro link startup procedure */ return ufshcd_dme_link_startup (hba);
@@ -1427,8 +1415,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)int index; lrb = hba->lrb; - tr_doorbell = -readl (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL ); + tr_doorbell =ufshcd_readl (hba,REG_UTP_TRANSFER_REQ_DOOR_BELL ); completed_reqs = tr_doorbell ^ hba->outstanding_reqs;for (index =0 ; index < hba->nutrs; index++) {
@@ -1502,9 +1489,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba) goto fatal_eh;if (hba->errors &UIC_ERROR ) { - - reg =readl (hba->mmio_base + -REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER ); + reg =ufshcd_readl (hba,REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER );if (reg &UIC_DATA_LINK_LAYER_ERROR_PA_INIT ) goto fatal_eh; }
@@ -1522,7 +1507,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba) {u32 tm_doorbell; - tm_doorbell =readl (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL ); + tm_doorbell =ufshcd_readl (hba,REG_UTP_TASK_REQ_DOOR_BELL ); hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;wake_up_interruptible (&hba->ufshcd_tm_wait_queue); }
@@ -1563,15 +1548,14 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)struct ufs_hba *hba = __hba;spin_lock (hba->host->host_lock); - intr_status =readl (hba->mmio_base +REG_INTERRUPT_STATUS ); + intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) {ufshcd_sl_intr (hba, intr_status);/* If UFSHCI 1.0 then clear interrupt status register */ if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (intr_status, - (hba->mmio_base +REG_INTERRUPT_STATUS )); +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }spin_unlock (hba->host->host_lock);
@@ -1636,8 +1620,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,/* send command to the controller */ __set_bit (free_slot, &hba->outstanding_tasks); -writel ((1 << free_slot), - (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << free_slot,REG_UTP_TASK_REQ_DOOR_BELL );spin_unlock_irqrestore (host->host_lock, flags);
drivers/scsi/ufs/ufshcd.h +6 -1
@@ -204,6 +204,11 @@ struct ufs_hba {struct ufs_query query; }; +#define ufshcd_writel (hba, val, reg) \ + writel((val), (hba)->mmio_base + (reg)) +#define ufshcd_readl (hba, reg) \ + readl((hba)->mmio_base + (reg)) +int ufshcd_init (struct device *,struct ufs_hba ** ,void __iomem * ,unsigned int );void ufshcd_remove (struct ufs_hba *);
@@ -214,7 +219,7 @@ void ufshcd_remove(struct ufs_hba *);*/ static inline void ufshcd_hba_stop (struct ufs_hba *hba) { -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_DISABLE ,REG_CONTROLLER_ENABLE ); }#endif /* End of Header */
Signature · 1 line
1.7.0.4
Re: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations
Hi,
I tested the new set of patches (v4 1-6) and it works.
Thanks,
Maya
Quoted 313 lines
Simplify operations with hiding
mmio_base.Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 105 +++++++++++++++++++-------------------------- drivers/scsi/ufs/ufshcd.h | 7 +++- 2 files changed, 50 insertions(+), 62 deletions(-)drivers/scsi/ufs/ufshcd.c +2
-3@@ -71,7 +71,7 @@ enum {*/ static inline u32 ufshcd_get_ufs_version (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UFS_VERSION ); +return ufshcd_readl (hba,REG_UFS_VERSION ); }/** @@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(structufs_hba *hba) */ static inline void ufshcd_utrl_clear (struct ufs_hba *hba,u32 pos) { -writel (~(1 << pos), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_CLEAR )); +ufshcd_writel (hba, ~(1 << pos),REG_UTP_TRANSFER_REQ_LIST_CLEAR ); }/**
drivers/scsi/ufs/ufshcd.c +8
-11@@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)*/ static inline int ufshcd_get_uic_cmd_result (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UIC_COMMAND_ARG_2 ) & +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_2 ) &MASK_UIC_COMMAND_RESULT ; }@@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option) {switch (option) {case INT_AGGR_RESET : -writel ((INT_AGGR_ENABLE | -INT_AGGR_COUNTER_AND_TIMER_RESET ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE | +INT_AGGR_COUNTER_AND_TIMER_RESET , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ;case INT_AGGR_CONFIG : -writel ((INT_AGGR_ENABLE | -INT_AGGR_PARAM_WRITE | -INT_AGGR_COUNTER_THRESHOLD_VALUE | -INT_AGGR_TIMEOUT_VALUE ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE |INT_AGGR_PARAM_WRITE | +INT_AGGR_COUNTER_THRESHOLD_VALUE | +INT_AGGR_TIMEOUT_VALUE , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ; }}
drivers/scsi/ufs/ufshcd.c +4
-6@@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, intoption) */ static void ufshcd_enable_run_stop_reg (struct ufs_hba *hba) { -writel (UTP_TASK_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TASK_REQ_LIST_RUN_STOP )); -writel (UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_LIST_RUN_STOP )); +ufshcd_writel (hba,UTP_TASK_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TASK_REQ_LIST_RUN_STOP ); +ufshcd_writel (hba,UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TRANSFER_REQ_LIST_RUN_STOP ); }/**
drivers/scsi/ufs/ufshcd.c +1
-1@@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba*hba) */ static inline void ufshcd_hba_start (struct ufs_hba *hba) { -writel (CONTROLLER_ENABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_ENABLE ,REG_CONTROLLER_ENABLE ); }/**
drivers/scsi/ufs/ufshcd.c +1
-1@@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba*hba) */ static inline int ufshcd_is_hba_active (struct ufs_hba *hba) { -return (readl (hba->mmio_base +REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; +return (ufshcd_readl (hba,REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; }/**
drivers/scsi/ufs/ufshcd.c +2
-4@@ -299,8 +293,7 @@ static inlinevoid ufshcd_send_command (struct ufs_hba *hba,unsigned int task_tag) {__set_bit (task_tag, &hba->outstanding_reqs); -writel ((1 << task_tag), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << task_tag,REG_UTP_TRANSFER_REQ_DOOR_BELL ); }/** @@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba,struct ufshcd_lrb *lrbp) */ static inline void ufshcd_hba_capabilities (struct ufs_hba *hba) { - hba->capabilities = -readl (hba->mmio_base +REG_CONTROLLER_CAPABILITIES ); + hba->capabilities =ufshcd_readl (hba,REG_CONTROLLER_CAPABILITIES );/* nutrs and nutmrs are 0 based values */ drivers/scsi/ufs/ufshcd.c +5
-8hba->nutrs = (hba->capabilities &MASK_TRANSFER_REQUESTS_SLOTS ) +1 ;@@ -399,16 +391,13 @@ static inline void ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd) {/* Write Args */ - writel(uic_cmnd->argument1, - (hba->mmio_base + REG_UIC_COMMAND_ARG_1)); -writel (uic_cmnd->argument2, - (hba->mmio_base +REG_UIC_COMMAND_ARG_2 )); -writel (uic_cmnd->argument3, - (hba->mmio_base +REG_UIC_COMMAND_ARG_3 )); + ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1); +ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -writel ((uic_cmnd->command &COMMAND_OPCODE_MASK ), - (hba->mmio_base +REG_UIC_COMMAND )); +ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +REG_UIC_COMMAND ); }/**
drivers/scsi/ufs/ufshcd.c +5
-6@@ -460,16 +449,15 @@ static void ufshcd_int_config(struct ufs_hba *hba, u32 option) {switch (option) {case UFSHCD_INT_ENABLE : -writel (hba->int_enable_mask, - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE );break ;case UFSHCD_INT_DISABLE :if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (INTERRUPT_DISABLE_MASK_10 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , +REG_INTERRUPT_ENABLE );else -writel (INTERRUPT_DISABLE_MASK_11 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , +REG_INTERRUPT_ENABLE );break ; }}
drivers/scsi/ufs/ufshcd.c +1
-1@@ -940,7 +928,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)unsigned long flags;/* check if controller is ready to accept UIC commands */ -if (((readl (hba->mmio_base +REG_CONTROLLER_STATUS )) & +if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) ==0x0 ) { dev_err(hba->dev,drivers/scsi/ufs/ufshcd.c +1
-1"Controller not ready" @@ -985,7 +973,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)u32 reg;/* check if device present */ - reg =readl ((hba->mmio_base +REG_CONTROLLER_STATUS )); + reg =ufshcd_readl (hba,REG_CONTROLLER_STATUS );if (!ufshcd_is_device_present (reg)) {dev_err (hba->dev,"cc: Device not present\n" );drivers/scsi/ufs/ufshcd.c +8
-8err = -ENXIO ;@@ -1107,14 +1095,14 @@ static int ufshcd_initialize_hba(struct ufs_hba *hba)return -EIO ;/* Configure UTRL and UTMRL base address registers */ -writel (lower_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_H )); -writel (lower_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_H )); +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H );/* Initialize unipro link startup procedure */ drivers/scsi/ufs/ufshcd.c +1
-2return ufshcd_dme_link_startup (hba);@@ -1427,8 +1415,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)int index; lrb = hba->lrb; - tr_doorbell = -readl (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL ); + tr_doorbell =ufshcd_readl (hba,REG_UTP_TRANSFER_REQ_DOOR_BELL ); completed_reqs = tr_doorbell ^ hba->outstanding_reqs;drivers/scsi/ufs/ufshcd.c +4
-7for (index =0 ; index < hba->nutrs; index++) {@@ -1502,9 +1489,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba) goto fatal_eh;if (hba->errors &UIC_ERROR ) { - - reg =readl (hba->mmio_base + -REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER ); + reg =ufshcd_readl (hba,REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER );if (reg &UIC_DATA_LINK_LAYER_ERROR_PA_INIT ) goto fatal_eh; }@@ -1522,7 +1507,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba) {u32 tm_doorbell; - tm_doorbell =readl (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL ); + tm_doorbell =ufshcd_readl (hba,REG_UTP_TASK_REQ_DOOR_BELL ); hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;wake_up_interruptible (&hba->ufshcd_tm_wait_queue); }@@ -1563,15 +1548,14 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)struct ufs_hba *hba = __hba;spin_lock (hba->host->host_lock); - intr_status =readl (hba->mmio_base +REG_INTERRUPT_STATUS ); + intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) {ufshcd_sl_intr (hba, intr_status);/* If UFSHCI 1.0 then clear interrupt status register */ if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (intr_status, - (hba->mmio_base +REG_INTERRUPT_STATUS )); +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }drivers/scsi/ufs/ufshcd.c +1
-2spin_unlock (hba->host->host_lock);@@ -1636,8 +1620,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,/* send command to the controller */ __set_bit (free_slot, &hba->outstanding_tasks); -writel ((1 << free_slot), - (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << free_slot,REG_UTP_TASK_REQ_DOOR_BELL );spin_unlock_irqrestore (host->host_lock, flags);drivers/scsi/ufs/ufshcd.h +6
-2@@ -204,6 +204,11 @@ struct ufs_hba {struct ufs_query query; }; +#define ufshcd_writel (hba, val, reg) \ + writel((val), (hba)->mmio_base + (reg)) +#define ufshcd_readl (hba, reg) \ + readl((hba)->mmio_base + (reg)) +int ufshcd_init (struct device *,struct ufs_hba ** ,void __iomem * ,unsigned int );void ufshcd_remove (struct ufs_hba *);@@ -214,7 +219,7 @@ void ufshcd_remove(struct ufs_hba *);*/ static inline void ufshcd_hba_stop (struct ufs_hba *hba) { -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_DISABLE ,REG_CONTROLLER_ENABLE ); }#endif /* End of Header */ --1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations
In reply to Seungwon JeonQuoted 291 lines · Seungwon Jeon
Simplify operations with hiding
mmio_base.Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 105 +++++++++++++++++++-------------------------- drivers/scsi/ufs/ufshcd.h | 7 +++- 2 files changed, 50 insertions(+), 62 deletions(-)drivers/scsi/ufs/ufshcd.c +44
-61@@ -71,7 +71,7 @@ enum {*/ static inline u32 ufshcd_get_ufs_version (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UFS_VERSION ); +return ufshcd_readl (hba,REG_UFS_VERSION ); }/** @@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(struct ufs_hba *hba)*/ static inline void ufshcd_utrl_clear (struct ufs_hba *hba,u32 pos) { -writel (~(1 << pos), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_CLEAR )); +ufshcd_writel (hba, ~(1 << pos),REG_UTP_TRANSFER_REQ_LIST_CLEAR ); }/** @@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)*/ static inline int ufshcd_get_uic_cmd_result (struct ufs_hba *hba) { -return readl (hba->mmio_base +REG_UIC_COMMAND_ARG_2 ) & +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_2 ) &MASK_UIC_COMMAND_RESULT ; }@@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option) {switch (option) {case INT_AGGR_RESET : -writel ((INT_AGGR_ENABLE | -INT_AGGR_COUNTER_AND_TIMER_RESET ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE | +INT_AGGR_COUNTER_AND_TIMER_RESET , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ;case INT_AGGR_CONFIG : -writel ((INT_AGGR_ENABLE | -INT_AGGR_PARAM_WRITE | -INT_AGGR_COUNTER_THRESHOLD_VALUE | -INT_AGGR_TIMEOUT_VALUE ), - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL )); +ufshcd_writel (hba,INT_AGGR_ENABLE |INT_AGGR_PARAM_WRITE | +INT_AGGR_COUNTER_THRESHOLD_VALUE | +INT_AGGR_TIMEOUT_VALUE , +REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL );break ; } }@@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)*/ static void ufshcd_enable_run_stop_reg (struct ufs_hba *hba) { -writel (UTP_TASK_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TASK_REQ_LIST_RUN_STOP )); -writel (UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , - (hba->mmio_base + -REG_UTP_TRANSFER_REQ_LIST_RUN_STOP )); +ufshcd_writel (hba,UTP_TASK_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TASK_REQ_LIST_RUN_STOP ); +ufshcd_writel (hba,UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT , +REG_UTP_TRANSFER_REQ_LIST_RUN_STOP ); }/** @@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)*/ static inline void ufshcd_hba_start (struct ufs_hba *hba) { -writel (CONTROLLER_ENABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_ENABLE ,REG_CONTROLLER_ENABLE ); }/** @@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)*/ static inline int ufshcd_is_hba_active (struct ufs_hba *hba) { -return (readl (hba->mmio_base +REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; +return (ufshcd_readl (hba,REG_CONTROLLER_ENABLE ) &0x1 ) ?0 :1 ; }/** @@ -299,8 +293,7 @@ static inlinevoid ufshcd_send_command (struct ufs_hba *hba,unsigned int task_tag) {__set_bit (task_tag, &hba->outstanding_reqs); -writel ((1 << task_tag), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << task_tag,REG_UTP_TRANSFER_REQ_DOOR_BELL ); }/** @@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)*/ static inline void ufshcd_hba_capabilities (struct ufs_hba *hba) { - hba->capabilities = -readl (hba->mmio_base +REG_CONTROLLER_CAPABILITIES ); + hba->capabilities =ufshcd_readl (hba,REG_CONTROLLER_CAPABILITIES );/* nutrs and nutmrs are 0 based values */ hba->nutrs = (hba->capabilities &MASK_TRANSFER_REQUESTS_SLOTS ) +1 ;@@ -399,16 +391,13 @@ static inline void ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd) {/* Write Args */ - writel(uic_cmnd->argument1, - (hba->mmio_base + REG_UIC_COMMAND_ARG_1)); -writel (uic_cmnd->argument2, - (hba->mmio_base +REG_UIC_COMMAND_ARG_2 )); -writel (uic_cmnd->argument3, - (hba->mmio_base +REG_UIC_COMMAND_ARG_3 )); + ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1); +ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -writel ((uic_cmnd->command &COMMAND_OPCODE_MASK ), - (hba->mmio_base +REG_UIC_COMMAND )); +ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +REG_UIC_COMMAND ); }/** @@ -460,16 +449,15 @@ static void ufshcd_int_config(struct ufs_hba *hba, u32 option) {switch (option) {case UFSHCD_INT_ENABLE : -writel (hba->int_enable_mask, - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE );break ;case UFSHCD_INT_DISABLE :if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (INTERRUPT_DISABLE_MASK_10 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , +REG_INTERRUPT_ENABLE );else -writel (INTERRUPT_DISABLE_MASK_11 , - (hba->mmio_base +REG_INTERRUPT_ENABLE )); +ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , +REG_INTERRUPT_ENABLE );break ; } }@@ -940,7 +928,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)unsigned long flags;/* check if controller is ready to accept UIC commands */ -if (((readl (hba->mmio_base +REG_CONTROLLER_STATUS )) & +if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) ==0x0 ) {dev_err (hba->dev, "Controller not ready"@@ -985,7 +973,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)u32 reg;/* check if device present */ - reg =readl ((hba->mmio_base +REG_CONTROLLER_STATUS )); + reg =ufshcd_readl (hba,REG_CONTROLLER_STATUS );if (!ufshcd_is_device_present (reg)) {dev_err (hba->dev,"cc: Device not present\n" ); err = -ENXIO ;@@ -1107,14 +1095,14 @@ static int ufshcd_initialize_hba(struct ufs_hba *hba)return -EIO ;/* Configure UTRL and UTMRL base address registers */ -writel (lower_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utrdl_dma_addr), - (hba->mmio_base +REG_UTP_TRANSFER_REQ_LIST_BASE_H )); -writel (lower_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_L )); -writel (upper_32_bits (hba->utmrdl_dma_addr), - (hba->mmio_base +REG_UTP_TASK_REQ_LIST_BASE_H )); +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H );/* Initialize unipro link startup procedure */ return ufshcd_dme_link_startup (hba);@@ -1427,8 +1415,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)int index; lrb = hba->lrb; - tr_doorbell = -readl (hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL ); + tr_doorbell =ufshcd_readl (hba,REG_UTP_TRANSFER_REQ_DOOR_BELL ); completed_reqs = tr_doorbell ^ hba->outstanding_reqs;for (index =0 ; index < hba->nutrs; index++) {@@ -1502,9 +1489,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba) goto fatal_eh;if (hba->errors &UIC_ERROR ) { - - reg =readl (hba->mmio_base + -REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER ); + reg =ufshcd_readl (hba,REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER );if (reg &UIC_DATA_LINK_LAYER_ERROR_PA_INIT ) goto fatal_eh; }@@ -1522,7 +1507,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba) {u32 tm_doorbell; - tm_doorbell =readl (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL ); + tm_doorbell =ufshcd_readl (hba,REG_UTP_TASK_REQ_DOOR_BELL ); hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;wake_up_interruptible (&hba->ufshcd_tm_wait_queue); }@@ -1563,15 +1548,14 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)struct ufs_hba *hba = __hba;spin_lock (hba->host->host_lock); - intr_status =readl (hba->mmio_base +REG_INTERRUPT_STATUS ); + intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) {ufshcd_sl_intr (hba, intr_status);/* If UFSHCI 1.0 then clear interrupt status register */ if (hba->ufs_version ==UFSHCI_VERSION_10 ) -writel (intr_status, - (hba->mmio_base +REG_INTERRUPT_STATUS )); +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }spin_unlock (hba->host->host_lock);@@ -1636,8 +1620,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,/* send command to the controller */ __set_bit (free_slot, &hba->outstanding_tasks); -writel ((1 << free_slot), - (hba->mmio_base +REG_UTP_TASK_REQ_DOOR_BELL )); +ufshcd_writel (hba,1 << free_slot,REG_UTP_TASK_REQ_DOOR_BELL );spin_unlock_irqrestore (host->host_lock, flags);drivers/scsi/ufs/ufshcd.h +6
-2@@ -204,6 +204,11 @@ struct ufs_hba {struct ufs_query query; }; +#define ufshcd_writel (hba, val, reg) \ + writel((val), (hba)->mmio_base + (reg)) +#define ufshcd_readl (hba, reg) \ + readl((hba)->mmio_base + (reg)) +int ufshcd_init (struct device *,struct ufs_hba ** ,void __iomem * ,unsigned int );void ufshcd_remove (struct ufs_hba *);@@ -214,7 +219,7 @@ void ufshcd_remove(struct ufs_hba *);*/ static inline void ufshcd_hba_stop (struct ufs_hba *hba) { -writel (CONTROLLER_DISABLE , (hba->mmio_base +REG_CONTROLLER_ENABLE )); +ufshcd_writel (hba,CONTROLLER_DISABLE ,REG_CONTROLLER_ENABLE ); }#endif /* End of Header */ --
Quoted 2 lines
1.7.0.4
Hi Seungwon,
I could apply your test patch without any issues but I still get "fatal: cannot convert from ks_c_5601-1987 to UTF-8" with V4 patch series.
At this point I'm confused :-| not sure if the problem is the character set or something else...
Hi James,
Please consider Acked-by: Santosh Y <[email protected]>, if you are able to apply the patches.
Signature · 1 line
~Santosh
RE: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations
Quoted 10 lines · Santosh Y
Quoted 9 lines · Seungwon Jeon
Simplify operations with hiding
mmio_base.Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 105 +++++++++++++++++++-------------------------- drivers/scsi/ufs/ufshcd.h | 7 +++- 2 files changed, 50 insertions(+), 62 deletions(-)
Quoted 6 lines
Hi Seungwon,
I could apply your test patch without any issues but I still get "fatal: cannot convert from ks_c_5601-1987 to UTF-8" with V4 patch series.
At this point I'm confused :-| not sure if the problem is the character set or something else...
Hi Santosh,
You got a pass with my test one before v4. It's strange.
Hi James,
Please let me know, if you have a same problem.
I guess I should change mail sender.
Quoted 5 lines
Hi James,
Please consider Acked-by: Santosh Y <[email protected]>, if you are able to apply the patches.
Thank you for your ack.
There are two patches remained. These are applied with your final comments. Do you have any idea?
[PATCH v4 5/6] scsi: ufs: add dme configuration primitives [PATCH v4 6/6] scsi: ufs: add dme control primitives
Thanks,
Seungwon Jeon
Re: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations
Quoted 5 lines
There are two patches remained. These are applied with your final comments. Do you have any idea?
[PATCH v4 5/6] scsi: ufs: add dme configuration primitives [PATCH v4 6/6] scsi: ufs: add dme control primitives
Since there is no use case for these implementations yet, except for ufshcd_get_dme_attr_val(), as per James's suggestion
[http://www.mail-archive.com/[email protected]/msg20207.html]
I did not ACK the patches.
The same patches can be used to implement related features and resubmit later.
Signature · 1 line
~Santosh
RE: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations
Quoted 11 lines · On Thursday, May 09, 2013 Santosh wrote:
Quoted 5 lines
There are two patches remained. These are applied with your final comments. Do you have any idea?
[PATCH v4 5/6] scsi: ufs: add dme configuration primitives [PATCH v4 6/6] scsi: ufs: add dme control primitivesSince there is no use case for these implementations yet, except for
ufshcd_get_dme_attr_val(), as per James's suggestion
[http://www.mail-archive.com/[email protected]/msg20207.html]
I did not ACK the patches.
The same patches can be used to implement related features and resubmit later.
I respect your decision. But I have another opinion.
The remained patches are basic operations which should be supported by ufshcd.
Especially, dme_set/set will be used in vender specific part of host controller rather than in ufshcd itself. And above all, Maya Erez completed to test and reported working fine.
If these patches are merged this time, it would be helpful to various hosts.
Thanks,
Seungwon Jeon
Quoted 7 lines
--
~Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations
Quoted 12 lines · Seungwon Jeon
Quoted 11 lines · On Thursday, May 09, 2013 Santosh wrote:
Quoted 5 lines
There are two patches remained. These are applied with your final comments. Do you have any idea?
[PATCH v4 5/6] scsi: ufs: add dme configuration primitives [PATCH v4 6/6] scsi: ufs: add dme control primitivesSince there is no use case for these implementations yet, except for
ufshcd_get_dme_attr_val(), as per James's suggestion
[http://www.mail-archive.com/[email protected]/msg20207.html]
I did not ACK the patches.
The same patches can be used to implement related features and resubmit later.
Quoted 6 lines
I respect your decision. But I have another opinion.
The remained patches are basic operations which should be supported by ufshcd.
Especially, dme_set/set will be used in vender specific part of host controller rather than in ufshcd itself. And above all, Maya Erez completed to test and reported working fine.
If these patches are merged this time, it would be helpful to various hosts.
I'm ok with merging these patches if James is fine with it. I will ACK the patches.
Signature · 1 line
~Santosh
James Bottomley
maintainerRe: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations
Quoted 20 lines · Santosh Y
Quoted 12 lines · Seungwon Jeon
Quoted 11 lines · On Thursday, May 09, 2013 Santosh wrote:
Quoted 5 lines
There are two patches remained. These are applied with your final comments. Do you have any idea?
[PATCH v4 5/6] scsi: ufs: add dme configuration primitives [PATCH v4 6/6] scsi: ufs: add dme control primitivesSince there is no use case for these implementations yet, except for
ufshcd_get_dme_attr_val(), as per James's suggestion
[http://www.mail-archive.com/[email protected]/msg20207.html]
I did not ACK the patches.
The same patches can be used to implement related features and resubmit later.Quoted 6 lines
I respect your decision. But I have another opinion.
The remained patches are basic operations which should be supported by ufshcd.
Especially, dme_set/set will be used in vender specific part of host controller rather than in ufshcd itself. And above all, Maya Erez completed to test and reported working fine.
If these patches are merged this time, it would be helpful to various hosts.
Quoted 2 lines
I'm ok with merging these patches if James is fine with it. I will ACK the patches.
Well, no, not really. The rule is simple: we don't add new functions to the kernel without callers. The reason is also simple: trying to do interface first and then user some time later is a "make work" development strategy that practically guarantees the interface is either never used or needs modification. From the kernel's point of view, which is more important, review of a function with no callers is only partial because you've no idea how it will be used. Whereas if you review a function and its callers, you can see how the API works and possibly suggest improvements.
James
RE: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations
Quoted 25 lines · James Bottomley
Quoted 8 lines · Santosh Y
Quoted 7 lines · Seungwon Jeon
Quoted 6 lines · On Thursday, May 09, 2013 Santosh wrote:
Quoted 5 lines
There are two patches remained. These are applied with your final comments. Do you have any idea?
[PATCH v4 5/6] scsi: ufs: add dme configuration primitives [PATCH v4 6/6] scsi: ufs: add dme control primitivesQuoted 8 lines
Quoted 8 lines
Quoted 5 lines
Since there is no use case for these implementations yet, except for
ufshcd_get_dme_attr_val(), as per James's suggestion
[http://www.mail-archive.com/[email protected]/msg20207.html]
I did not ACK the patches.
The same patches can be used to implement related features and resubmit later.I respect your decision. But I have another opinion.
The remained patches are basic operations which should be supported by ufshcd. Especially, dme_set/set will be used in vender specific part of host controller rather than inufshcd itself.
Quoted 6 lines
Quoted 3 lines
And above all, Maya Erez completed to test and reported working fine. If these patches are merged this time, it would be helpful to various hosts.
I'm ok with merging these patches if James is fine with it. I will ACK the patches.
Quoted 9 lines
Well, no, not really. The rule is simple: we don't add new functions to the kernel without callers. The reason is also simple: trying to do interface first and then user some time later is a "make work" development strategy that practically guarantees the interface is either never used or needs modification. From the kernel's point of view, which is more important, review of a function with no callers is only partial because you've no idea how it will be used. Whereas if you review a function and its callers, you can see how the API works and possibly suggest improvements.
Thank you for your feedback.
Okay, it will be reintroduced with actual usage soon. Could you pick the remains except [5/6, 6/6] into your tree? The following patches include Santosh's ack. [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations [PATCH v4 2/6] scsi: ufs: amend interrupt configuration [PATCH v4 3/6] scsi: ufs: fix interrupt status clears [PATCH v4 4/6] scsi: ufs: rework link start-up process
Thanks,
Seungwon Jeon
Quoted 9 lines
James
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v4 2/6 scsi: ufs: amend interrupt configuration
In reply to Seungwon JeonIt makes interrupt setting more flexible especially for disabling. And wrong bit mask is fixed for ver 1.0. [17:16] is added for mask.
--- drivers/scsi/ufs/ufshcd.c | 84 +++++++++++++++++++++++++++++++------------- drivers/scsi/ufs/ufshcd.h | 4 +- drivers/scsi/ufs/ufshci.h | 5 ++- 3 files changed, 64 insertions(+), 29 deletions(-)
drivers/scsi/ufs/ufshcd.c +59 -25
@@ -35,6 +35,10 @@#include "ufshcd.h" +#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ + UTP_TASK_REQ_COMPL |\ + UFSHCD_ERROR_MASK) +enum {UFSHCD_MAX_CHANNEL =0 ,UFSHCD_MAX_ID =1 ,
@@ -64,6 +68,20 @@ enum { };/** +* ufshcd_get_intr_mask - Get the interrupt bit mask +* @hba - Pointer to adapter instance +* +* Returns interrupt bit mask per version +*/ +static inline u32 ufshcd_get_intr_mask (struct ufs_hba *hba) +{ +if (hba->ufs_version ==UFSHCI_VERSION_10 ) +return INTERRUPT_MASK_ALL_VER_10 ; +else +return INTERRUPT_MASK_ALL_VER_11 ; +} + +/** * ufshcd_get_ufs_version - Get the UFS version supported by the HBA * @hba - Pointer to adapter instance *
@@ -441,25 +459,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp) }/** -* ufshcd_int_config - enable/disable interrupts +* ufshcd_enable_intr - enable interrupts * @hba: per adapter instance -* @option: interrupt option +* @intrs: interrupt bits */ -static void ufshcd_int_config (struct ufs_hba *hba,u32 option) +static void ufshcd_enable_intr (struct ufs_hba *hba,u32 intrs) { -switch (option) { -case UFSHCD_INT_ENABLE : -ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE ); -break ; -case UFSHCD_INT_DISABLE : -if (hba->ufs_version ==UFSHCI_VERSION_10 ) -ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , -REG_INTERRUPT_ENABLE ); -else -ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , -REG_INTERRUPT_ENABLE ); -break ; +u32 set =ufshcd_readl (hba,REG_INTERRUPT_ENABLE ); + +if (hba->ufs_version ==UFSHCI_VERSION_10 ) { +u32 rw; + rw = set &INTERRUPT_MASK_RW_VER_10 ; + set = rw | ((set ^ intrs) & intrs); + }else { + set |= intrs; + } + +ufshcd_writel (hba, set,REG_INTERRUPT_ENABLE ); +} + +/** +* ufshcd_disable_intr - disable interrupts +* @hba: per adapter instance +* @intrs: interrupt bits +*/ +static void ufshcd_disable_intr (struct ufs_hba *hba,u32 intrs) +{ +u32 set =ufshcd_readl (hba,REG_INTERRUPT_ENABLE ); + +if (hba->ufs_version ==UFSHCI_VERSION_10 ) { +u32 rw; + rw = (set &INTERRUPT_MASK_RW_VER_10 ) & + ~(intrs &INTERRUPT_MASK_RW_VER_10 ); + set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10 ); + + }else { + set &= ~intrs; } + +ufshcd_writel (hba, set,REG_INTERRUPT_ENABLE ); }/**
@@ -946,8 +984,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) uic_cmd->argument3 =0 ;/* enable UIC related interrupts */ - hba->int_enable_mask |=UIC_COMMAND_COMPL ; -ufshcd_int_config (hba,UFSHCD_INT_ENABLE ); +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL );/* sending UIC commands to controller */ ufshcd_send_uic_command (hba, uic_cmd);
@@ -994,13 +1031,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) }/* Enable required interrupts */ - hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL | -UIC_ERROR | -UTP_TASK_REQ_COMPL | -DEVICE_FATAL_ERROR | -CONTROLLER_FATAL_ERROR | -SYSTEM_BUS_FATAL_ERROR ); -ufshcd_int_config (hba,UFSHCD_INT_ENABLE ); +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS );/* Configure interrupt aggregation */ ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG );
@@ -1828,7 +1859,7 @@ static void ufshcd_hba_free(struct ufs_hba *hba)void ufshcd_remove (struct ufs_hba *hba) {/* disable interrupts */ -ufshcd_int_config (hba,UFSHCD_INT_DISABLE ); +ufshcd_disable_intr (hba, hba->intr_mask);ufshcd_hba_stop (hba);ufshcd_hba_free (hba);
@@ -1886,6 +1917,9 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,/* Get UFS version supported by the controller */ hba->ufs_version =ufshcd_get_ufs_version (hba); +/* Get Interrupt bit mask per version */ + hba->intr_mask =ufshcd_get_intr_mask (hba); +/* Allocate memory for host memory space */ err =ufshcd_memory_alloc (hba);if (err) {
drivers/scsi/ufs/ufshcd.h +2 -2
@@ -153,7 +153,7 @@ struct ufs_query {* @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states -* @int_enable_mask: Interrupt Mask Bits +* @intr_mask: Interrupt Mask Bits * @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors
@@ -191,7 +191,7 @@ struct ufs_hba {unsigned long tm_condition;u32 ufshcd_state; -u32 int_enable_mask; +u32 intr_mask;/* Work Queues */ struct work_struct uic_workq;
drivers/scsi/ufs/ufshci.h +3 -2
@@ -232,10 +232,11 @@ enum {/* Interrupt disable masks */ enum {/* Interrupt disable mask for UFSHCI v1.0 */ -INTERRUPT_DISABLE_MASK_10 =0xFFFF , +INTERRUPT_MASK_ALL_VER_10 =0x30FFF , +INTERRUPT_MASK_RW_VER_10 =0x30000 ,/* Interrupt disable mask for UFSHCI v1.1 */ -INTERRUPT_DISABLE_MASK_11 =0x0 , +INTERRUPT_MASK_ALL_VER_11 =0x31FFF , };/*
Signature · 1 line
1.7.0.4
Re: [PATCH v4 2/6] scsi: ufs: amend interrupt configuration
Quoted 194 lines · Seungwon Jeon
It makes interrupt setting more flexible especially for disabling. And wrong bit mask is fixed for ver 1.0. [17:16] is added for mask.
Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 84 +++++++++++++++++++++++++++++++------------- drivers/scsi/ufs/ufshcd.h | 4 +- drivers/scsi/ufs/ufshci.h | 5 ++- 3 files changed, 64 insertions(+), 29 deletions(-)drivers/scsi/ufs/ufshcd.c +59
-25@@ -35,6 +35,10 @@#include "ufshcd.h" +#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ + UTP_TASK_REQ_COMPL |\ + UFSHCD_ERROR_MASK) +enum {UFSHCD_MAX_CHANNEL =0 ,UFSHCD_MAX_ID =1 ,@@ -64,6 +68,20 @@ enum { };/** +* ufshcd_get_intr_mask - Get the interrupt bit mask +* @hba - Pointer to adapter instance +* +* Returns interrupt bit mask per version +*/ +static inline u32 ufshcd_get_intr_mask (struct ufs_hba *hba) +{ +if (hba->ufs_version ==UFSHCI_VERSION_10 ) +return INTERRUPT_MASK_ALL_VER_10 ; +else +return INTERRUPT_MASK_ALL_VER_11 ; +} + +/** * ufshcd_get_ufs_version - Get the UFS version supported by the HBA * @hba - Pointer to adapter instance * @@ -441,25 +459,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp) }/** -* ufshcd_int_config - enable/disable interrupts +* ufshcd_enable_intr - enable interrupts * @hba: per adapter instance -* @option: interrupt option +* @intrs: interrupt bits */ -static void ufshcd_int_config (struct ufs_hba *hba,u32 option) +static void ufshcd_enable_intr (struct ufs_hba *hba,u32 intrs) { -switch (option) { -case UFSHCD_INT_ENABLE : -ufshcd_writel (hba, hba->int_enable_mask,REG_INTERRUPT_ENABLE ); -break ; -case UFSHCD_INT_DISABLE : -if (hba->ufs_version ==UFSHCI_VERSION_10 ) -ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_10 , -REG_INTERRUPT_ENABLE ); -else -ufshcd_writel (hba,INTERRUPT_DISABLE_MASK_11 , -REG_INTERRUPT_ENABLE ); -break ; +u32 set =ufshcd_readl (hba,REG_INTERRUPT_ENABLE ); + +if (hba->ufs_version ==UFSHCI_VERSION_10 ) { +u32 rw; + rw = set &INTERRUPT_MASK_RW_VER_10 ; + set = rw | ((set ^ intrs) & intrs); + }else { + set |= intrs; + } + +ufshcd_writel (hba, set,REG_INTERRUPT_ENABLE ); +} + +/** +* ufshcd_disable_intr - disable interrupts +* @hba: per adapter instance +* @intrs: interrupt bits +*/ +static void ufshcd_disable_intr (struct ufs_hba *hba,u32 intrs) +{ +u32 set =ufshcd_readl (hba,REG_INTERRUPT_ENABLE ); + +if (hba->ufs_version ==UFSHCI_VERSION_10 ) { +u32 rw; + rw = (set &INTERRUPT_MASK_RW_VER_10 ) & + ~(intrs &INTERRUPT_MASK_RW_VER_10 ); + set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10 ); + + }else { + set &= ~intrs; } + +ufshcd_writel (hba, set,REG_INTERRUPT_ENABLE ); }/** @@ -946,8 +984,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) uic_cmd->argument3 =0 ;/* enable UIC related interrupts */ - hba->int_enable_mask |=UIC_COMMAND_COMPL ; -ufshcd_int_config (hba,UFSHCD_INT_ENABLE ); +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL );/* sending UIC commands to controller */ ufshcd_send_uic_command (hba, uic_cmd);@@ -994,13 +1031,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) }/* Enable required interrupts */ - hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL | -UIC_ERROR | -UTP_TASK_REQ_COMPL | -DEVICE_FATAL_ERROR | -CONTROLLER_FATAL_ERROR | -SYSTEM_BUS_FATAL_ERROR ); -ufshcd_int_config (hba,UFSHCD_INT_ENABLE ); +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS );/* Configure interrupt aggregation */ ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG );@@ -1828,7 +1859,7 @@ static void ufshcd_hba_free(struct ufs_hba *hba)void ufshcd_remove (struct ufs_hba *hba) {/* disable interrupts */ -ufshcd_int_config (hba,UFSHCD_INT_DISABLE ); +ufshcd_disable_intr (hba, hba->intr_mask);ufshcd_hba_stop (hba);ufshcd_hba_free (hba);@@ -1886,6 +1917,9 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,/* Get UFS version supported by the controller */ hba->ufs_version =ufshcd_get_ufs_version (hba); +/* Get Interrupt bit mask per version */ + hba->intr_mask =ufshcd_get_intr_mask (hba); +/* Allocate memory for host memory space */ err =ufshcd_memory_alloc (hba);if (err) {drivers/scsi/ufs/ufshcd.h +2
-2@@ -153,7 +153,7 @@ struct ufs_query {* @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states -* @int_enable_mask: Interrupt Mask Bits +* @intr_mask: Interrupt Mask Bits * @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors @@ -191,7 +191,7 @@ struct ufs_hba {unsigned long tm_condition;u32 ufshcd_state; -u32 int_enable_mask; +u32 intr_mask;/* Work Queues */ struct work_struct uic_workq;drivers/scsi/ufs/ufshci.h +3
-3@@ -232,10 +232,11 @@ enum {/* Interrupt disable masks */ enum {/* Interrupt disable mask for UFSHCI v1.0 */ -INTERRUPT_DISABLE_MASK_10 =0xFFFF , +INTERRUPT_MASK_ALL_VER_10 =0x30FFF , +INTERRUPT_MASK_RW_VER_10 =0x30000 ,/* Interrupt disable mask for UFSHCI v1.1 */ -INTERRUPT_DISABLE_MASK_11 =0x0 , +INTERRUPT_MASK_ALL_VER_11 =0x31FFF , };/* --
Quoted 3 lines
1.7.0.4
Signature · 1 line
~Santosh
PATCH v4 3/6 scsi: ufs: fix interrupt status clears
In reply to Seungwon JeonThere is no need to check the version to clear the interrupt status. And the order is changed prior to actual handling.
--- drivers/scsi/ufs/ufshcd.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-)
drivers/scsi/ufs/ufshcd.c +1 -4
@@ -1582,11 +1582,8 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba) intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) { +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS );ufshcd_sl_intr (hba, intr_status); - -/* If UFSHCI 1.0 then clear interrupt status register */ -if (hba->ufs_version ==UFSHCI_VERSION_10 ) -ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }spin_unlock (hba->host->host_lock);
Signature · 1 line
1.7.0.4
Re: [PATCH v4 3/6] scsi: ufs: fix interrupt status clears
Quoted 28 lines · Seungwon Jeon
There is no need to check the version to clear the interrupt status. And the order is changed prior to actual handling.
Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-)drivers/scsi/ufs/ufshcd.c +1
-5@@ -1582,11 +1582,8 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba) intr_status =ufshcd_readl (hba,REG_INTERRUPT_STATUS );if (intr_status) { +ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS );ufshcd_sl_intr (hba, intr_status); - -/* If UFSHCI 1.0 then clear interrupt status register */ -if (hba->ufs_version ==UFSHCI_VERSION_10 ) -ufshcd_writel (hba, intr_status,REG_INTERRUPT_STATUS ); retval =IRQ_HANDLED ; }spin_unlock (hba->host->host_lock); --
Quoted 3 lines
1.7.0.4
Signature · 1 line
~Santosh
PATCH v4 4/6 scsi: ufs: rework link start-up process
In reply to Seungwon JeonLink start-up requires long time with multiphase handshakes between UFS host and device. This affects driver's probe time. This patch let link start-up run asynchronously. Link start-up will be executed at the end of prove separately. Along with this change, the following is worked.
Defined completion time of uic command to avoid a permanent wait. Added mutex to guarantee of uic command at a time. Adapted some sequence of controller initialization after link statup according to HCI standard.
---
Change in v4:
- Addressed late interrupt case (Sujit).
- Move print message in link startup (Maya).
drivers/scsi/ufs/ufshcd.c | 295 ++++++++++++++++++++++++++++++-------------- drivers/scsi/ufs/ufshcd.h | 10 +- 2 files changed, 208 insertions(+), 97 deletions(-)
drivers/scsi/ufs/ufshcd.c +201 -94
@@ -33,11 +33,15 @@* this program. */ +#include <linux/async.h> +#include "ufshcd.h" #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) +/* UIC command timeout, unit: ms */ +#define UIC_CMD_TIMEOUT 500enum {UFSHCD_MAX_CHANNEL =0 ,
@@ -401,24 +405,122 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) }/** -* ufshcd_send_uic_command - Send UIC commands to unipro layers +* ufshcd_ready_for_uic_cmd - Check if controller is ready +* to accept UIC commands * @hba: per adapter instance -* @uic_command: UIC command +* Return true on success, else false +*/ +static inline bool ufshcd_ready_for_uic_cmd (struct ufs_hba *hba) +{ +if (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) +return true; +else +return false; +} + +/** +* ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Mutex must be held. */ static inline void -ufshcd_send_uic_command (struct ufs_hba *hba,struct uic_command *uic_cmnd) +ufshcd_dispatch_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) { +WARN_ON (hba->active_uic_cmd); + + hba->active_uic_cmd = uic_cmd; +/* Write Args */ -ufshcd_writel (hba, uic_cmnd->argument1,REG_UIC_COMMAND_ARG_1 ); -ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); -ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 ); +ufshcd_writel (hba, uic_cmd->argument1,REG_UIC_COMMAND_ARG_1 ); +ufshcd_writel (hba, uic_cmd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +ufshcd_writel (hba, uic_cmd->command &COMMAND_OPCODE_MASK ,REG_UIC_COMMAND ); }/** +* ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command +* @hba: per adapter instance +* @uic_command: UIC command +* +* Must be called with mutex held. +* Returns 0 only if success. +*/ +static int +ufshcd_wait_for_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; +unsigned long flags; + +if (wait_for_completion_timeout (&uic_cmd->done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) + ret = uic_cmd->argument2 &MASK_UIC_COMMAND_RESULT ; +else + ret = -ETIMEDOUT ; + +spin_lock_irqsave (hba->host->host_lock, flags); + hba->active_uic_cmd =NULL ; +spin_unlock_irqrestore (hba->host->host_lock, flags); + +return ret; +} + +/** +* __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Identical to ufshcd_send_uic_cmd() expect mutex. Must be called +* with mutex held. +* Returns 0 only if success. +*/ +static int +__ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; +unsigned long flags; + +if (!ufshcd_ready_for_uic_cmd (hba)) { +dev_err (hba->dev, +"Controller not ready to accept UIC commands\n" ); +return -EIO ; + } + +init_completion (&uic_cmd->done); + +spin_lock_irqsave (hba->host->host_lock, flags); +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba, uic_cmd); + +return ret; +} + +/** +* ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Returns 0 only if success. +*/ +static int +ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, uic_cmd); +mutex_unlock (&hba->uic_cmd_mutex); + +return ret; +} + +/** * ufshcd_map_sg - Map scatter-gather list to prdt * @lrbp - pointer to local reference block *
@@ -962,34 +1064,16 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)*/ static int ufshcd_dme_link_startup (struct ufs_hba *hba) { -struct uic_command *uic_cmd; -unsigned long flags; - -/* check if controller is ready to accept UIC commands */ -if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) & -UIC_COMMAND_READY ) ==0x0 ) { -dev_err (hba->dev, -"Controller not ready" -" to accept UIC commands\n" ); -return -EIO ; - } +struct uic_command uic_cmd = {0 }; +int ret; -spin_lock_irqsave (hba->host->host_lock, flags); + uic_cmd.command =UIC_CMD_DME_LINK_STARTUP ; -/* form UIC command */ - uic_cmd = &hba->active_uic_cmd; - uic_cmd->command =UIC_CMD_DME_LINK_STARTUP ; - uic_cmd->argument1 =0 ; - uic_cmd->argument2 =0 ; - uic_cmd->argument3 =0 ; - -/* enable UIC related interrupts */ -ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); - -/* sending UIC commands to controller */ -ufshcd_send_uic_command (hba, uic_cmd); -spin_unlock_irqrestore (hba->host->host_lock, flags); -return 0 ; + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev, +"dme-link-startup: error code %d\n" , ret); +return ret; }/**
@@ -998,9 +1082,10 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)* * To bring UFS host controller to operational state, * 1. Check if device is present -* 2. Configure run-stop-registers -* 3. Enable required interrupts -* 4. Configure interrupt aggregation +* 2. Enable required interrupts +* 3. Configure interrupt aggregation +* 4. Program UTRL and UTMRL base addres +* 5. Configure run-stop-registers * * Returns 0 on success, non-zero value on failure */
@@ -1017,6 +1102,22 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } +/* Enable required interrupts */ +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); + +/* Configure interrupt aggregation */ +ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); + +/* Configure UTRL and UTMRL base address registers */ +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H ); +/* * UCRDY, UTMRLDY and UTRLRDY bits must be 1 * DEI, HEI bits must be 0
@@ -1030,17 +1131,11 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } -/* Enable required interrupts */ -ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); - -/* Configure interrupt aggregation */ -ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); -if (hba->ufshcd_state ==UFSHCD_STATE_RESET )scsi_unblock_requests (hba->host); hba->ufshcd_state =UFSHCD_STATE_OPERATIONAL ; -scsi_scan_host (hba->host); + out:return err; }
@@ -1109,34 +1204,28 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) }/** -* ufshcd_initialize_hba - start the initialization process +* ufshcd_link_startup - Initialize unipro link startup * @hba: per adapter instance * -* 1. Enable the controller via ufshcd_hba_enable. -* 2. Program the Transfer Request List Address with the starting address of -* UTRDL. -* 3. Program the Task Management Request List Address with starting address -* of UTMRDL. -* -* Returns 0 on success, non-zero value on failure. +* Returns 0 for success, non-zero in case of failure */ -static int ufshcd_initialize_hba (struct ufs_hba *hba) +static int ufshcd_link_startup (struct ufs_hba *hba) { -if (ufshcd_hba_enable (hba)) -return -EIO ; +int ret; -/* Configure UTRL and UTMRL base address registers */ -ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_H ); -ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_H ); +/* enable UIC related interrupts */ +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); -/* Initialize unipro link startup procedure */ -return ufshcd_dme_link_startup (hba); + ret =ufshcd_dme_link_startup (hba); +if (ret) + goto out; + + ret =ufshcd_make_hba_operational (hba); + +out: +if (ret) +dev_err (hba->dev,"link startup failed %d\n" , ret); +return ret; }/**
@@ -1176,12 +1265,19 @@ static int ufshcd_do_reset(struct ufs_hba *hba) hba->outstanding_reqs =0 ; hba->outstanding_tasks =0 ; -/* start the initialization process */ -if (ufshcd_initialize_hba (hba)) { +/* Host controller enable */ +if (ufshcd_hba_enable (hba)) {dev_err (hba->dev,"Reset: Controller initialization failed\n" );return FAILED ; } + +if (ufshcd_link_startup (hba)) { +dev_err (hba->dev, +"Reset: Link start-up failed\n" ); +return FAILED ; + } +return SUCCESS ; }
@@ -1434,6 +1530,19 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) }/** +* ufshcd_uic_cmd_compl - handle completion of uic command +* @hba: per adapter instance +*/ +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +{ +if (hba->active_uic_cmd) { + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); +complete (&hba->active_uic_cmd->done); + } +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance */
@@ -1473,28 +1582,6 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) }/** -* ufshcd_uic_cc_handler - handle UIC command completion -* @work: pointer to a work queue structure -* -* Returns 0 on success, non-zero value on failure -*/ -static void ufshcd_uic_cc_handler (struct work_struct *work) -{ -struct ufs_hba *hba; - - hba = container_of(work, struct ufs_hba, uic_workq); - -if ((hba->active_uic_cmd.command ==UIC_CMD_DME_LINK_STARTUP ) && - !(ufshcd_get_uic_cmd_result (hba))) { - -if (ufshcd_make_hba_operational (hba)) -dev_err (hba->dev, -"cc: hba not operational state\n" ); -return ; - } -} - -/** * ufshcd_fatal_err_handler - handle fatal errors * @hba: per adapter instance */
@@ -1555,7 +1642,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)ufshcd_err_handler (hba);if (intr_status &UIC_COMMAND_COMPL ) -schedule_work (&hba->uic_workq); +ufshcd_uic_cmd_compl (hba);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);
@@ -1778,6 +1865,21 @@ out:return err; } +/** +* ufshcd_async_scan - asynchronous execution for link startup +* @data: data pointer to pass to this function +* @cookie: cookie data +*/ +static void ufshcd_async_scan (void *data,async_cookie_t cookie) +{ +struct ufs_hba *hba = (struct ufs_hba *)data; +int ret; + + ret =ufshcd_link_startup (hba); +if (!ret) +scsi_scan_host (hba->host); +} +static struct scsi_host_template ufshcd_driver_template = { .module =THIS_MODULE , .name =UFSHCD ,
@@ -1939,12 +2041,14 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,init_waitqueue_head (&hba->ufshcd_tm_wait_queue);/* Initialize work queues */ -INIT_WORK (&hba->uic_workq, ufshcd_uic_cc_handler);INIT_WORK (&hba->feh_workq, ufshcd_fatal_err_handler);/* Initialize mutex for query requests */ mutex_init (&hba->query.lock_ufs_query); +/* Initialize UIC command mutex */ +mutex_init (&hba->uic_cmd_mutex); +/* IRQ registration */ err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {
@@ -1965,14 +2069,17 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, goto out_free_irq; } -/* Initialization routine */ - err =ufshcd_initialize_hba (hba); +/* Host controller enable */ + err =ufshcd_hba_enable (hba);if (err) { -dev_err (hba->dev,"Initialization failed\n" ); +dev_err (hba->dev,"Host controller enable failed\n" ); goto out_remove_scsi_host; } + *hba_handle = hba; +async_schedule (ufshcd_async_scan, hba); +return 0 ; out_remove_scsi_host:
drivers/scsi/ufs/ufshcd.h +7 -3
@@ -51,6 +51,7 @@#include <linux/bitops.h> #include <linux/pm_runtime.h> #include <linux/clk.h> +#include <linux/completion.h> #include <asm/irq.h> #include <asm/byteorder.h>
@@ -76,6 +77,7 @@* @argument3: UIC command argument 3 * @cmd_active: Indicate if UIC command is outstanding * @result: UIC command result +* @done: UIC command completion */ struct uic_command {u32 command;
@@ -84,6 +86,7 @@ struct uic_command {u32 argument3;int cmd_active;int result; +struct completion done; };/**
@@ -150,11 +153,11 @@ struct ufs_query {* @ufs_version: UFS Version to which controller complies * @irq: Irq number of the controller * @active_uic_cmd: handle of active UIC command +* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits -* @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors * @query: query request information
@@ -186,7 +189,9 @@ struct ufs_hba {u32 ufs_version;unsigned int irq; -struct uic_command active_uic_cmd; +struct uic_command *active_uic_cmd; +struct mutex uic_cmd_mutex; +wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition;
@@ -194,7 +199,6 @@ struct ufs_hba {u32 intr_mask;/* Work Queues */ -struct work_struct uic_workq;struct work_struct feh_workq;/* HBA Errors */
Signature · 1 line
1.7.0.4
Re: [PATCH v4 4/6] scsi: ufs: rework link start-up process
Quoted 523 lines · Seungwon Jeon
Link start-up requires long time with multiphase handshakes between UFS host and device. This affects driver's probe time. This patch let link start-up run asynchronously. Link start-up will be executed at the end of prove separately. Along with this change, the following is worked.
Defined completion time of uic command to avoid a permanent wait. Added mutex to guarantee of uic command at a time. Adapted some sequence of controller initialization after link statup according to HCI standard.
Signed-off-by Seungwon Jeon <[email protected]>Signed-off-by Sujit Reddy Thumma <[email protected]>Tested-by Maya Erez <[email protected]>---
Change in v4:
- Addressed late interrupt case (Sujit).
- Move print message in link startup (Maya).drivers/scsi/ufs/ufshcd.c | 295 ++++++++++++++++++++++++++++++-------------- drivers/scsi/ufs/ufshcd.h | 10 +- 2 files changed, 208 insertions(+), 97 deletions(-)drivers/scsi/ufs/ufshcd.c +201
-94@@ -33,11 +33,15 @@* this program. */ +#include <linux/async.h> +#include "ufshcd.h" #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) +/* UIC command timeout, unit: ms */ +#define UIC_CMD_TIMEOUT 500enum {UFSHCD_MAX_CHANNEL =0 ,@@ -401,24 +405,122 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) }/** -* ufshcd_send_uic_command - Send UIC commands to unipro layers +* ufshcd_ready_for_uic_cmd - Check if controller is ready +* to accept UIC commands * @hba: per adapter instance -* @uic_command: UIC command +* Return true on success, else false +*/ +static inline bool ufshcd_ready_for_uic_cmd (struct ufs_hba *hba) +{ +if (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) +return true; +else +return false; +} + +/** +* ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Mutex must be held. */ static inline void -ufshcd_send_uic_command (struct ufs_hba *hba,struct uic_command *uic_cmnd) +ufshcd_dispatch_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) { +WARN_ON (hba->active_uic_cmd); + + hba->active_uic_cmd = uic_cmd; +/* Write Args */ -ufshcd_writel (hba, uic_cmnd->argument1,REG_UIC_COMMAND_ARG_1 ); -ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); -ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 ); +ufshcd_writel (hba, uic_cmd->argument1,REG_UIC_COMMAND_ARG_1 ); +ufshcd_writel (hba, uic_cmd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +ufshcd_writel (hba, uic_cmd->command &COMMAND_OPCODE_MASK ,REG_UIC_COMMAND ); }/** +* ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command +* @hba: per adapter instance +* @uic_command: UIC command +* +* Must be called with mutex held. +* Returns 0 only if success. +*/ +static int +ufshcd_wait_for_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; +unsigned long flags; + +if (wait_for_completion_timeout (&uic_cmd->done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) + ret = uic_cmd->argument2 &MASK_UIC_COMMAND_RESULT ; +else + ret = -ETIMEDOUT ; + +spin_lock_irqsave (hba->host->host_lock, flags); + hba->active_uic_cmd =NULL ; +spin_unlock_irqrestore (hba->host->host_lock, flags); + +return ret; +} + +/** +* __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Identical to ufshcd_send_uic_cmd() expect mutex. Must be called +* with mutex held. +* Returns 0 only if success. +*/ +static int +__ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; +unsigned long flags; + +if (!ufshcd_ready_for_uic_cmd (hba)) { +dev_err (hba->dev, +"Controller not ready to accept UIC commands\n" ); +return -EIO ; + } + +init_completion (&uic_cmd->done); + +spin_lock_irqsave (hba->host->host_lock, flags); +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba, uic_cmd); + +return ret; +} + +/** +* ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Returns 0 only if success. +*/ +static int +ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, uic_cmd); +mutex_unlock (&hba->uic_cmd_mutex); + +return ret; +} + +/** * ufshcd_map_sg - Map scatter-gather list to prdt * @lrbp - pointer to local reference block * @@ -962,34 +1064,16 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)*/ static int ufshcd_dme_link_startup (struct ufs_hba *hba) { -struct uic_command *uic_cmd; -unsigned long flags; - -/* check if controller is ready to accept UIC commands */ -if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) & -UIC_COMMAND_READY ) ==0x0 ) { -dev_err (hba->dev, -"Controller not ready" -" to accept UIC commands\n" ); -return -EIO ; - } +struct uic_command uic_cmd = {0 }; +int ret; -spin_lock_irqsave (hba->host->host_lock, flags); + uic_cmd.command =UIC_CMD_DME_LINK_STARTUP ; -/* form UIC command */ - uic_cmd = &hba->active_uic_cmd; - uic_cmd->command =UIC_CMD_DME_LINK_STARTUP ; - uic_cmd->argument1 =0 ; - uic_cmd->argument2 =0 ; - uic_cmd->argument3 =0 ; - -/* enable UIC related interrupts */ -ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); - -/* sending UIC commands to controller */ -ufshcd_send_uic_command (hba, uic_cmd); -spin_unlock_irqrestore (hba->host->host_lock, flags); -return 0 ; + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev, +"dme-link-startup: error code %d\n" , ret); +return ret; }/** @@ -998,9 +1082,10 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)* * To bring UFS host controller to operational state, * 1. Check if device is present -* 2. Configure run-stop-registers -* 3. Enable required interrupts -* 4. Configure interrupt aggregation +* 2. Enable required interrupts +* 3. Configure interrupt aggregation +* 4. Program UTRL and UTMRL base addres +* 5. Configure run-stop-registers * * Returns 0 on success, non-zero value on failure */ @@ -1017,6 +1102,22 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } +/* Enable required interrupts */ +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); + +/* Configure interrupt aggregation */ +ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); + +/* Configure UTRL and UTMRL base address registers */ +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H ); +/* * UCRDY, UTMRLDY and UTRLRDY bits must be 1 * DEI, HEI bits must be 0 @@ -1030,17 +1131,11 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } -/* Enable required interrupts */ -ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); - -/* Configure interrupt aggregation */ -ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); -if (hba->ufshcd_state ==UFSHCD_STATE_RESET )scsi_unblock_requests (hba->host); hba->ufshcd_state =UFSHCD_STATE_OPERATIONAL ; -scsi_scan_host (hba->host); + out:return err; }@@ -1109,34 +1204,28 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) }/** -* ufshcd_initialize_hba - start the initialization process +* ufshcd_link_startup - Initialize unipro link startup * @hba: per adapter instance * -* 1. Enable the controller via ufshcd_hba_enable. -* 2. Program the Transfer Request List Address with the starting address of -* UTRDL. -* 3. Program the Task Management Request List Address with starting address -* of UTMRDL. -* -* Returns 0 on success, non-zero value on failure. +* Returns 0 for success, non-zero in case of failure */ -static int ufshcd_initialize_hba (struct ufs_hba *hba) +static int ufshcd_link_startup (struct ufs_hba *hba) { -if (ufshcd_hba_enable (hba)) -return -EIO ; +int ret; -/* Configure UTRL and UTMRL base address registers */ -ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_H ); -ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_H ); +/* enable UIC related interrupts */ +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); -/* Initialize unipro link startup procedure */ -return ufshcd_dme_link_startup (hba); + ret =ufshcd_dme_link_startup (hba); +if (ret) + goto out; + + ret =ufshcd_make_hba_operational (hba); + +out: +if (ret) +dev_err (hba->dev,"link startup failed %d\n" , ret); +return ret; }/** @@ -1176,12 +1265,19 @@ static int ufshcd_do_reset(struct ufs_hba *hba) hba->outstanding_reqs =0 ; hba->outstanding_tasks =0 ; -/* start the initialization process */ -if (ufshcd_initialize_hba (hba)) { +/* Host controller enable */ +if (ufshcd_hba_enable (hba)) {dev_err (hba->dev,"Reset: Controller initialization failed\n" );return FAILED ; } + +if (ufshcd_link_startup (hba)) { +dev_err (hba->dev, +"Reset: Link start-up failed\n" ); +return FAILED ; + } +return SUCCESS ; }@@ -1434,6 +1530,19 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) }/** +* ufshcd_uic_cmd_compl - handle completion of uic command +* @hba: per adapter instance +*/ +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +{ +if (hba->active_uic_cmd) { + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); +complete (&hba->active_uic_cmd->done); + } +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance */ @@ -1473,28 +1582,6 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) }/** -* ufshcd_uic_cc_handler - handle UIC command completion -* @work: pointer to a work queue structure -* -* Returns 0 on success, non-zero value on failure -*/ -static void ufshcd_uic_cc_handler (struct work_struct *work) -{ -struct ufs_hba *hba; - - hba = container_of(work, struct ufs_hba, uic_workq); - -if ((hba->active_uic_cmd.command ==UIC_CMD_DME_LINK_STARTUP ) && - !(ufshcd_get_uic_cmd_result (hba))) { - -if (ufshcd_make_hba_operational (hba)) -dev_err (hba->dev, -"cc: hba not operational state\n" ); -return ; - } -} - -/** * ufshcd_fatal_err_handler - handle fatal errors * @hba: per adapter instance */ @@ -1555,7 +1642,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)ufshcd_err_handler (hba);if (intr_status &UIC_COMMAND_COMPL ) -schedule_work (&hba->uic_workq); +ufshcd_uic_cmd_compl (hba);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);@@ -1778,6 +1865,21 @@ out:return err; } +/** +* ufshcd_async_scan - asynchronous execution for link startup +* @data: data pointer to pass to this function +* @cookie: cookie data +*/ +static void ufshcd_async_scan (void *data,async_cookie_t cookie) +{ +struct ufs_hba *hba = (struct ufs_hba *)data; +int ret; + + ret =ufshcd_link_startup (hba); +if (!ret) +scsi_scan_host (hba->host); +} +static struct scsi_host_template ufshcd_driver_template = { .module =THIS_MODULE , .name =UFSHCD ,@@ -1939,12 +2041,14 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,init_waitqueue_head (&hba->ufshcd_tm_wait_queue);/* Initialize work queues */ -INIT_WORK (&hba->uic_workq, ufshcd_uic_cc_handler);INIT_WORK (&hba->feh_workq, ufshcd_fatal_err_handler);/* Initialize mutex for query requests */ mutex_init (&hba->query.lock_ufs_query); +/* Initialize UIC command mutex */ +mutex_init (&hba->uic_cmd_mutex); +/* IRQ registration */ err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {@@ -1965,14 +2069,17 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, goto out_free_irq; } -/* Initialization routine */ - err =ufshcd_initialize_hba (hba); +/* Host controller enable */ + err =ufshcd_hba_enable (hba);if (err) { -dev_err (hba->dev,"Initialization failed\n" ); +dev_err (hba->dev,"Host controller enable failed\n" ); goto out_remove_scsi_host; } + *hba_handle = hba; +async_schedule (ufshcd_async_scan, hba); +return 0 ; out_remove_scsi_host:drivers/scsi/ufs/ufshcd.h +7
-4@@ -51,6 +51,7 @@#include <linux/bitops.h> #include <linux/pm_runtime.h> #include <linux/clk.h> +#include <linux/completion.h> #include <asm/irq.h> #include <asm/byteorder.h> @@ -76,6 +77,7 @@* @argument3: UIC command argument 3 * @cmd_active: Indicate if UIC command is outstanding * @result: UIC command result +* @done: UIC command completion */ struct uic_command {u32 command;@@ -84,6 +86,7 @@ struct uic_command {u32 argument3;int cmd_active;int result; +struct completion done; };/** @@ -150,11 +153,11 @@ struct ufs_query {* @ufs_version: UFS Version to which controller complies * @irq: Irq number of the controller * @active_uic_cmd: handle of active UIC command +* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits -* @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors * @query: query request information @@ -186,7 +189,9 @@ struct ufs_hba {u32 ufs_version;unsigned int irq; -struct uic_command active_uic_cmd; +struct uic_command *active_uic_cmd; +struct mutex uic_cmd_mutex; +wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition;@@ -194,7 +199,6 @@ struct ufs_hba {u32 intr_mask;/* Work Queues */ -struct work_struct uic_workq;struct work_struct feh_workq;/* HBA Errors */ --
Quoted 3 lines
1.7.0.4
Signature · 1 line
~Santosh
PATCH v4 5/6 scsi: ufs: add dme configuration primitives
In reply to Seungwon JeonImplements to support Get and Set operation of the DME. These operations are used to configure the behavior of the UNIPRO.
---
Change in v4:
- Removed unipro.h header file. It will be introduced in next.
- Changed function names and error message.
drivers/scsi/ufs/ufshcd.c | 88 +++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.h | 30 +++++++++++++++ drivers/scsi/ufs/ufshci.h | 5 +++ 3 files changed, 123 insertions(+), 0 deletions(-)
drivers/scsi/ufs/ufshcd.c +88 -0
@@ -191,6 +191,18 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }/** +* ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command +* @hba: Pointer to adapter instance +* +* This function gets UIC command argument3 +* Returns 0 on success, non zero value on error +*/ +static inline u32 ufshcd_get_dme_attr_val (struct ufs_hba *hba) +{ +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_3 ); +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance
@@ -1077,6 +1089,80 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) }/** +* ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @attr_set: attribute set type as uic command argument2 +* @mib_val: setting value as uic command argument3 +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_set_attr (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-set" , +"dme-peer-set" + }; +const char *set = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_SET :UIC_CMD_DME_SET ; + uic_cmd.argument1 = attr_sel; + uic_cmd.argument2 =UIC_ARG_ATTR_SET (attr_set); + uic_cmd.argument3 = mib_val; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: attr-id 0x%x error code %d\n" , + set,GET_UIC_ATTR_ID (attr_sel), ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_set_attr); + +/** +* ufshcd_dme_get_attr - UIC command for DME_GET, DME_PEER_GET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @mib_val: the value of the attribute as returned by the UIC command +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_get_attr (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-get" , +"dme-peer-get" + }; +const char *get = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_GET :UIC_CMD_DME_GET ; + uic_cmd.argument1 = attr_sel; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: attr-id 0x%x error code %d\n" , + get,GET_UIC_ATTR_ID (attr_sel), ret); + goto out; + } + +if (mib_val) + *mib_val = uic_cmd.argument3; +out: +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_get_attr); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance *
@@ -1538,6 +1624,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)if (hba->active_uic_cmd) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba);complete (&hba->active_uic_cmd->done); } }
drivers/scsi/ufs/ufshcd.h +30 -0
@@ -217,6 +217,11 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); +extern int ufshcd_dme_set_attr (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer); +extern int ufshcd_dme_get_attr (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer); +/** * ufshcd_hba_stop - Send controller to reset state * @hba: per adapter instance
@@ -226,4 +231,29 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba) ufshcd_writel(hba, CONTROLLER_DISABLE, REG_CONTROLLER_ENABLE); } +/* UIC command interfaces for DME primitives */ +static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_set_attr (hba, attr_sel, attr_set, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_set_attr (hba, attr_sel, attr_set, mib_val,1 ); +} + +static inline int ufshcd_dme_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_get_attr (hba, attr_sel, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_get_attr (hba, attr_sel, mib_val,1 ); +} +#endif /* End of Header */
drivers/scsi/ufs/ufshci.h +5 -0
@@ -191,6 +191,11 @@ enum {#define CONFIG_RESULT_CODE_MASK 0xFF#define GENERIC_ERROR_CODE_MASK 0xFF +#define UIC_ARG_MIB_SEL (attr, sel) ((((attr) & 0xFFFF) << 16) |\ + ((sel) & 0xFFFF)) +#define UIC_ARG_ATTR_SET (type) (((type) & 0xFF) << 16) +#define GET_UIC_ATTR_ID (val) (((val) >> 16) & 0xFFFF) +/* UIC Commands */ enum {UIC_CMD_DME_GET =0x01 ,
Signature · 1 line
1.7.0.4
Re: [PATCH v4 5/6] scsi: ufs: add dme configuration primitives
Quoted 192 lines · Seungwon Jeon
Implements to support Get and Set operation of the DME. These operations are used to configure the behavior of the UNIPRO.
Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>---
Change in v4:
- Removedunipro.hheader file. It will be introduced in next.
- Changed function names and error message.drivers/scsi/ufs/ufshcd.c | 88 +++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.h | 30 +++++++++++++++ drivers/scsi/ufs/ufshci.h | 5 +++ 3 files changed, 123 insertions(+), 0 deletions(-)drivers/scsi/ufs/ufshcd.c +88
-0@@ -191,6 +191,18 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }/** +* ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command +* @hba: Pointer to adapter instance +* +* This function gets UIC command argument3 +* Returns 0 on success, non zero value on error +*/ +static inline u32 ufshcd_get_dme_attr_val (struct ufs_hba *hba) +{ +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_3 ); +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance @@ -1077,6 +1089,80 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) }/** +* ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @attr_set: attribute set type as uic command argument2 +* @mib_val: setting value as uic command argument3 +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_set_attr (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-set" , +"dme-peer-set" + }; +const char *set = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_SET :UIC_CMD_DME_SET ; + uic_cmd.argument1 = attr_sel; + uic_cmd.argument2 =UIC_ARG_ATTR_SET (attr_set); + uic_cmd.argument3 = mib_val; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: attr-id 0x%x error code %d\n" , + set,GET_UIC_ATTR_ID (attr_sel), ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_set_attr); + +/** +* ufshcd_dme_get_attr - UIC command for DME_GET, DME_PEER_GET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @mib_val: the value of the attribute as returned by the UIC command +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_get_attr (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-get" , +"dme-peer-get" + }; +const char *get = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_GET :UIC_CMD_DME_GET ; + uic_cmd.argument1 = attr_sel; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: attr-id 0x%x error code %d\n" , + get,GET_UIC_ATTR_ID (attr_sel), ret); + goto out; + } + +if (mib_val) + *mib_val = uic_cmd.argument3; +out: +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_get_attr); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance * @@ -1538,6 +1624,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)if (hba->active_uic_cmd) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba);complete (&hba->active_uic_cmd->done); } }drivers/scsi/ufs/ufshcd.h +30
-0@@ -217,6 +217,11 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); +extern int ufshcd_dme_set_attr (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer); +extern int ufshcd_dme_get_attr (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer); +/** * ufshcd_hba_stop - Send controller to reset state * @hba: per adapter instance @@ -226,4 +231,29 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba) ufshcd_writel(hba, CONTROLLER_DISABLE, REG_CONTROLLER_ENABLE); } +/* UIC command interfaces for DME primitives */ +static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_set_attr (hba, attr_sel, attr_set, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_set_attr (hba, attr_sel, attr_set, mib_val,1 ); +} + +static inline int ufshcd_dme_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_get_attr (hba, attr_sel, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_get_attr (hba, attr_sel, mib_val,1 ); +} +#endif /* End of Header */ drivers/scsi/ufs/ufshci.h +5
-1@@ -191,6 +191,11 @@ enum {#define CONFIG_RESULT_CODE_MASK 0xFF#define GENERIC_ERROR_CODE_MASK 0xFF +#define UIC_ARG_MIB_SEL (attr, sel) ((((attr) & 0xFFFF) << 16) |\ + ((sel) & 0xFFFF)) +#define UIC_ARG_ATTR_SET (type) (((type) & 0xFF) << 16) +#define GET_UIC_ATTR_ID (val) (((val) >> 16) & 0xFFFF) +/* UIC Commands */ enum {UIC_CMD_DME_GET =0x01 , --
Quoted 3 lines
1.7.0.4
Signature · 1 line
~Santosh
PATCH v4 6/6 scsi: ufs: add dme control primitives
In reply to Seungwon JeonImplements to support the following operations. Currently, this patch doesn't introduce DME_ENABLE and DME_RESET because host controller's HCE enable contains these roles.
DME_POWERON{OFF}, DME_HIBERNATE_ENTER{EXIT}, DME_ENDPOINTRESET.
---
Change in v4:
- Changed function names.
drivers/scsi/ufs/ufshcd.c | 123 +++++++++++++++++++++++++++++++++++++++++++-- drivers/scsi/ufs/ufshcd.h | 26 ++++++++++ drivers/scsi/ufs/ufshci.h | 15 ++++++ 3 files changed, 160 insertions(+), 4 deletions(-)
drivers/scsi/ufs/ufshcd.c +119 -4
@@ -39,6 +39,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)/* UIC command timeout, unit: ms */ #define UIC_CMD_TIMEOUT 500
@@ -203,6 +204,18 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) }/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance
@@ -1163,6 +1176,103 @@ out:EXPORT_SYMBOL_GPL (ufshcd_dme_get_attr);/** +* ufshcd_dme_power_ctrl - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* @on: indicate wherter power_on or power_off +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_ctrl (struct ufs_hba *hba,u8 on) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-power-off" , +"dme-power-on" + }; +const char *power = action[!!on]; +int ret; + + uic_cmd.command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: error code %d\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_ctrl); + +/** +* ufshcd_dme_hibern8_ctrl - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* @enter: indicate wherter hibernation enter or exit +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_ctrl (struct ufs_hba *hba,u8 enter) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-hibernate-exit" , +"dme-hibernate-enter" + }; +const char *hibern8 = action[!!enter]; +u8 status; +int ret; + + uic_cmd.command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + +mutex_lock (&hba->uic_cmd_mutex); +init_completion (&hba->hibern8_done); + ret =__ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: error code %d\n" , hibern8, ret); + goto out; + } + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:0x%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +mutex_unlock (&hba->uic_cmd_mutex); +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_ctrl); + +/** +* ufshcd_dme_endpoint_reset - UIC command for DME_ENDPOINTRESET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_endpoint_reset (struct ufs_hba *hba) +{ +struct uic_command uic_cmd = {0 }; +int ret; + + uic_cmd.command =UIC_CMD_DME_END_PT_RST ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"dme-endpoint-reset: error code %d\n" , ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_endpoint_reset); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance *
@@ -1618,16 +1728,21 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)/** * ufshcd_uic_cmd_compl - handle completion of uic command * @hba: per adapter instance +* @intr_status: interrupt status generated by the controller */ -static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { -if (hba->active_uic_cmd) { +if ((intr_status &UIC_COMMAND_COMPL ) && + hba->active_uic_cmd) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba); hba->active_uic_cmd->argument3 =ufshcd_get_dme_attr_val (hba);complete (&hba->active_uic_cmd->done); } + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/**
@@ -1729,8 +1844,8 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) -ufshcd_uic_cmd_compl (hba); +if (intr_status &UFSHCD_UIC_MASK ) +ufshcd_uic_cmd_compl (hba, intr_status);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);
drivers/scsi/ufs/ufshcd.h +26 -0
@@ -156,6 +156,7 @@ struct ufs_query {* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @feh_workq: Work queue for fatal controller error handling
@@ -195,6 +196,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;
@@ -221,6 +224,9 @@ extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, u8 attr_set, u32 mib_val, u8 peer);extern int ufshcd_dme_get_attr (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_ctrl (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_ctrl (struct ufs_hba *hba,u8 enter); +extern int ufshcd_dme_endpoint_reset (struct ufs_hba *hba);/** * ufshcd_hba_stop - Send controller to reset state
@@ -256,4 +262,24 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, return ufshcd_dme_get_attr(hba, attr_sel, mib_val, 1); } +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_ctrl (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_ctrl (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_ctrl (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_ctrl (hba,0 ); +} +#endif /* End of Header */
drivers/scsi/ufs/ufshci.h +15 -0
@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\
@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0
Signature · 1 line
1.7.0.4
Re: [PATCH v4 6/6] scsi: ufs: add dme control primitives
Quoted 277 lines · Seungwon Jeon
Implements to support the following operations. Currently, this patch doesn't introduce
DME_ENABLEandDME_RESETbecause host controller's HCE enable contains these roles.DME_POWERON{OFF}, DME_HIBERNATE_ENTER{EXIT},
DME_ENDPOINTRESET.Signed-off-by Seungwon Jeon <[email protected]>Tested-by Maya Erez <[email protected]>---
Change in v4:
- Changed function names.drivers/scsi/ufs/ufshcd.c | 123 +++++++++++++++++++++++++++++++++++++++++++-- drivers/scsi/ufs/ufshcd.h | 26 ++++++++++ drivers/scsi/ufs/ufshci.h | 15 ++++++ 3 files changed, 160 insertions(+), 4 deletions(-)drivers/scsi/ufs/ufshcd.c +119
-4@@ -39,6 +39,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)/* UIC command timeout, unit: ms */ #define UIC_CMD_TIMEOUT 500@@ -203,6 +204,18 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) }/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance @@ -1163,6 +1176,103 @@ out:EXPORT_SYMBOL_GPL (ufshcd_dme_get_attr);/** +* ufshcd_dme_power_ctrl - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* @on: indicate wherter power_on or power_off +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_ctrl (struct ufs_hba *hba,u8 on) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-power-off" , +"dme-power-on" + }; +const char *power = action[!!on]; +int ret; + + uic_cmd.command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: error code %d\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_ctrl); + +/** +* ufshcd_dme_hibern8_ctrl - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* @enter: indicate wherter hibernation enter or exit +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_ctrl (struct ufs_hba *hba,u8 enter) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-hibernate-exit" , +"dme-hibernate-enter" + }; +const char *hibern8 = action[!!enter]; +u8 status; +int ret; + + uic_cmd.command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + +mutex_lock (&hba->uic_cmd_mutex); +init_completion (&hba->hibern8_done); + ret =__ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: error code %d\n" , hibern8, ret); + goto out; + } + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:0x%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +mutex_unlock (&hba->uic_cmd_mutex); +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_ctrl); + +/** +* ufshcd_dme_endpoint_reset - UIC command for DME_ENDPOINTRESET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_endpoint_reset (struct ufs_hba *hba) +{ +struct uic_command uic_cmd = {0 }; +int ret; + + uic_cmd.command =UIC_CMD_DME_END_PT_RST ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"dme-endpoint-reset: error code %d\n" , ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_endpoint_reset); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance * @@ -1618,16 +1728,21 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)/** * ufshcd_uic_cmd_compl - handle completion of uic command * @hba: per adapter instance +* @intr_status: interrupt status generated by the controller */ -static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { -if (hba->active_uic_cmd) { +if ((intr_status &UIC_COMMAND_COMPL ) && + hba->active_uic_cmd) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba); hba->active_uic_cmd->argument3 =ufshcd_get_dme_attr_val (hba);complete (&hba->active_uic_cmd->done); } + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/** @@ -1729,8 +1844,8 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) -ufshcd_uic_cmd_compl (hba); +if (intr_status &UFSHCD_UIC_MASK ) +ufshcd_uic_cmd_compl (hba, intr_status);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);drivers/scsi/ufs/ufshcd.h +26
-0@@ -156,6 +156,7 @@ struct ufs_query {* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @feh_workq: Work queue for fatal controller error handling @@ -195,6 +196,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;@@ -221,6 +224,9 @@ extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, u8 attr_set, u32 mib_val, u8 peer);extern int ufshcd_dme_get_attr (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_ctrl (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_ctrl (struct ufs_hba *hba,u8 enter); +extern int ufshcd_dme_endpoint_reset (struct ufs_hba *hba);/** * ufshcd_hba_stop - Send controller to reset state @@ -256,4 +262,24 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, return ufshcd_dme_get_attr(hba, attr_sel, mib_val, 1); } +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_ctrl (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_ctrl (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_ctrl (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_ctrl (hba,0 ); +} +#endif /* End of Header */ drivers/scsi/ufs/ufshci.h +15
-1@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0 --
Quoted 3 lines
1.7.0.4
Signature · 1 line
~Santosh
PATCH 1/1 scsi: ufs: use devres functions for ufshcd
In reply to Seungwon JeonThis patches replaces normal calls for resource allocation with devm_*() derivative functions. It makes the routine to free resources simpler.
--- drivers/scsi/ufs/ufshcd-pci.c | 1 - drivers/scsi/ufs/ufshcd-pltfrm.c | 69 +++++++++---------------------------- drivers/scsi/ufs/ufshcd.c | 8 ++--- 3 files changed, 20 insertions(+), 58 deletions(-)
drivers/scsi/ufs/ufshcd-pci.c +0 -1
@@ -92,7 +92,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)struct ufs_hba *hba =pci_get_drvdata (pdev);disable_irq (pdev->irq); -free_irq (pdev->irq, hba);ufshcd_remove (hba);pci_release_regions (pdev);pci_set_drvdata (pdev,NULL );
drivers/scsi/ufs/ufshcd-pltfrm.c +17 -52
115 lines not on this page · raw message
drivers/scsi/ufs/ufshcd.c +3 -5
@@ -2050,7 +2050,7 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,mutex_init (&hba->uic_cmd_mutex);/* IRQ registration */ - err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba); + err =devm_request_irq (dev, irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {dev_err (hba->dev,"request irq failed\n" ); goto out_lrb_free;
@@ -2060,13 +2060,13 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, err =scsi_init_shared_tag_map (host, host->can_queue);if (err) {dev_err (hba->dev,"init shared queue failed\n" ); - goto out_free_irq; + goto out_lrb_free; } err =scsi_add_host (host, hba->dev);if (err) {dev_err (hba->dev,"scsi_add_host failed\n" ); - goto out_free_irq; + goto out_lrb_free; }/* Host controller enable */
@@ -2084,8 +2084,6 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, out_remove_scsi_host:scsi_remove_host (hba->host); -out_free_irq: -free_irq (irq, hba); out_lrb_free:ufshcd_free_hba_memory (hba); out_disable:
Signature · 1 line
1.7.0.4
RE: [PATCH] scsi: ufs: use devres functions for ufshcd
Please ignore this one which is wrong sending.
Quoted 190 lines · Seungwon Jeon
This patches replaces normal calls for resource allocation with devm_*() derivative functions. It makes the routine to free resources simpler.
Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd-pci.c | 1 - drivers/scsi/ufs/ufshcd-pltfrm.c | 69 +++++++++---------------------------- drivers/scsi/ufs/ufshcd.c | 8 ++--- 3 files changed, 20 insertions(+), 58 deletions(-)drivers/scsi/ufs/ufshcd-pci.c +0
-1@@ -92,7 +92,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)struct ufs_hba *hba =pci_get_drvdata (pdev);disable_irq (pdev->irq); -free_irq (pdev->irq, hba);ufshcd_remove (hba);pci_release_regions (pdev);pci_set_drvdata (pdev,NULL );drivers/scsi/ufs/ufshcd-pltfrm.c +17
-52@@ -33,9 +33,10 @@* this program. */ -#include "ufshcd.h" #include <linux/platform_device.h> +#include "ufshcd.h" +#ifdef CONFIG_PM /** * ufshcd_pltfrm_suspend - suspend power management function @@ -97,63 +98,43 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)struct ufs_hba *hba;void __iomem *mmio_base;struct resource *mem_res; -struct resource *irq_res; -resource_size_t mem_size; -int err; +int irq, err;struct device *dev = &pdev->dev; mem_res =platform_get_resource (pdev,IORESOURCE_MEM ,0 );if (!mem_res) { -dev_err (&pdev->dev, -"Memory resource not available\n" ); +dev_err (dev,"Memory resource not available\n" ); err = -ENODEV ; goto out_error; } - mem_size =resource_size (mem_res); -if (!request_mem_region (mem_res->start, mem_size,"ufshcd" )) { -dev_err (&pdev->dev, -"Cannot reserve the memory resource\n" ); - err = -EBUSY ; - goto out_error; + mmio_base =devm_ioremap_resource (dev, mem_res); +if (IS_ERR (mmio_base)) { +dev_err (dev,"memory map failed\n" ); +return PTR_ERR (mmio_base); } - mmio_base =ioremap_nocache (mem_res->start, mem_size); -if (!mmio_base) { -dev_err (&pdev->dev,"memory map failed\n" ); - err = -ENOMEM ; - goto out_release_regions; - } - - irq_res =platform_get_resource (pdev,IORESOURCE_IRQ ,0 ); -if (!irq_res) { -dev_err (&pdev->dev,"IRQ resource not available\n" ); - err = -ENODEV ; - goto out_iounmap; + irq =platform_get_irq (pdev,0 ); +if (irq <0 ) { +dev_err (dev,"IRQ resource not available\n" ); +return -ENODEV ; } err =dma_set_coherent_mask (dev, dev->coherent_dma_mask);if (err) { -dev_err (&pdev->dev,"set dma mask failed\n" ); - goto out_iounmap; +dev_err (dev,"set dma mask failed\n" ); +return err; } - err =ufshcd_init (&pdev->dev, &hba, mmio_base, irq_res->start); + err =ufshcd_init (dev, &hba, mmio_base, irq);if (err) { -dev_err (&pdev->dev,"Intialization failed\n" ); - goto out_iounmap; +dev_err (dev,"Intialization failed\n" ); +return err; }platform_set_drvdata (pdev, hba);return 0 ; - -out_iounmap: -iounmap (mmio_base); -out_release_regions: -release_mem_region (mem_res->start, mem_size); -out_error: -return err; }/** @@ -164,26 +145,10 @@ out_error:*/ static int ufshcd_pltfrm_remove (struct platform_device *pdev) { -struct resource *mem_res; -resource_size_t mem_size;struct ufs_hba *hba =platform_get_drvdata (pdev);disable_irq (hba->irq); - -/* Some buggy controllers raise interrupt after -* the resources are removed. So first we unregister the -* irq handler and then the resources used by driver -*/ - -free_irq (hba->irq, hba);ufshcd_remove (hba); - mem_res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); -if (!mem_res) -dev_err (&pdev->dev,"ufshcd: Memory resource not available\n" ); -else { - mem_size =resource_size (mem_res); -release_mem_region (mem_res->start, mem_size); - }platform_set_drvdata (pdev,NULL );return 0 ; }drivers/scsi/ufs/ufshcd.c +3
-6@@ -2050,7 +2050,7 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,mutex_init (&hba->uic_cmd_mutex);/* IRQ registration */ - err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba); + err =devm_request_irq (dev, irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {dev_err (hba->dev,"request irq failed\n" ); goto out_lrb_free;@@ -2060,13 +2060,13 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, err =scsi_init_shared_tag_map (host, host->can_queue);if (err) {dev_err (hba->dev,"init shared queue failed\n" ); - goto out_free_irq; + goto out_lrb_free; } err =scsi_add_host (host, hba->dev);if (err) {dev_err (hba->dev,"scsi_add_host failed\n" ); - goto out_free_irq; + goto out_lrb_free; }/* Host controller enable */ @@ -2084,8 +2084,6 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, out_remove_scsi_host:scsi_remove_host (hba->host); -out_free_irq: -free_irq (irq, hba); out_lrb_free:ufshcd_free_hba_memory (hba); out_disable: --1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH RESEND 1/1 scsi: ufs: use devres functions for ufshcd
In reply to Seungwon JeonThis patches replaces normal calls for resource allocation with devm_*() derivative functions. It makes the routine to free resources simpler.
--- drivers/scsi/ufs/ufshcd-pci.c | 1 - drivers/scsi/ufs/ufshcd-pltfrm.c | 72 +++++++++---------------------------- drivers/scsi/ufs/ufshcd.c | 8 ++--- 3 files changed, 21 insertions(+), 60 deletions(-)
drivers/scsi/ufs/ufshcd-pci.c +0 -1
@@ -92,7 +92,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)struct ufs_hba *hba =pci_get_drvdata (pdev);disable_irq (pdev->irq); -free_irq (pdev->irq, hba);ufshcd_remove (hba);pci_release_regions (pdev);pci_set_drvdata (pdev,NULL );
drivers/scsi/ufs/ufshcd-pltfrm.c +18 -54
116 lines not on this page · raw message
drivers/scsi/ufs/ufshcd.c +3 -5
@@ -2050,7 +2050,7 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,mutex_init (&hba->uic_cmd_mutex);/* IRQ registration */ - err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba); + err =devm_request_irq (dev, irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {dev_err (hba->dev,"request irq failed\n" ); goto out_lrb_free;
@@ -2060,13 +2060,13 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, err =scsi_init_shared_tag_map (host, host->can_queue);if (err) {dev_err (hba->dev,"init shared queue failed\n" ); - goto out_free_irq; + goto out_lrb_free; } err =scsi_add_host (host, hba->dev);if (err) {dev_err (hba->dev,"scsi_add_host failed\n" ); - goto out_free_irq; + goto out_lrb_free; }/* Host controller enable */
@@ -2084,8 +2084,6 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, out_remove_scsi_host:scsi_remove_host (hba->host); -out_free_irq: -free_irq (irq, hba); out_lrb_free:ufshcd_free_hba_memory (hba); out_disable:
Signature · 1 line
1.7.0.4
Quoted 53 lines
drivers/scsi/ufs/ufshcd.c +53
-0+ +/** +* ufshcd_validate_dev_connection() - Check device connection status +* @hba: per-adapter instance +* +* Send NOP OUT UPIU and wait for NOP IN response to check whether the +* device Transport Protocol (UTP) layer is ready after a reset. +* If the UTP layer at the device side is not initialized, it may +* not respond with NOP IN UPIU within timeout of %NOP_OUT_TIMEOUT +* and we retry sending NOP OUT for %NOP_OUT_RETRIES iterations. +*/ +static int ufshcd_validate_dev_connection (struct ufs_hba *hba) +{ +int err; +struct ufshcd_lrb *lrbp; +unsigned long timeout; +unsigned long flags; +struct completion wait; +int retries =NOP_OUT_RETRIES ; + +retry: +spin_lock_irqsave (hba->host->host_lock, flags); + lrbp = &hba->lrb[INTERNAL_CMD_TAG ]; +init_completion (&wait); + + err =ufshcd_compose_nop_out_upiu (hba, lrbp); +if (err) + goto may_retry; + + lrbp->completion = &wait; +ufshcd_send_command (hba,INTERNAL_CMD_TAG ); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + timeout =wait_for_completion_timeout ( + &wait,msecs_to_jiffies (NOP_OUT_TIMEOUT )); + +spin_lock_irqsave (hba->host->host_lock, flags); +if (timeout >0 ) { +int ocs; + + ocs =ufshcd_get_tr_ocs (lrbp); +switch (ocs) { +case OCS_SUCCESS : + goto out; +default : +dev_dbg (hba->dev,"%s: OCS error %d\n" , __func__, ocs); + err = -EIO ; + goto may_retry; + } + }else { +u32 reg; + + err = -ETIMEDOUT ;
drivers/scsi/ufs/ufshcd.c static int ufshcd_dme_link_startup(struct ufs_hba *hba) · line 1216
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +10
-0+ +/* clear outstanding transaction before retry */ +ufshcd_utrl_clear (hba,INTERNAL_CMD_TAG ); +__clear_bit (INTERNAL_CMD_TAG , &hba->outstanding_reqs); + +/* poll for max. 1 sec to clear door bell register by h/w */ +spin_unlock_irqrestore (hba->host->host_lock, flags); +if (readl_poll_timeout ( + hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL , + reg, !(reg &INTERNAL_CMD_TAG ),1000 ,1000 ))
Condition is always true here, change it to !(reg & (1 << INTERNAL_CMD_TAG)).
Quoted 5 lines
drivers/scsi/ufs/ufshcd.c +5
-0+ retries =0 ; +spin_lock_irqsave (hba->host->host_lock, flags); + goto may_retry; + } +
Signature · 1 line
~Santosh
Quoted 57 lines · Santosh Y
Quoted 57 lines
drivers/scsi/ufs/ufshcd.c +57
-0+ +/** +* ufshcd_validate_dev_connection() - Check device connection status +* @hba: per-adapter instance +* +* Send NOP OUT UPIU and wait for NOP IN response to check whether the +* device Transport Protocol (UTP) layer is ready after a reset. +* If the UTP layer at the device side is not initialized, it may +* not respond with NOP IN UPIU within timeout of %NOP_OUT_TIMEOUT +* and we retry sending NOP OUT for %NOP_OUT_RETRIES iterations. +*/ +static int ufshcd_validate_dev_connection (struct ufs_hba *hba) +{ +int err; +struct ufshcd_lrb *lrbp; +unsigned long timeout; +unsigned long flags; +struct completion wait; +int retries =NOP_OUT_RETRIES ; + +retry: +spin_lock_irqsave (hba->host->host_lock, flags); + lrbp = &hba->lrb[INTERNAL_CMD_TAG ]; +init_completion (&wait); + + err =ufshcd_compose_nop_out_upiu (hba, lrbp); +if (err) + goto may_retry; + + lrbp->completion = &wait; +ufshcd_send_command (hba,INTERNAL_CMD_TAG ); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + timeout =wait_for_completion_timeout ( + &wait,msecs_to_jiffies (NOP_OUT_TIMEOUT )); + +spin_lock_irqsave (hba->host->host_lock, flags); +if (timeout >0 ) { +int ocs; + + ocs =ufshcd_get_tr_ocs (lrbp); +switch (ocs) { +case OCS_SUCCESS : + goto out; +default : +dev_dbg (hba->dev,"%s: OCS error %d\n" , __func__, ocs); + err = -EIO ; + goto may_retry; + } + }else { +u32 reg; + + err = -ETIMEDOUT ; + +/* clear outstanding transaction before retry */ +ufshcd_utrl_clear (hba,INTERNAL_CMD_TAG ); +__clear_bit (INTERNAL_CMD_TAG , &hba->outstanding_reqs);
Quoted 8 lines
drivers/scsi/ufs/ufshcd.c static int ufshcd_dme_link_startup(struct ufs_hba *hba) · line 1216
Quoted 6 lines
drivers/scsi/ufs/ufshcd.c +6
-0+ +/* poll for max. 1 sec to clear door bell register by h/w */ +spin_unlock_irqrestore (hba->host->host_lock, flags); +if (readl_poll_timeout ( + hba->mmio_base +REG_UTP_TRANSFER_REQ_DOOR_BELL , + reg, !(reg &INTERNAL_CMD_TAG ),1000 ,1000 ))Condition is always true here, change it to !(reg & (1 <<
INTERNAL_CMD_TAG)).
Good catch. I will update.
Quoted 9 lines
Quoted 6 lines
drivers/scsi/ufs/ufshcd.c +5
-0+ retries =0 ; +spin_lock_irqsave (hba->host->host_lock, flags); + goto may_retry; + } +
Signature · 2 lines
Regards, Sujit