RE: [PATCH v3 5/6] scsi: ufs: add operation for the uic power mode change

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Tested-by: Yaniv Gardi <ygardi@xxxxxxxxxxxxxx>

QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation


= > -----Original Message-----
= > From: linux-scsi-owner@xxxxxxxxxxxxxxx [mailto:linux-scsi-
= > owner@xxxxxxxxxxxxxxx] On Behalf Of Seungwon Jeon
= > Sent: Tuesday, August 27, 2013 2:58 PM
= > To: 'Subhash Jadavani'
= > Cc: linux-scsi@xxxxxxxxxxxxxxx; 'Vinayak Holikatti'; 'Santosh Y'; 'James E.J.
= > Bottomley'
= > Subject: RE: [PATCH v3 5/6] scsi: ufs: add operation for the uic power
= > mode change
= > 
= > On Tue, August 27, 2013, Subhash Jadavani wrote:
= > > On 8/27/2013 4:58 PM, Seungwon Jeon wrote:
= > > > On Tue, August 27, 2013, Subhash Jadavani wrote:
= > > >> On 8/26/2013 8:10 PM, Seungwon Jeon wrote:
= > > >>> Setting PA_PWRMode using DME_SET triggers the power mode
= > change.
= > > >>> And then the result will be given by the HCS.UPMCRS.
= > > >>> This operation should be done atomically.
= > > >>>
= > > >>> Signed-off-by: Seungwon Jeon <tgih.jun@xxxxxxxxxxx>
= > > >>> ---
= > > >>>    drivers/scsi/ufs/ufshcd.c |   84
= > ++++++++++++++++++++++++++++++++++++++++++--
= > > >>>    drivers/scsi/ufs/ufshcd.h |    3 ++
= > > >>>    drivers/scsi/ufs/ufshci.h |   12 ++++++
= > > >>>    3 files changed, 95 insertions(+), 4 deletions(-)
= > > >>>
= > > >>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
= > > >>> index 00bfc1a..c67118d 100644
= > > >>> --- a/drivers/scsi/ufs/ufshcd.c
= > > >>> +++ b/drivers/scsi/ufs/ufshcd.c
= > > >>> @@ -36,9 +36,11 @@
= > > >>>    #include <linux/async.h>
= > > >>>
= > > >>>    #include "ufshcd.h"
= > > >>> +#include "unipro.h"
= > > >>>
= > > >>>    #define UFSHCD_ENABLE_INTRS
= > 	(UTP_TRANSFER_REQ_COMPL |\
= > > >>>    				 UTP_TASK_REQ_COMPL |\
= > > >>> +				 UIC_POWER_MODE |\
= > > >>>    				 UFSHCD_ERROR_MASK)
= > > >>>    /* UIC command timeout, unit: ms */
= > > >>>    #define UIC_CMD_TIMEOUT	500
= > > >>> @@ -520,6 +522,18 @@ static inline bool
= > ufshcd_ready_for_uic_cmd(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_dispatch_uic_cmd - Dispatch UIC commands to unipro
= > layers
= > > >>>     * @hba: per adapter instance
= > > >>>     * @uic_cmd: UIC command
= > > >>> @@ -1526,6 +1540,64 @@ out:
= > > >>>    EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
= > > >>>
= > > >>>    /**
= > > >>> + * ufshcd_uic_change_pwr_mode - Perform the UIC power mode
= > chage
= > > >>> + *				using DME_SET primitives.
= > > >>> + * @hba: per adapter instance
= > > >>> + * @mode: powr mode value
= > > >>> + *
= > > >>> + * Returns 0 on success, non-zero value on failure  */ int
= > > >>> +ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode) {
= > > >>> +	struct uic_command uic_cmd = {0};
= > > >>> +	struct completion pwr_done;
= > > >>> +	unsigned long flags;
= > > >>> +	u8 status;
= > > >>> +	int ret;
= > > >>> +
= > > >>> +	uic_cmd.command = UIC_CMD_DME_SET;
= > > >>> +	uic_cmd.argument1 = UIC_ARG_MIB(PA_PWRMODE);
= > > >>> +	uic_cmd.argument3 = mode;
= > > >>> +	init_completion(&pwr_done);
= > > >>> +
= > > >>> +	mutex_lock(&hba->uic_cmd_mutex);
= > > >>> +
= > > >>> +	spin_lock_irqsave(hba->host->host_lock, flags);
= > > >>> +	hba->pwr_done = &pwr_done;
= > > >>> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
= > > >>> +	ret = __ufshcd_send_uic_cmd(hba, &uic_cmd);
= > > >>> +	if (ret) {
= > > >>> +		dev_err(hba->dev,
= > > >>> +			"pwr mode change with mode 0x%x uic error
= > %d\n",
= > > >>> +			mode, ret);
= > > >>> +		goto out;
= > > >>> +	}
= > > >>> +
= > > >>> +	if (!wait_for_completion_timeout(hba->pwr_done,
= > > >>> +
= > msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
= > > >>> +		dev_err(hba->dev,
= > > >>> +			"pwr mode change with mode 0x%x completion
= > timeout\n",
= > > >>> +			mode);
= > > >>> +		ret = -ETIMEDOUT;
= > > >>> +		goto out;
= > > >>> +	}
= > > >>> +
= > > >>> +	status = ufshcd_get_upmcrs(hba);
= > > >> I have a doubt on the relation between UIC Power Mode Status
= > (UPMS)
= > > >> bit & UIC Power Mode Change Request Status (UPMCRS) field.
= > > >>
= > > >> Once we send the DME_SET(PA_PWRMODE) command, we will get
= > the UIC
= > > >> command completion interrupt (with IS.UCCS bit set) which just
= > > >> indicate that the attribute is written but power mode change
= > > >> procedure will complete only after some delay which is indicated
= > > >> via IS.UPMS status bit and then we would read the HCS.UPMCRS field
= > > >> to know the status of power mode change.
= > > >>
= > > >> This is my exact doubt: Currently UFSHCD driver first clears the
= > > >> IS.UPMS bit (ufshcd_intr() first clears the current interrupts in
= > > >> REG_INTERRUPT_STATUS and then calls the ufshcd_sl_intr() handler,
= > > >> and in your current patch we are anyway not reading the UPMCRS
= > > >> field from interrupt contex ) and then read the HCS.UPMCRS field.
= > > >> Will HCS.UPMCRS field retain its status value even after IS.UPMS
= > > >> bit is cleared? UFSHCI specification doesn't clearly mention this
= > > >> so either we have to get the clarity from JEDEC or from your ufs
= > > >> host controller vendor on the behaviour. I am checking with our ufs
= > > >> host controller vendor as well and will let you know what is the
= > > >> expected behaviour. BTW, i guess you might have already tested this
= > patch to be working on your UFS host controller?
= > > > Hi Subhash,
= > > >
= > > > Yes, It's already tested and works fine.
= > > > IS.UPMS is a indication to inform the result of 'power mode
= > change'(UPMCRS).
= > > > So clearing the interrupt would not affect this result.
= > > Thanks for clarifying.
= > >
= > > > Generally it seems not common idea.
= > >
= > > Infact on SDHCi controller, there is a case where "auto-cmd error
= > > status" register fields are only valid when the "auto-cmd error"
= > > interrupt bit is set in interrupt status register. Clearing status bit
= > > also clears the "auto-cmd error status" register fields automatically.
= > > So i was in doubt whether similar could be the case here or not.
= > 
= > It's interesting thing to me.
= > 
= > >
= > > > Anyway, if your host has different behavior, please let me know.
= > >
= > > Sure, checking on this. Would let you know soon. BTW, UFSHCI
= > > specification doesn't mention it clearly so it could be implementation
= > > dependent as well and if it is the case, we might have to change it
= > > later to accomodate the different implementation. So for now, you have
= > > my Reviewed-by: Subhash Jadavani <subhashj@xxxxxxxxxxxxxx>
= > 
= > Thank you for review.
= > 
= > Seungwon Jeon
= > 
= > >
= > > >
= > > > Thanks,
= > > > Seungwon Jeon
= > > >
= > > >>> +	if (status != PWR_LOCAL) {
= > > >>> +		dev_err(hba->dev,
= > > >>> +			"pwr mode change failed, host umpcrs:0x%x\n",
= > > >>> +			status);
= > > >>> +		ret = (status != PWR_OK) ? status : -1;
= > > >>> +	}
= > > >>> +out:
= > > >>> +	spin_lock_irqsave(hba->host->host_lock, flags);
= > > >>> +	hba->pwr_done = NULL;
= > > >>> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
= > > >>> +	mutex_unlock(&hba->uic_cmd_mutex);
= > > >>> +	return ret;
= > > >>> +}
= > > >>> +
= > > >>> +/**
= > > >>>     * ufshcd_complete_dev_init() - checks device readiness
= > > >>>     * hba: per-adapter instance
= > > >>>     *
= > > >>> @@ -1992,16 +2064,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)
= > > >>>    {
= > > >>> -	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 & UIC_POWER_MODE) && hba->pwr_done)
= > > >>> +		complete(hba->pwr_done);
= > > >>>    }
= > > >>>
= > > >>>    /**
= > > >>> @@ -2451,8 +2527,8 @@ static void ufshcd_sl_intr(struct ufs_hba
= > *hba, u32 intr_status)
= > > >>>    	if (hba->errors)
= > > >>>    		ufshcd_check_errors(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);
= > > >>> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
= > > >>> index ab1518d..ecff83d 100644
= > > >>> --- a/drivers/scsi/ufs/ufshcd.h
= > > >>> +++ b/drivers/scsi/ufs/ufshcd.h
= > > >>> @@ -178,6 +178,7 @@ struct ufs_dev_cmd {
= > > >>>     * @tm_tag_wq: wait queue for free task management slots
= > > >>>     * @tm_condition: condition variable for task management
= > > >>>     * @tm_slots_in_use: bit map of task management request slots
= > > >>> in use
= > > >>> + * @pwr_done: completion for power mode change
= > > >>>     * @ufshcd_state: UFSHCD states
= > > >>>     * @eh_flags: Error handling flags
= > > >>>     * @intr_mask: Interrupt Mask Bits @@ -227,6 +228,8 @@ struct
= > > >>> ufs_hba {
= > > >>>    	unsigned long tm_condition;
= > > >>>    	unsigned long tm_slots_in_use;
= > > >>>
= > > >>> +	struct completion *pwr_done;
= > > >>> +
= > > >>>    	u32 ufshcd_state;
= > > >>>    	u32 eh_flags;
= > > >>>    	u32 intr_mask;
= > > >>> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
= > > >>> index 1e1fe26..0475c66 100644
= > > >>> --- a/drivers/scsi/ufs/ufshci.h
= > > >>> +++ b/drivers/scsi/ufs/ufshci.h
= > > >>> @@ -124,6 +124,9 @@ enum {
= > > >>>    #define CONTROLLER_FATAL_ERROR
= > 	UFS_BIT(16)
= > > >>>    #define SYSTEM_BUS_FATAL_ERROR
= > 	UFS_BIT(17)
= > > >>>
= > > >>> +#define UFSHCD_UIC_MASK		(UIC_COMMAND_COMPL
= > |\
= > > >>> +				 UIC_POWER_MODE)
= > > >>> +
= > > >>>    #define UFSHCD_ERROR_MASK	(UIC_ERROR |\
= > > >>>    				DEVICE_FATAL_ERROR |\
= > > >>>    				CONTROLLER_FATAL_ERROR |\
= > > >>> @@ -142,6 +145,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
= > > >> --
= > > >> To unsubscribe from this list: send the line "unsubscribe
= > > >> linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx
= > > >> 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 majordomo@xxxxxxxxxxxxxxx
= > > > 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 majordomo@xxxxxxxxxxxxxxx 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 majordomo@xxxxxxxxxxxxxxx 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux