public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 5/5] scsi: ufs: add dme operations
@ 2013-04-24 16:06 Seungwon Jeon
  2013-05-01  7:52 ` merez
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Seungwon Jeon @ 2013-04-24 16:06 UTC (permalink / raw)
  To: linux-scsi
  Cc: 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

Add uic command operations including DME_XXX series.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
---
 drivers/scsi/ufs/ufs-attrs.h |  129 ++++++++++++++++++++++++
 drivers/scsi/ufs/ufshcd.c    |  220 +++++++++++++++++++++++++++++++++++++++++-
 drivers/scsi/ufs/ufshcd.h    |   55 +++++++++++
 drivers/scsi/ufs/ufshci.h    |   19 ++++
 4 files changed, 422 insertions(+), 1 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-attrs.h

diff --git a/drivers/scsi/ufs/ufs-attrs.h b/drivers/scsi/ufs/ufs-attrs.h
new file mode 100644
index 0000000..562bb49
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-attrs.h
@@ -0,0 +1,129 @@
+/*
+ * drivers/scsi/ufs/ufs-attrs.h
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _UFS_ATTRS_H_
+#define _UFS_ATTRS_H_
+
+/*
+ * PHY Adpater attributes
+ */
+#define PA_ACTIVETXDATALANES	0x1560
+#define PA_ACTIVERXDATALANES	0x1580
+#define PA_TXTRAILINGCLOCKS	0x1564
+#define PA_PHY_TYPE		0x1500
+#define PA_AVAILTXDATALANES	0x1520
+#define PA_AVAILRXDATALANES	0x1540
+#define PA_MINRXTRAILINGCLOCKS	0x1543
+#define PA_TXPWRSTATUS		0x1567
+#define PA_RXPWRSTATUS		0x1582
+#define PA_TXFORCECLOCK		0x1562
+#define PA_TXPWRMODE		0x1563
+#define PA_LEGACYDPHYESCDL	0x1570
+#define PA_MAXTXSPEEDFAST	0x1521
+#define PA_MAXTXSPEEDSLOW	0x1522
+#define PA_MAXRXSPEEDFAST	0x1541
+#define PA_MAXRXSPEEDSLOW	0x1542
+#define PA_TXLINKSTARTUPHS	0x1544
+#define PA_TXSPEEDFAST		0x1565
+#define PA_TXSPEEDSLOW		0x1566
+#define PA_REMOTEVERINFO	0x15A0
+#define PA_TXGEAR		0x1568
+#define PA_TXTERMINATION	0x1569
+#define PA_HSSERIES		0x156A
+#define PA_PWRMODE		0x1571
+#define PA_RXGEAR		0x1583
+#define PA_RXTERMINATION	0x1584
+#define PA_MAXRXPWMGEAR		0x1586
+#define PA_MAXRXHSGEAR		0x1587
+#define PA_RXHSUNTERMCAP	0x15A5
+#define PA_RXLSTERMCAP		0x15A6
+#define PA_PACPREQTIMEOUT	0x1590
+#define PA_PACPREQEOBTIMEOUT	0x1591
+#define PA_LOCALVERINFO		0x15A9
+#define PA_TACTIVATE		0x15A8
+#define PA_PACPFRAMECOUNT	0x15C0
+#define PA_PACPERRORCOUNT	0x15C1
+#define PA_PHYTESTCONTROL	0x15C2
+#define PA_PWRMODEUSERDATA0	0x15B0
+#define PA_PWRMODEUSERDATA1	0x15B1
+#define PA_PWRMODEUSERDATA2	0x15B2
+#define PA_PWRMODEUSERDATA3	0x15B3
+#define PA_PWRMODEUSERDATA4	0x15B4
+#define PA_PWRMODEUSERDATA5	0x15B5
+#define PA_PWRMODEUSERDATA6	0x15B6
+#define PA_PWRMODEUSERDATA7	0x15B7
+#define PA_PWRMODEUSERDATA8	0x15B8
+#define PA_PWRMODEUSERDATA9	0x15B9
+#define PA_PWRMODEUSERDATA10	0x15BA
+#define PA_PWRMODEUSERDATA11	0x15BB
+#define PA_CONNECTEDTXDATALANE	0x1561
+#define PA_CONNECTEDRXDATALANE	0x1581
+#define PA_LOGICALLANEMAP	0x15A1
+#define PA_SLEEPNOCONFIGTIME	0x15A2
+#define PA_STALLNOCONFIGTIME	0x15A3
+#define PA_SAVECONFIGTIME	0x15A4
+
+/*
+ * Data Link Layer Attributes
+ */
+#define DL_TC0TXFCTHRESHOLD	0x2040
+#define DL_FC0PROTTIMEOUTVAL	0x2041
+#define DL_TC0REPLAYTIMEOUTVAL	0x2042
+#define DL_AFC0REQTIMEOUTVAL	0x2043
+#define DL_AFC0CREDITTHRESHOLD	0x2044
+#define DL_TC0OUTACKTHRESHOLD	0x2045
+#define DL_TC1TXFCTHRESHOLD	0x2060
+#define DL_FC1PROTTIMEOUTVAL	0x2061
+#define DL_TC1REPLAYTIMEOUTVAL	0x2062
+#define DL_AFC1REQTIMEOUTVAL	0x2063
+#define DL_AFC1CREDITTHRESHOLD	0x2064
+#define DL_TC1OUTACKTHRESHOLD	0x2065
+#define DL_TXPREEMPTIONCAP	0x2000
+#define DL_TC0TXMAXSDUSIZE	0x2001
+#define DL_TC0RXINITCREDITVAL	0x2002
+#define DL_TC0TXBUFFERSIZE	0x2005
+#define DL_PEERTC0PRESENT	0x2046
+#define DL_PEERTC0RXINITCREVAL	0x2047
+#define DL_TC1TXMAXSDUSIZE	0x2003
+#define DL_TC1RXINITCREDITVAL	0x2004
+#define DL_TC1TXBUFFERSIZE	0x2006
+#define DL_PEERTC1PRESENT	0x2066
+#define DL_PEERTC1RXINITCREVAL	0x2067
+
+/*
+ * Network Layer Attributes
+ */
+#define N_DEVICEID		0x3000
+#define N_DEVICEID_VALID	0x3001
+#define N_TC0TXMAXSDUSIZE	0x3020
+#define N_TC1TXMAXSDUSIZE	0x3021
+
+/*
+ * Transport Layer Attributes
+ */
+#define T_NUMCPORTS		0x4000
+#define T_NUMTESTFEATURES	0x4001
+#define T_CONNECTIONSTATE	0x4020
+#define T_PEERDEVICEID		0x4021
+#define T_PEERCPORTID		0x4022
+#define T_TRAFFICCLASS		0x4023
+#define T_PROTOCOLID		0x4024
+#define T_CPORTFLAGS		0x4025
+#define T_TXTOKENVALUE		0x4026
+#define T_RXTOKENVALUE		0x4027
+#define T_LOCALBUFFERSPACE	0x4028
+#define T_PEERBUFFERSPACE	0x4029
+#define T_CREDITSTOSEND		0x402A
+#define T_CPORTMODE		0x402B
+#define T_TC0TXMAXSDUSIZE	0x4060
+#define T_TC1TXMAXSDUSIZE	0x4061
+
+#endif /* _UFS_ATTRS_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 76ff332..55575ea 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -37,6 +37,7 @@
 
 #define UFSHCD_ENABLE_INTRS	(UTP_TRANSFER_REQ_COMPL |\
 				 UTP_TASK_REQ_COMPL |\
+				 UFSHCD_HIBERNATE_MASK |\
 				 UFSHCD_ERROR_MASK)
 #define UIC_CMD_TIMEOUT	100
 
@@ -188,6 +189,31 @@ 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_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
@@ -804,6 +830,195 @@ 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
+ *
+ * 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;
+	static const char *const action[] = {
+		"dme-set", "dme-peer-set"
+	};
+	const char *set = action[!!peer];
+	unsigned long flags;
+	int ret;
+
+	if (!ufshcd_ready_uic_cmd(hba))
+		return -EIO;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+
+	/* form UIC command */
+	uic_cmd = &hba->active_uic_cmd;
+	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;
+
+	/* dispatch UIC commands to controller */
+	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ret = ufshcd_wait_for_uic_cmd(hba);
+	dev_dbg(hba->dev, "%s: error code %d returned\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
+ *
+ * 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;
+	static const char *const action[] = {
+		"dme-get", "dme-peer-get"
+	};
+	const char *get = action[!!peer];
+	unsigned long flags;
+	int ret;
+
+	if (!ufshcd_ready_uic_cmd(hba))
+		return -EIO;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+
+	/* form UIC command */
+	uic_cmd = &hba->active_uic_cmd;
+	uic_cmd->command = peer ?
+		UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
+	uic_cmd->argument1 = attr_sel;
+	uic_cmd->argument2 = 0;
+	uic_cmd->argument3 = 0;
+
+	/* dispatch UIC commands to controller */
+	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ret = ufshcd_wait_for_uic_cmd(hba);
+	if (mib_val)
+		*mib_val = ufshcd_get_dme_attr_val(hba);
+
+	dev_dbg(hba->dev, "%s: error code %d returned\n", get, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ufshcd_dme_xxx_get);
+
+/**
+ * ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF
+ * @hba: per adapter instance
+ *
+ * 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;
+	static const char *const action[] = {
+		"dme-power-on",
+		"dme-power-off",
+	};
+	const char *power = action[!!on];
+	unsigned long flags;
+	int ret;
+
+	if (!ufshcd_ready_uic_cmd(hba))
+		return -EIO;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+
+	/* form UIC command */
+	uic_cmd = &hba->active_uic_cmd;
+	uic_cmd->command = on ?
+		UIC_CMD_DME_POWERON : UIC_CMD_DME_POWEROFF;
+	uic_cmd->argument1 = 0;
+	uic_cmd->argument2 = 0;
+	uic_cmd->argument3 = 0;
+
+	/* dispatch UIC commands to controller */
+	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ret = ufshcd_wait_for_uic_cmd(hba);
+	if (ret)
+		dev_err(hba->dev, "%s: error code %d returned\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
+ *
+ * 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;
+	static const char *const action[] = {
+		"dme-hibernate-enter",
+		"dme-hibernate-exit"
+	};
+	const char *hibern8 = action[!!enter];
+	unsigned long flags;
+	u8 status;
+	int ret;
+
+	if (!ufshcd_ready_uic_cmd(hba))
+		return -EIO;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+
+	/* form UIC command */
+	uic_cmd = &hba->active_uic_cmd;
+	uic_cmd->command = enter ?
+		UIC_CMD_DME_HIBER_ENTER : UIC_CMD_DME_HIBER_EXIT;
+	uic_cmd->argument1 = 0;
+	uic_cmd->argument2 = 0;
+	uic_cmd->argument3 = 0;
+
+	/* dispatch UIC commands to controller */
+	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ret= ufshcd_wait_for_uic_cmd(hba);
+	if (ret) {
+		dev_err(hba->dev, "%s: error code %d returned\n", hibern8, ret);
+		goto out;
+	}
+
+	init_completion(&hba->hibern8_done);
+
+	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:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ufshcd_dme_hibern8_xxx);
+
+/**
  * ufshcd_make_hba_operational - Make UFS controller operational
  * @hba: per adapter instance
  *
@@ -1238,6 +1453,9 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
 {
 	if (intr_status & UIC_COMMAND_COMPL)
 		complete(&hba->active_uic_cmd.done);
+
+	if (intr_status & UFSHCD_HIBERNATE_MASK)
+		complete(&hba->hibern8_done);
 }
 
 /**
@@ -1362,7 +1580,7 @@ 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)
+	if (intr_status & UFSHCD_UIC_MASK)
 		ufshcd_uic_cmd_compl(hba, intr_status);
 
 	if (intr_status & UTP_TASK_REQ_COMPL)
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 2fb4d94..5bf19f5 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -140,6 +140,7 @@ struct ufshcd_lrb {
  * @active_uic_cmd: handle of active 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
  * @link_startup_wq: Work queue for link start-up
@@ -177,6 +178,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;
 
@@ -197,4 +200,56 @@ void ufshcd_remove(struct ufs_hba *);
 #define ufshcd_readl(hba, reg)	\
 	readl((hba)->mmio_base + (reg))
 
+
+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);
+
+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);
+}
+
+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, u8 enter)
+{
+	return ufshcd_dme_hibern8_xxx(hba, 1);
+}
+
+static inline int ufshcd_dme_hibern8_exit(struct ufs_hba *hba, u8 enter)
+{
+	return ufshcd_dme_hibern8_xxx(hba, 0);
+}
+
 #endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index d5c5f14..28ede2a 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -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
@@ -191,6 +206,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,
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 5/5] scsi: ufs: add dme operations
  2013-04-24 16:06 [PATCH 5/5] scsi: ufs: add dme operations Seungwon Jeon
@ 2013-05-01  7:52 ` merez
  2013-05-02  8:06 ` Santosh Y
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: merez @ 2013-05-01  7:52 UTC (permalink / raw)
  To: Seungwon Jeon
  Cc: linux-scsi, 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

Tested-by: Maya Erez <merez@codeaurora.org>

> Add uic command operations including DME_XXX series.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> ---
>  drivers/scsi/ufs/ufs-attrs.h |  129 ++++++++++++++++++++++++
>  drivers/scsi/ufs/ufshcd.c    |  220
> +++++++++++++++++++++++++++++++++++++++++-
>  drivers/scsi/ufs/ufshcd.h    |   55 +++++++++++
>  drivers/scsi/ufs/ufshci.h    |   19 ++++
>  4 files changed, 422 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/scsi/ufs/ufs-attrs.h
>
> diff --git a/drivers/scsi/ufs/ufs-attrs.h b/drivers/scsi/ufs/ufs-attrs.h
> new file mode 100644
> index 0000000..562bb49
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufs-attrs.h
> @@ -0,0 +1,129 @@
> +/*
> + * drivers/scsi/ufs/ufs-attrs.h
> + *
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef _UFS_ATTRS_H_
> +#define _UFS_ATTRS_H_
> +
> +/*
> + * PHY Adpater attributes
> + */
> +#define PA_ACTIVETXDATALANES	0x1560
> +#define PA_ACTIVERXDATALANES	0x1580
> +#define PA_TXTRAILINGCLOCKS	0x1564
> +#define PA_PHY_TYPE		0x1500
> +#define PA_AVAILTXDATALANES	0x1520
> +#define PA_AVAILRXDATALANES	0x1540
> +#define PA_MINRXTRAILINGCLOCKS	0x1543
> +#define PA_TXPWRSTATUS		0x1567
> +#define PA_RXPWRSTATUS		0x1582
> +#define PA_TXFORCECLOCK		0x1562
> +#define PA_TXPWRMODE		0x1563
> +#define PA_LEGACYDPHYESCDL	0x1570
> +#define PA_MAXTXSPEEDFAST	0x1521
> +#define PA_MAXTXSPEEDSLOW	0x1522
> +#define PA_MAXRXSPEEDFAST	0x1541
> +#define PA_MAXRXSPEEDSLOW	0x1542
> +#define PA_TXLINKSTARTUPHS	0x1544
> +#define PA_TXSPEEDFAST		0x1565
> +#define PA_TXSPEEDSLOW		0x1566
> +#define PA_REMOTEVERINFO	0x15A0
> +#define PA_TXGEAR		0x1568
> +#define PA_TXTERMINATION	0x1569
> +#define PA_HSSERIES		0x156A
> +#define PA_PWRMODE		0x1571
> +#define PA_RXGEAR		0x1583
> +#define PA_RXTERMINATION	0x1584
> +#define PA_MAXRXPWMGEAR		0x1586
> +#define PA_MAXRXHSGEAR		0x1587
> +#define PA_RXHSUNTERMCAP	0x15A5
> +#define PA_RXLSTERMCAP		0x15A6
> +#define PA_PACPREQTIMEOUT	0x1590
> +#define PA_PACPREQEOBTIMEOUT	0x1591
> +#define PA_LOCALVERINFO		0x15A9
> +#define PA_TACTIVATE		0x15A8
> +#define PA_PACPFRAMECOUNT	0x15C0
> +#define PA_PACPERRORCOUNT	0x15C1
> +#define PA_PHYTESTCONTROL	0x15C2
> +#define PA_PWRMODEUSERDATA0	0x15B0
> +#define PA_PWRMODEUSERDATA1	0x15B1
> +#define PA_PWRMODEUSERDATA2	0x15B2
> +#define PA_PWRMODEUSERDATA3	0x15B3
> +#define PA_PWRMODEUSERDATA4	0x15B4
> +#define PA_PWRMODEUSERDATA5	0x15B5
> +#define PA_PWRMODEUSERDATA6	0x15B6
> +#define PA_PWRMODEUSERDATA7	0x15B7
> +#define PA_PWRMODEUSERDATA8	0x15B8
> +#define PA_PWRMODEUSERDATA9	0x15B9
> +#define PA_PWRMODEUSERDATA10	0x15BA
> +#define PA_PWRMODEUSERDATA11	0x15BB
> +#define PA_CONNECTEDTXDATALANE	0x1561
> +#define PA_CONNECTEDRXDATALANE	0x1581
> +#define PA_LOGICALLANEMAP	0x15A1
> +#define PA_SLEEPNOCONFIGTIME	0x15A2
> +#define PA_STALLNOCONFIGTIME	0x15A3
> +#define PA_SAVECONFIGTIME	0x15A4
> +
> +/*
> + * Data Link Layer Attributes
> + */
> +#define DL_TC0TXFCTHRESHOLD	0x2040
> +#define DL_FC0PROTTIMEOUTVAL	0x2041
> +#define DL_TC0REPLAYTIMEOUTVAL	0x2042
> +#define DL_AFC0REQTIMEOUTVAL	0x2043
> +#define DL_AFC0CREDITTHRESHOLD	0x2044
> +#define DL_TC0OUTACKTHRESHOLD	0x2045
> +#define DL_TC1TXFCTHRESHOLD	0x2060
> +#define DL_FC1PROTTIMEOUTVAL	0x2061
> +#define DL_TC1REPLAYTIMEOUTVAL	0x2062
> +#define DL_AFC1REQTIMEOUTVAL	0x2063
> +#define DL_AFC1CREDITTHRESHOLD	0x2064
> +#define DL_TC1OUTACKTHRESHOLD	0x2065
> +#define DL_TXPREEMPTIONCAP	0x2000
> +#define DL_TC0TXMAXSDUSIZE	0x2001
> +#define DL_TC0RXINITCREDITVAL	0x2002
> +#define DL_TC0TXBUFFERSIZE	0x2005
> +#define DL_PEERTC0PRESENT	0x2046
> +#define DL_PEERTC0RXINITCREVAL	0x2047
> +#define DL_TC1TXMAXSDUSIZE	0x2003
> +#define DL_TC1RXINITCREDITVAL	0x2004
> +#define DL_TC1TXBUFFERSIZE	0x2006
> +#define DL_PEERTC1PRESENT	0x2066
> +#define DL_PEERTC1RXINITCREVAL	0x2067
> +
> +/*
> + * Network Layer Attributes
> + */
> +#define N_DEVICEID		0x3000
> +#define N_DEVICEID_VALID	0x3001
> +#define N_TC0TXMAXSDUSIZE	0x3020
> +#define N_TC1TXMAXSDUSIZE	0x3021
> +
> +/*
> + * Transport Layer Attributes
> + */
> +#define T_NUMCPORTS		0x4000
> +#define T_NUMTESTFEATURES	0x4001
> +#define T_CONNECTIONSTATE	0x4020
> +#define T_PEERDEVICEID		0x4021
> +#define T_PEERCPORTID		0x4022
> +#define T_TRAFFICCLASS		0x4023
> +#define T_PROTOCOLID		0x4024
> +#define T_CPORTFLAGS		0x4025
> +#define T_TXTOKENVALUE		0x4026
> +#define T_RXTOKENVALUE		0x4027
> +#define T_LOCALBUFFERSPACE	0x4028
> +#define T_PEERBUFFERSPACE	0x4029
> +#define T_CREDITSTOSEND		0x402A
> +#define T_CPORTMODE		0x402B
> +#define T_TC0TXMAXSDUSIZE	0x4060
> +#define T_TC1TXMAXSDUSIZE	0x4061
> +
> +#endif /* _UFS_ATTRS_H_ */
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 76ff332..55575ea 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -37,6 +37,7 @@
>
>  #define UFSHCD_ENABLE_INTRS	(UTP_TRANSFER_REQ_COMPL |\
>  				 UTP_TASK_REQ_COMPL |\
> +				 UFSHCD_HIBERNATE_MASK |\
>  				 UFSHCD_ERROR_MASK)
>  #define UIC_CMD_TIMEOUT	100
>
> @@ -188,6 +189,31 @@ 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_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
> @@ -804,6 +830,195 @@ 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
> + *
> + * 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;
> +	static const char *const action[] = {
> +		"dme-set", "dme-peer-set"
> +	};
> +	const char *set = action[!!peer];
> +	unsigned long flags;
> +	int ret;
> +
> +	if (!ufshcd_ready_uic_cmd(hba))
> +		return -EIO;
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +
> +	/* form UIC command */
> +	uic_cmd = &hba->active_uic_cmd;
> +	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;
> +
> +	/* dispatch UIC commands to controller */
> +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	ret = ufshcd_wait_for_uic_cmd(hba);
> +	dev_dbg(hba->dev, "%s: error code %d returned\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
> + *
> + * 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;
> +	static const char *const action[] = {
> +		"dme-get", "dme-peer-get"
> +	};
> +	const char *get = action[!!peer];
> +	unsigned long flags;
> +	int ret;
> +
> +	if (!ufshcd_ready_uic_cmd(hba))
> +		return -EIO;
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +
> +	/* form UIC command */
> +	uic_cmd = &hba->active_uic_cmd;
> +	uic_cmd->command = peer ?
> +		UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
> +	uic_cmd->argument1 = attr_sel;
> +	uic_cmd->argument2 = 0;
> +	uic_cmd->argument3 = 0;
> +
> +	/* dispatch UIC commands to controller */
> +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	ret = ufshcd_wait_for_uic_cmd(hba);
> +	if (mib_val)
> +		*mib_val = ufshcd_get_dme_attr_val(hba);
> +
> +	dev_dbg(hba->dev, "%s: error code %d returned\n", get, ret);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_xxx_get);
> +
> +/**
> + * ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF
> + * @hba: per adapter instance
> + *
> + * 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;
> +	static const char *const action[] = {
> +		"dme-power-on",
> +		"dme-power-off",
> +	};
> +	const char *power = action[!!on];
> +	unsigned long flags;
> +	int ret;
> +
> +	if (!ufshcd_ready_uic_cmd(hba))
> +		return -EIO;
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +
> +	/* form UIC command */
> +	uic_cmd = &hba->active_uic_cmd;
> +	uic_cmd->command = on ?
> +		UIC_CMD_DME_POWERON : UIC_CMD_DME_POWEROFF;
> +	uic_cmd->argument1 = 0;
> +	uic_cmd->argument2 = 0;
> +	uic_cmd->argument3 = 0;
> +
> +	/* dispatch UIC commands to controller */
> +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> +
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	ret = ufshcd_wait_for_uic_cmd(hba);
> +	if (ret)
> +		dev_err(hba->dev, "%s: error code %d returned\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
> + *
> + * 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;
> +	static const char *const action[] = {
> +		"dme-hibernate-enter",
> +		"dme-hibernate-exit"
> +	};
> +	const char *hibern8 = action[!!enter];
> +	unsigned long flags;
> +	u8 status;
> +	int ret;
> +
> +	if (!ufshcd_ready_uic_cmd(hba))
> +		return -EIO;
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +
> +	/* form UIC command */
> +	uic_cmd = &hba->active_uic_cmd;
> +	uic_cmd->command = enter ?
> +		UIC_CMD_DME_HIBER_ENTER : UIC_CMD_DME_HIBER_EXIT;
> +	uic_cmd->argument1 = 0;
> +	uic_cmd->argument2 = 0;
> +	uic_cmd->argument3 = 0;
> +
> +	/* dispatch UIC commands to controller */
> +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> +
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	ret= ufshcd_wait_for_uic_cmd(hba);
> +	if (ret) {
> +		dev_err(hba->dev, "%s: error code %d returned\n", hibern8, ret);
> +		goto out;
> +	}
> +
> +	init_completion(&hba->hibern8_done);
> +
> +	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:
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_hibern8_xxx);
> +
> +/**
>   * ufshcd_make_hba_operational - Make UFS controller operational
>   * @hba: per adapter instance
>   *
> @@ -1238,6 +1453,9 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba
> *hba, u32 intr_status)
>  {
>  	if (intr_status & UIC_COMMAND_COMPL)
>  		complete(&hba->active_uic_cmd.done);
> +
> +	if (intr_status & UFSHCD_HIBERNATE_MASK)
> +		complete(&hba->hibern8_done);
>  }
>
>  /**
> @@ -1362,7 +1580,7 @@ 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)
> +	if (intr_status & UFSHCD_UIC_MASK)
>  		ufshcd_uic_cmd_compl(hba, intr_status);
>
>  	if (intr_status & UTP_TASK_REQ_COMPL)
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 2fb4d94..5bf19f5 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -140,6 +140,7 @@ struct ufshcd_lrb {
>   * @active_uic_cmd: handle of active 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
>   * @link_startup_wq: Work queue for link start-up
> @@ -177,6 +178,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;
>
> @@ -197,4 +200,56 @@ void ufshcd_remove(struct ufs_hba *);
>  #define ufshcd_readl(hba, reg)	\
>  	readl((hba)->mmio_base + (reg))
>
> +
> +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);
> +
> +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);
> +}
> +
> +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, u8 enter)
> +{
> +	return ufshcd_dme_hibern8_xxx(hba, 1);
> +}
> +
> +static inline int ufshcd_dme_hibern8_exit(struct ufs_hba *hba, u8 enter)
> +{
> +	return ufshcd_dme_hibern8_xxx(hba, 0);
> +}
> +
>  #endif /* End of Header */
> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
> index d5c5f14..28ede2a 100644
> --- a/drivers/scsi/ufs/ufshci.h
> +++ b/drivers/scsi/ufs/ufshci.h
> @@ -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
> @@ -191,6 +206,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,
> --
> 1.7.0.4
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> 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


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 5/5] scsi: ufs: add dme operations
  2013-04-24 16:06 [PATCH 5/5] scsi: ufs: add dme operations Seungwon Jeon
  2013-05-01  7:52 ` merez
@ 2013-05-02  8:06 ` Santosh Y
  2013-05-02  8:07   ` Santosh Y
  2013-05-02 12:08 ` Subhash Jadavani
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Santosh Y @ 2013-05-02  8:06 UTC (permalink / raw)
  To: Seungwon Jeon; +Cc: linux-scsi, Vinayak Holikatti, James E.J. Bottomley

> +/*
> + * drivers/scsi/ufs/ufs-attrs.h
> + *
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef _UFS_ATTRS_H_
> +#define _UFS_ATTRS_H_
> +
> +/*
> + * PHY Adpater attributes
> + */
> +#define PA_ACTIVETXDATALANES   0x1560
> +#define PA_ACTIVERXDATALANES   0x1580
> +#define PA_TXTRAILINGCLOCKS    0x1564
> +#define PA_PHY_TYPE            0x1500
> +#define PA_AVAILTXDATALANES    0x1520
> +#define PA_AVAILRXDATALANES    0x1540
> +#define PA_MINRXTRAILINGCLOCKS 0x1543
> +#define PA_TXPWRSTATUS         0x1567
> +#define PA_RXPWRSTATUS         0x1582
> +#define PA_TXFORCECLOCK                0x1562
> +#define PA_TXPWRMODE           0x1563
> +#define PA_LEGACYDPHYESCDL     0x1570
> +#define PA_MAXTXSPEEDFAST      0x1521
> +#define PA_MAXTXSPEEDSLOW      0x1522
> +#define PA_MAXRXSPEEDFAST      0x1541
> +#define PA_MAXRXSPEEDSLOW      0x1542
> +#define PA_TXLINKSTARTUPHS     0x1544
> +#define PA_TXSPEEDFAST         0x1565
> +#define PA_TXSPEEDSLOW         0x1566
> +#define PA_REMOTEVERINFO       0x15A0
> +#define PA_TXGEAR              0x1568
> +#define PA_TXTERMINATION       0x1569
> +#define PA_HSSERIES            0x156A
> +#define PA_PWRMODE             0x1571
> +#define PA_RXGEAR              0x1583
> +#define PA_RXTERMINATION       0x1584
> +#define PA_MAXRXPWMGEAR                0x1586
> +#define PA_MAXRXHSGEAR         0x1587
> +#define PA_RXHSUNTERMCAP       0x15A5
> +#define PA_RXLSTERMCAP         0x15A6
> +#define PA_PACPREQTIMEOUT      0x1590
> +#define PA_PACPREQEOBTIMEOUT   0x1591
> +#define PA_LOCALVERINFO                0x15A9
> +#define PA_TACTIVATE           0x15A8
> +#define PA_PACPFRAMECOUNT      0x15C0
> +#define PA_PACPERRORCOUNT      0x15C1
> +#define PA_PHYTESTCONTROL      0x15C2
> +#define PA_PWRMODEUSERDATA0    0x15B0
> +#define PA_PWRMODEUSERDATA1    0x15B1
> +#define PA_PWRMODEUSERDATA2    0x15B2
> +#define PA_PWRMODEUSERDATA3    0x15B3
> +#define PA_PWRMODEUSERDATA4    0x15B4
> +#define PA_PWRMODEUSERDATA5    0x15B5
> +#define PA_PWRMODEUSERDATA6    0x15B6
> +#define PA_PWRMODEUSERDATA7    0x15B7
> +#define PA_PWRMODEUSERDATA8    0x15B8
> +#define PA_PWRMODEUSERDATA9    0x15B9
> +#define PA_PWRMODEUSERDATA10   0x15BA
> +#define PA_PWRMODEUSERDATA11   0x15BB
> +#define PA_CONNECTEDTXDATALANE 0x1561
> +#define PA_CONNECTEDRXDATALANE 0x1581
> +#define PA_LOGICALLANEMAP      0x15A1
> +#define PA_SLEEPNOCONFIGTIME   0x15A2
> +#define PA_STALLNOCONFIGTIME   0x15A3
> +#define PA_SAVECONFIGTIME      0x15A4
> +
> +/*
> + * Data Link Layer Attributes
> + */
> +#define DL_TC0TXFCTHRESHOLD    0x2040
> +#define DL_FC0PROTTIMEOUTVAL   0x2041
> +#define DL_TC0REPLAYTIMEOUTVAL 0x2042
> +#define DL_AFC0REQTIMEOUTVAL   0x2043
> +#define DL_AFC0CREDITTHRESHOLD 0x2044
> +#define DL_TC0OUTACKTHRESHOLD  0x2045
> +#define DL_TC1TXFCTHRESHOLD    0x2060
> +#define DL_FC1PROTTIMEOUTVAL   0x2061
> +#define DL_TC1REPLAYTIMEOUTVAL 0x2062
> +#define DL_AFC1REQTIMEOUTVAL   0x2063
> +#define DL_AFC1CREDITTHRESHOLD 0x2064
> +#define DL_TC1OUTACKTHRESHOLD  0x2065
> +#define DL_TXPREEMPTIONCAP     0x2000
> +#define DL_TC0TXMAXSDUSIZE     0x2001
> +#define DL_TC0RXINITCREDITVAL  0x2002
> +#define DL_TC0TXBUFFERSIZE     0x2005
> +#define DL_PEERTC0PRESENT      0x2046
> +#define DL_PEERTC0RXINITCREVAL 0x2047
> +#define DL_TC1TXMAXSDUSIZE     0x2003
> +#define DL_TC1RXINITCREDITVAL  0x2004
> +#define DL_TC1TXBUFFERSIZE     0x2006
> +#define DL_PEERTC1PRESENT      0x2066
> +#define DL_PEERTC1RXINITCREVAL 0x2067
> +
> +/*
> + * Network Layer Attributes
> + */
> +#define N_DEVICEID             0x3000
> +#define N_DEVICEID_VALID       0x3001
> +#define N_TC0TXMAXSDUSIZE      0x3020
> +#define N_TC1TXMAXSDUSIZE      0x3021
> +
> +/*
> + * Transport Layer Attributes
> + */
> +#define T_NUMCPORTS            0x4000
> +#define T_NUMTESTFEATURES      0x4001
> +#define T_CONNECTIONSTATE      0x4020
> +#define T_PEERDEVICEID         0x4021
> +#define T_PEERCPORTID          0x4022
> +#define T_TRAFFICCLASS         0x4023
> +#define T_PROTOCOLID           0x4024
> +#define T_CPORTFLAGS           0x4025
> +#define T_TXTOKENVALUE         0x4026
> +#define T_RXTOKENVALUE         0x4027
> +#define T_LOCALBUFFERSPACE     0x4028
> +#define T_PEERBUFFERSPACE      0x4029
> +#define T_CREDITSTOSEND                0x402A
> +#define T_CPORTMODE            0x402B
> +#define T_TC0TXMAXSDUSIZE      0x4060
> +#define T_TC1TXMAXSDUSIZE      0x4061
> +
> +#endif /* _UFS_ATTRS_H_ */


These are Unipro. So change the name of the file to unipro.h

> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 76ff332..55575ea 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -37,6 +37,7 @@
>
>  #define UFSHCD_ENABLE_INTRS    (UTP_TRANSFER_REQ_COMPL |\
>                                  UTP_TASK_REQ_COMPL |\
> +                                UFSHCD_HIBERNATE_MASK |\
>                                  UFSHCD_ERROR_MASK)
>  #define UIC_CMD_TIMEOUT        100
>
> @@ -188,6 +189,31 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
>  }
>


-- 
~Santosh

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 5/5] scsi: ufs: add dme operations
  2013-05-02  8:06 ` Santosh Y
@ 2013-05-02  8:07   ` Santosh Y
  2013-05-02 13:38     ` Seungwon Jeon
  0 siblings, 1 reply; 14+ messages in thread
From: Santosh Y @ 2013-05-02  8:07 UTC (permalink / raw)
  To: Seungwon Jeon; +Cc: linux-scsi, Vinayak Holikatti, James E.J. Bottomley

On Thu, May 2, 2013 at 1:36 PM, Santosh Y <santoshsy@gmail.com> wrote:
>> +/*
>> + * drivers/scsi/ufs/ufs-attrs.h
>> + *
>> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + */
>> +
>> +#ifndef _UFS_ATTRS_H_
>> +#define _UFS_ATTRS_H_
>> +
>> +/*
>> + * PHY Adpater attributes
>> + */
>> +#define PA_ACTIVETXDATALANES   0x1560
>> +#define PA_ACTIVERXDATALANES   0x1580
>> +#define PA_TXTRAILINGCLOCKS    0x1564
>> +#define PA_PHY_TYPE            0x1500
>> +#define PA_AVAILTXDATALANES    0x1520
>> +#define PA_AVAILRXDATALANES    0x1540
>> +#define PA_MINRXTRAILINGCLOCKS 0x1543
>> +#define PA_TXPWRSTATUS         0x1567
>> +#define PA_RXPWRSTATUS         0x1582
>> +#define PA_TXFORCECLOCK                0x1562
>> +#define PA_TXPWRMODE           0x1563
>> +#define PA_LEGACYDPHYESCDL     0x1570
>> +#define PA_MAXTXSPEEDFAST      0x1521
>> +#define PA_MAXTXSPEEDSLOW      0x1522
>> +#define PA_MAXRXSPEEDFAST      0x1541
>> +#define PA_MAXRXSPEEDSLOW      0x1542
>> +#define PA_TXLINKSTARTUPHS     0x1544
>> +#define PA_TXSPEEDFAST         0x1565
>> +#define PA_TXSPEEDSLOW         0x1566
>> +#define PA_REMOTEVERINFO       0x15A0
>> +#define PA_TXGEAR              0x1568
>> +#define PA_TXTERMINATION       0x1569
>> +#define PA_HSSERIES            0x156A
>> +#define PA_PWRMODE             0x1571
>> +#define PA_RXGEAR              0x1583
>> +#define PA_RXTERMINATION       0x1584
>> +#define PA_MAXRXPWMGEAR                0x1586
>> +#define PA_MAXRXHSGEAR         0x1587
>> +#define PA_RXHSUNTERMCAP       0x15A5
>> +#define PA_RXLSTERMCAP         0x15A6
>> +#define PA_PACPREQTIMEOUT      0x1590
>> +#define PA_PACPREQEOBTIMEOUT   0x1591
>> +#define PA_LOCALVERINFO                0x15A9
>> +#define PA_TACTIVATE           0x15A8
>> +#define PA_PACPFRAMECOUNT      0x15C0
>> +#define PA_PACPERRORCOUNT      0x15C1
>> +#define PA_PHYTESTCONTROL      0x15C2
>> +#define PA_PWRMODEUSERDATA0    0x15B0
>> +#define PA_PWRMODEUSERDATA1    0x15B1
>> +#define PA_PWRMODEUSERDATA2    0x15B2
>> +#define PA_PWRMODEUSERDATA3    0x15B3
>> +#define PA_PWRMODEUSERDATA4    0x15B4
>> +#define PA_PWRMODEUSERDATA5    0x15B5
>> +#define PA_PWRMODEUSERDATA6    0x15B6
>> +#define PA_PWRMODEUSERDATA7    0x15B7
>> +#define PA_PWRMODEUSERDATA8    0x15B8
>> +#define PA_PWRMODEUSERDATA9    0x15B9
>> +#define PA_PWRMODEUSERDATA10   0x15BA
>> +#define PA_PWRMODEUSERDATA11   0x15BB
>> +#define PA_CONNECTEDTXDATALANE 0x1561
>> +#define PA_CONNECTEDRXDATALANE 0x1581
>> +#define PA_LOGICALLANEMAP      0x15A1
>> +#define PA_SLEEPNOCONFIGTIME   0x15A2
>> +#define PA_STALLNOCONFIGTIME   0x15A3
>> +#define PA_SAVECONFIGTIME      0x15A4
>> +
>> +/*
>> + * Data Link Layer Attributes
>> + */
>> +#define DL_TC0TXFCTHRESHOLD    0x2040
>> +#define DL_FC0PROTTIMEOUTVAL   0x2041
>> +#define DL_TC0REPLAYTIMEOUTVAL 0x2042
>> +#define DL_AFC0REQTIMEOUTVAL   0x2043
>> +#define DL_AFC0CREDITTHRESHOLD 0x2044
>> +#define DL_TC0OUTACKTHRESHOLD  0x2045
>> +#define DL_TC1TXFCTHRESHOLD    0x2060
>> +#define DL_FC1PROTTIMEOUTVAL   0x2061
>> +#define DL_TC1REPLAYTIMEOUTVAL 0x2062
>> +#define DL_AFC1REQTIMEOUTVAL   0x2063
>> +#define DL_AFC1CREDITTHRESHOLD 0x2064
>> +#define DL_TC1OUTACKTHRESHOLD  0x2065
>> +#define DL_TXPREEMPTIONCAP     0x2000
>> +#define DL_TC0TXMAXSDUSIZE     0x2001
>> +#define DL_TC0RXINITCREDITVAL  0x2002
>> +#define DL_TC0TXBUFFERSIZE     0x2005
>> +#define DL_PEERTC0PRESENT      0x2046
>> +#define DL_PEERTC0RXINITCREVAL 0x2047
>> +#define DL_TC1TXMAXSDUSIZE     0x2003
>> +#define DL_TC1RXINITCREDITVAL  0x2004
>> +#define DL_TC1TXBUFFERSIZE     0x2006
>> +#define DL_PEERTC1PRESENT      0x2066
>> +#define DL_PEERTC1RXINITCREVAL 0x2067
>> +
>> +/*
>> + * Network Layer Attributes
>> + */
>> +#define N_DEVICEID             0x3000
>> +#define N_DEVICEID_VALID       0x3001
>> +#define N_TC0TXMAXSDUSIZE      0x3020
>> +#define N_TC1TXMAXSDUSIZE      0x3021
>> +
>> +/*
>> + * Transport Layer Attributes
>> + */
>> +#define T_NUMCPORTS            0x4000
>> +#define T_NUMTESTFEATURES      0x4001
>> +#define T_CONNECTIONSTATE      0x4020
>> +#define T_PEERDEVICEID         0x4021
>> +#define T_PEERCPORTID          0x4022
>> +#define T_TRAFFICCLASS         0x4023
>> +#define T_PROTOCOLID           0x4024
>> +#define T_CPORTFLAGS           0x4025
>> +#define T_TXTOKENVALUE         0x4026
>> +#define T_RXTOKENVALUE         0x4027
>> +#define T_LOCALBUFFERSPACE     0x4028
>> +#define T_PEERBUFFERSPACE      0x4029
>> +#define T_CREDITSTOSEND                0x402A
>> +#define T_CPORTMODE            0x402B
>> +#define T_TC0TXMAXSDUSIZE      0x4060
>> +#define T_TC1TXMAXSDUSIZE      0x4061
>> +
>> +#endif /* _UFS_ATTRS_H_ */
>
>
> These are Unipro. So change the name of the file to unipro.h
>
 I meant Unipro attributes, So change the name accordingly.

>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index 76ff332..55575ea 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -37,6 +37,7 @@
>>
>>  #define UFSHCD_ENABLE_INTRS    (UTP_TRANSFER_REQ_COMPL |\
>>                                  UTP_TASK_REQ_COMPL |\
>> +                                UFSHCD_HIBERNATE_MASK |\
>>                                  UFSHCD_ERROR_MASK)
>>  #define UIC_CMD_TIMEOUT        100
>>
>> @@ -188,6 +189,31 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
>>  }
>>
>
>
> --
> ~Santosh



-- 
~Santosh

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 5/5] scsi: ufs: add dme operations
  2013-04-24 16:06 [PATCH 5/5] scsi: ufs: add dme operations Seungwon Jeon
  2013-05-01  7:52 ` merez
  2013-05-02  8:06 ` Santosh Y
@ 2013-05-02 12:08 ` Subhash Jadavani
  2013-05-02 13:39   ` Seungwon Jeon
  2013-05-04  8:45 ` [PATCH v2 7/7] scsi: ufs: add dme control primitives Seungwon Jeon
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Subhash Jadavani @ 2013-05-02 12:08 UTC (permalink / raw)
  To: Seungwon Jeon
  Cc: linux-scsi, 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

On 4/24/2013 9:36 PM, Seungwon Jeon wrote:
> Add uic command operations including DME_XXX series.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> ---
>   drivers/scsi/ufs/ufs-attrs.h |  129 ++++++++++++++++++++++++
>   drivers/scsi/ufs/ufshcd.c    |  220 +++++++++++++++++++++++++++++++++++++++++-
>   drivers/scsi/ufs/ufshcd.h    |   55 +++++++++++
>   drivers/scsi/ufs/ufshci.h    |   19 ++++
>   4 files changed, 422 insertions(+), 1 deletions(-)
>   create mode 100644 drivers/scsi/ufs/ufs-attrs.h
>
> diff --git a/drivers/scsi/ufs/ufs-attrs.h b/drivers/scsi/ufs/ufs-attrs.h
> new file mode 100644
> index 0000000..562bb49
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufs-attrs.h
> @@ -0,0 +1,129 @@
> +/*
> + * drivers/scsi/ufs/ufs-attrs.h
> + *
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef _UFS_ATTRS_H_
> +#define _UFS_ATTRS_H_

I don't see a need to add this file as part of this patch as there are 
no users of the same in this patch. So its better to remove from here 
and add it as separate patch when their real use arises.

> +
> +/*
> + * PHY Adpater attributes
> + */
> +#define PA_ACTIVETXDATALANES	0x1560
> +#define PA_ACTIVERXDATALANES	0x1580
> +#define PA_TXTRAILINGCLOCKS	0x1564
> +#define PA_PHY_TYPE		0x1500
> +#define PA_AVAILTXDATALANES	0x1520
> +#define PA_AVAILRXDATALANES	0x1540
> +#define PA_MINRXTRAILINGCLOCKS	0x1543
> +#define PA_TXPWRSTATUS		0x1567
> +#define PA_RXPWRSTATUS		0x1582
> +#define PA_TXFORCECLOCK		0x1562
> +#define PA_TXPWRMODE		0x1563
> +#define PA_LEGACYDPHYESCDL	0x1570
> +#define PA_MAXTXSPEEDFAST	0x1521
> +#define PA_MAXTXSPEEDSLOW	0x1522
> +#define PA_MAXRXSPEEDFAST	0x1541
> +#define PA_MAXRXSPEEDSLOW	0x1542
> +#define PA_TXLINKSTARTUPHS	0x1544
> +#define PA_TXSPEEDFAST		0x1565
> +#define PA_TXSPEEDSLOW		0x1566
> +#define PA_REMOTEVERINFO	0x15A0
> +#define PA_TXGEAR		0x1568
> +#define PA_TXTERMINATION	0x1569
> +#define PA_HSSERIES		0x156A
> +#define PA_PWRMODE		0x1571
> +#define PA_RXGEAR		0x1583
> +#define PA_RXTERMINATION	0x1584
> +#define PA_MAXRXPWMGEAR		0x1586
> +#define PA_MAXRXHSGEAR		0x1587
> +#define PA_RXHSUNTERMCAP	0x15A5
> +#define PA_RXLSTERMCAP		0x15A6
> +#define PA_PACPREQTIMEOUT	0x1590
> +#define PA_PACPREQEOBTIMEOUT	0x1591
> +#define PA_LOCALVERINFO		0x15A9
> +#define PA_TACTIVATE		0x15A8
> +#define PA_PACPFRAMECOUNT	0x15C0
> +#define PA_PACPERRORCOUNT	0x15C1
> +#define PA_PHYTESTCONTROL	0x15C2
> +#define PA_PWRMODEUSERDATA0	0x15B0
> +#define PA_PWRMODEUSERDATA1	0x15B1
> +#define PA_PWRMODEUSERDATA2	0x15B2
> +#define PA_PWRMODEUSERDATA3	0x15B3
> +#define PA_PWRMODEUSERDATA4	0x15B4
> +#define PA_PWRMODEUSERDATA5	0x15B5
> +#define PA_PWRMODEUSERDATA6	0x15B6
> +#define PA_PWRMODEUSERDATA7	0x15B7
> +#define PA_PWRMODEUSERDATA8	0x15B8
> +#define PA_PWRMODEUSERDATA9	0x15B9
> +#define PA_PWRMODEUSERDATA10	0x15BA
> +#define PA_PWRMODEUSERDATA11	0x15BB
> +#define PA_CONNECTEDTXDATALANE	0x1561
> +#define PA_CONNECTEDRXDATALANE	0x1581
> +#define PA_LOGICALLANEMAP	0x15A1
> +#define PA_SLEEPNOCONFIGTIME	0x15A2
> +#define PA_STALLNOCONFIGTIME	0x15A3
> +#define PA_SAVECONFIGTIME	0x15A4
> +
> +/*
> + * Data Link Layer Attributes
> + */
> +#define DL_TC0TXFCTHRESHOLD	0x2040
> +#define DL_FC0PROTTIMEOUTVAL	0x2041
> +#define DL_TC0REPLAYTIMEOUTVAL	0x2042
> +#define DL_AFC0REQTIMEOUTVAL	0x2043
> +#define DL_AFC0CREDITTHRESHOLD	0x2044
> +#define DL_TC0OUTACKTHRESHOLD	0x2045
> +#define DL_TC1TXFCTHRESHOLD	0x2060
> +#define DL_FC1PROTTIMEOUTVAL	0x2061
> +#define DL_TC1REPLAYTIMEOUTVAL	0x2062
> +#define DL_AFC1REQTIMEOUTVAL	0x2063
> +#define DL_AFC1CREDITTHRESHOLD	0x2064
> +#define DL_TC1OUTACKTHRESHOLD	0x2065
> +#define DL_TXPREEMPTIONCAP	0x2000
> +#define DL_TC0TXMAXSDUSIZE	0x2001
> +#define DL_TC0RXINITCREDITVAL	0x2002
> +#define DL_TC0TXBUFFERSIZE	0x2005
> +#define DL_PEERTC0PRESENT	0x2046
> +#define DL_PEERTC0RXINITCREVAL	0x2047
> +#define DL_TC1TXMAXSDUSIZE	0x2003
> +#define DL_TC1RXINITCREDITVAL	0x2004
> +#define DL_TC1TXBUFFERSIZE	0x2006
> +#define DL_PEERTC1PRESENT	0x2066
> +#define DL_PEERTC1RXINITCREVAL	0x2067
> +
> +/*
> + * Network Layer Attributes
> + */
> +#define N_DEVICEID		0x3000
> +#define N_DEVICEID_VALID	0x3001
> +#define N_TC0TXMAXSDUSIZE	0x3020
> +#define N_TC1TXMAXSDUSIZE	0x3021
> +
> +/*
> + * Transport Layer Attributes
> + */
> +#define T_NUMCPORTS		0x4000
> +#define T_NUMTESTFEATURES	0x4001
> +#define T_CONNECTIONSTATE	0x4020
> +#define T_PEERDEVICEID		0x4021
> +#define T_PEERCPORTID		0x4022
> +#define T_TRAFFICCLASS		0x4023
> +#define T_PROTOCOLID		0x4024
> +#define T_CPORTFLAGS		0x4025
> +#define T_TXTOKENVALUE		0x4026
> +#define T_RXTOKENVALUE		0x4027
> +#define T_LOCALBUFFERSPACE	0x4028
> +#define T_PEERBUFFERSPACE	0x4029
> +#define T_CREDITSTOSEND		0x402A
> +#define T_CPORTMODE		0x402B
> +#define T_TC0TXMAXSDUSIZE	0x4060
> +#define T_TC1TXMAXSDUSIZE	0x4061
> +
> +#endif /* _UFS_ATTRS_H_ */
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 76ff332..55575ea 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -37,6 +37,7 @@
>   
>   #define UFSHCD_ENABLE_INTRS	(UTP_TRANSFER_REQ_COMPL |\
>   				 UTP_TASK_REQ_COMPL |\
> +				 UFSHCD_HIBERNATE_MASK |\
>   				 UFSHCD_ERROR_MASK)
>   #define UIC_CMD_TIMEOUT	100
>   
> @@ -188,6 +189,31 @@ 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);
> +}
> +
> +

Please remove one extra line space above.

> +/**
> + * 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
> @@ -804,6 +830,195 @@ 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
> + *
> + * 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;
> +	static const char *const action[] = {
> +		"dme-set", "dme-peer-set"
> +	};
> +	const char *set = action[!!peer];
> +	unsigned long flags;
> +	int ret;
> +
> +	if (!ufshcd_ready_uic_cmd(hba))
> +		return -EIO;
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +
> +	/* form UIC command */
> +	uic_cmd = &hba->active_uic_cmd;
> +	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;
> +
> +	/* dispatch UIC commands to controller */
> +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	ret = ufshcd_wait_for_uic_cmd(hba);
> +	dev_dbg(hba->dev, "%s: error code %d returned\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
> + *
> + * 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;
> +	static const char *const action[] = {
> +		"dme-get", "dme-peer-get"
> +	};
> +	const char *get = action[!!peer];
> +	unsigned long flags;
> +	int ret;
> +
> +	if (!ufshcd_ready_uic_cmd(hba))
> +		return -EIO;
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +
> +	/* form UIC command */
> +	uic_cmd = &hba->active_uic_cmd;
> +	uic_cmd->command = peer ?
> +		UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
> +	uic_cmd->argument1 = attr_sel;
> +	uic_cmd->argument2 = 0;
> +	uic_cmd->argument3 = 0;
> +
> +	/* dispatch UIC commands to controller */
> +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	ret = ufshcd_wait_for_uic_cmd(hba);
> +	if (mib_val)
> +		*mib_val = ufshcd_get_dme_attr_val(hba);
> +
> +	dev_dbg(hba->dev, "%s: error code %d returned\n", get, ret);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_xxx_get);
> +
> +/**
> + * ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF
> + * @hba: per adapter instance
> + *
> + * 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;
> +	static const char *const action[] = {
> +		"dme-power-on",
> +		"dme-power-off",
> +	};
> +	const char *power = action[!!on];
> +	unsigned long flags;
> +	int ret;
> +
> +	if (!ufshcd_ready_uic_cmd(hba))
> +		return -EIO;
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +
> +	/* form UIC command */
> +	uic_cmd = &hba->active_uic_cmd;
> +	uic_cmd->command = on ?
> +		UIC_CMD_DME_POWERON : UIC_CMD_DME_POWEROFF;
> +	uic_cmd->argument1 = 0;
> +	uic_cmd->argument2 = 0;
> +	uic_cmd->argument3 = 0;
> +
> +	/* dispatch UIC commands to controller */
> +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> +
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	ret = ufshcd_wait_for_uic_cmd(hba);
> +	if (ret)
> +		dev_err(hba->dev, "%s: error code %d returned\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
> + *
> + * 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;
> +	static const char *const action[] = {
> +		"dme-hibernate-enter",
> +		"dme-hibernate-exit"
> +	};
> +	const char *hibern8 = action[!!enter];
> +	unsigned long flags;
> +	u8 status;
> +	int ret;
> +
> +	if (!ufshcd_ready_uic_cmd(hba))
> +		return -EIO;
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +
> +	/* form UIC command */
> +	uic_cmd = &hba->active_uic_cmd;
> +	uic_cmd->command = enter ?
> +		UIC_CMD_DME_HIBER_ENTER : UIC_CMD_DME_HIBER_EXIT;
> +	uic_cmd->argument1 = 0;
> +	uic_cmd->argument2 = 0;
> +	uic_cmd->argument3 = 0;
> +
> +	/* dispatch UIC commands to controller */
> +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> +
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	ret= ufshcd_wait_for_uic_cmd(hba);
> +	if (ret) {
> +		dev_err(hba->dev, "%s: error code %d returned\n", hibern8, ret);
> +		goto out;
> +	}
> +
> +	init_completion(&hba->hibern8_done);
> +
> +	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:
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_hibern8_xxx);
> +
> +/**
>    * ufshcd_make_hba_operational - Make UFS controller operational
>    * @hba: per adapter instance
>    *
> @@ -1238,6 +1453,9 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
>   {
>   	if (intr_status & UIC_COMMAND_COMPL)
>   		complete(&hba->active_uic_cmd.done);
> +
> +	if (intr_status & UFSHCD_HIBERNATE_MASK)
> +		complete(&hba->hibern8_done);
>   }
>   
>   /**
> @@ -1362,7 +1580,7 @@ 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)
> +	if (intr_status & UFSHCD_UIC_MASK)
>   		ufshcd_uic_cmd_compl(hba, intr_status);
>   
>   	if (intr_status & UTP_TASK_REQ_COMPL)
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 2fb4d94..5bf19f5 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -140,6 +140,7 @@ struct ufshcd_lrb {
>    * @active_uic_cmd: handle of active 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
>    * @link_startup_wq: Work queue for link start-up
> @@ -177,6 +178,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;
>   
> @@ -197,4 +200,56 @@ void ufshcd_remove(struct ufs_hba *);
>   #define ufshcd_readl(hba, reg)	\
>   	readl((hba)->mmio_base + (reg))
>   
> +
> +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);
> +
> +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);
> +}
> +
> +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, u8 enter)
> +{
> +	return ufshcd_dme_hibern8_xxx(hba, 1);
> +}
> +
> +static inline int ufshcd_dme_hibern8_exit(struct ufs_hba *hba, u8 enter)
> +{
> +	return ufshcd_dme_hibern8_xxx(hba, 0);
> +}
> +
>   #endif /* End of Header */
> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
> index d5c5f14..28ede2a 100644
> --- a/drivers/scsi/ufs/ufshci.h
> +++ b/drivers/scsi/ufs/ufshci.h
> @@ -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
> @@ -191,6 +206,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,


^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH 5/5] scsi: ufs: add dme operations
  2013-05-02  8:07   ` Santosh Y
@ 2013-05-02 13:38     ` Seungwon Jeon
  0 siblings, 0 replies; 14+ messages in thread
From: Seungwon Jeon @ 2013-05-02 13:38 UTC (permalink / raw)
  To: 'Santosh Y'
  Cc: linux-scsi, 'Vinayak Holikatti',
	'James E.J. Bottomley'

On Thursday, May 02, 2013 Santosh Y wrote:
> On Thu, May 2, 2013 at 1:36 PM, Santosh Y <santoshsy@gmail.com> wrote:
> >> +/*
> >> + * drivers/scsi/ufs/ufs-attrs.h
> >> + *
> >> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> >> + *
> >> + * This program is free software; you can redistribute it and/or modify
> >> + * it under the terms of the GNU General Public License as published by
> >> + * the Free Software Foundation; either version 2 of the License, or
> >> + * (at your option) any later version.
> >> + */
> >> +
> >> +#ifndef _UFS_ATTRS_H_
> >> +#define _UFS_ATTRS_H_
> >> +
> >> +/*
> >> + * PHY Adpater attributes
> >> + */
> >> +#define PA_ACTIVETXDATALANES   0x1560
> >> +#define PA_ACTIVERXDATALANES   0x1580
> >> +#define PA_TXTRAILINGCLOCKS    0x1564
> >> +#define PA_PHY_TYPE            0x1500
> >> +#define PA_AVAILTXDATALANES    0x1520
> >> +#define PA_AVAILRXDATALANES    0x1540
> >> +#define PA_MINRXTRAILINGCLOCKS 0x1543
> >> +#define PA_TXPWRSTATUS         0x1567
> >> +#define PA_RXPWRSTATUS         0x1582
> >> +#define PA_TXFORCECLOCK                0x1562
> >> +#define PA_TXPWRMODE           0x1563
> >> +#define PA_LEGACYDPHYESCDL     0x1570
> >> +#define PA_MAXTXSPEEDFAST      0x1521
> >> +#define PA_MAXTXSPEEDSLOW      0x1522
> >> +#define PA_MAXRXSPEEDFAST      0x1541
> >> +#define PA_MAXRXSPEEDSLOW      0x1542
> >> +#define PA_TXLINKSTARTUPHS     0x1544
> >> +#define PA_TXSPEEDFAST         0x1565
> >> +#define PA_TXSPEEDSLOW         0x1566
> >> +#define PA_REMOTEVERINFO       0x15A0
> >> +#define PA_TXGEAR              0x1568
> >> +#define PA_TXTERMINATION       0x1569
> >> +#define PA_HSSERIES            0x156A
> >> +#define PA_PWRMODE             0x1571
> >> +#define PA_RXGEAR              0x1583
> >> +#define PA_RXTERMINATION       0x1584
> >> +#define PA_MAXRXPWMGEAR                0x1586
> >> +#define PA_MAXRXHSGEAR         0x1587
> >> +#define PA_RXHSUNTERMCAP       0x15A5
> >> +#define PA_RXLSTERMCAP         0x15A6
> >> +#define PA_PACPREQTIMEOUT      0x1590
> >> +#define PA_PACPREQEOBTIMEOUT   0x1591
> >> +#define PA_LOCALVERINFO                0x15A9
> >> +#define PA_TACTIVATE           0x15A8
> >> +#define PA_PACPFRAMECOUNT      0x15C0
> >> +#define PA_PACPERRORCOUNT      0x15C1
> >> +#define PA_PHYTESTCONTROL      0x15C2
> >> +#define PA_PWRMODEUSERDATA0    0x15B0
> >> +#define PA_PWRMODEUSERDATA1    0x15B1
> >> +#define PA_PWRMODEUSERDATA2    0x15B2
> >> +#define PA_PWRMODEUSERDATA3    0x15B3
> >> +#define PA_PWRMODEUSERDATA4    0x15B4
> >> +#define PA_PWRMODEUSERDATA5    0x15B5
> >> +#define PA_PWRMODEUSERDATA6    0x15B6
> >> +#define PA_PWRMODEUSERDATA7    0x15B7
> >> +#define PA_PWRMODEUSERDATA8    0x15B8
> >> +#define PA_PWRMODEUSERDATA9    0x15B9
> >> +#define PA_PWRMODEUSERDATA10   0x15BA
> >> +#define PA_PWRMODEUSERDATA11   0x15BB
> >> +#define PA_CONNECTEDTXDATALANE 0x1561
> >> +#define PA_CONNECTEDRXDATALANE 0x1581
> >> +#define PA_LOGICALLANEMAP      0x15A1
> >> +#define PA_SLEEPNOCONFIGTIME   0x15A2
> >> +#define PA_STALLNOCONFIGTIME   0x15A3
> >> +#define PA_SAVECONFIGTIME      0x15A4
> >> +
> >> +/*
> >> + * Data Link Layer Attributes
> >> + */
> >> +#define DL_TC0TXFCTHRESHOLD    0x2040
> >> +#define DL_FC0PROTTIMEOUTVAL   0x2041
> >> +#define DL_TC0REPLAYTIMEOUTVAL 0x2042
> >> +#define DL_AFC0REQTIMEOUTVAL   0x2043
> >> +#define DL_AFC0CREDITTHRESHOLD 0x2044
> >> +#define DL_TC0OUTACKTHRESHOLD  0x2045
> >> +#define DL_TC1TXFCTHRESHOLD    0x2060
> >> +#define DL_FC1PROTTIMEOUTVAL   0x2061
> >> +#define DL_TC1REPLAYTIMEOUTVAL 0x2062
> >> +#define DL_AFC1REQTIMEOUTVAL   0x2063
> >> +#define DL_AFC1CREDITTHRESHOLD 0x2064
> >> +#define DL_TC1OUTACKTHRESHOLD  0x2065
> >> +#define DL_TXPREEMPTIONCAP     0x2000
> >> +#define DL_TC0TXMAXSDUSIZE     0x2001
> >> +#define DL_TC0RXINITCREDITVAL  0x2002
> >> +#define DL_TC0TXBUFFERSIZE     0x2005
> >> +#define DL_PEERTC0PRESENT      0x2046
> >> +#define DL_PEERTC0RXINITCREVAL 0x2047
> >> +#define DL_TC1TXMAXSDUSIZE     0x2003
> >> +#define DL_TC1RXINITCREDITVAL  0x2004
> >> +#define DL_TC1TXBUFFERSIZE     0x2006
> >> +#define DL_PEERTC1PRESENT      0x2066
> >> +#define DL_PEERTC1RXINITCREVAL 0x2067
> >> +
> >> +/*
> >> + * Network Layer Attributes
> >> + */
> >> +#define N_DEVICEID             0x3000
> >> +#define N_DEVICEID_VALID       0x3001
> >> +#define N_TC0TXMAXSDUSIZE      0x3020
> >> +#define N_TC1TXMAXSDUSIZE      0x3021
> >> +
> >> +/*
> >> + * Transport Layer Attributes
> >> + */
> >> +#define T_NUMCPORTS            0x4000
> >> +#define T_NUMTESTFEATURES      0x4001
> >> +#define T_CONNECTIONSTATE      0x4020
> >> +#define T_PEERDEVICEID         0x4021
> >> +#define T_PEERCPORTID          0x4022
> >> +#define T_TRAFFICCLASS         0x4023
> >> +#define T_PROTOCOLID           0x4024
> >> +#define T_CPORTFLAGS           0x4025
> >> +#define T_TXTOKENVALUE         0x4026
> >> +#define T_RXTOKENVALUE         0x4027
> >> +#define T_LOCALBUFFERSPACE     0x4028
> >> +#define T_PEERBUFFERSPACE      0x4029
> >> +#define T_CREDITSTOSEND                0x402A
> >> +#define T_CPORTMODE            0x402B
> >> +#define T_TC0TXMAXSDUSIZE      0x4060
> >> +#define T_TC1TXMAXSDUSIZE      0x4061
> >> +
> >> +#endif /* _UFS_ATTRS_H_ */
> >
> >
> > These are Unipro. So change the name of the file to unipro.h
> >
>  I meant Unipro attributes, So change the name accordingly.
Ok, unipro.h seems proper.

Thanks,
Seungwon Jeon
> 
> >> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> >> index 76ff332..55575ea 100644
> >> --- a/drivers/scsi/ufs/ufshcd.c
> >> +++ b/drivers/scsi/ufs/ufshcd.c
> >> @@ -37,6 +37,7 @@
> >>
> >>  #define UFSHCD_ENABLE_INTRS    (UTP_TRANSFER_REQ_COMPL |\
> >>                                  UTP_TASK_REQ_COMPL |\
> >> +                                UFSHCD_HIBERNATE_MASK |\
> >>                                  UFSHCD_ERROR_MASK)
> >>  #define UIC_CMD_TIMEOUT        100
> >>
> >> @@ -188,6 +189,31 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
> >>  }
> >>
> >
> >
> > --
> > ~Santosh
> 
> 
> 
> --
> ~Santosh
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH 5/5] scsi: ufs: add dme operations
  2013-05-02 12:08 ` Subhash Jadavani
@ 2013-05-02 13:39   ` Seungwon Jeon
  0 siblings, 0 replies; 14+ messages in thread
From: Seungwon Jeon @ 2013-05-02 13:39 UTC (permalink / raw)
  To: 'Subhash Jadavani'
  Cc: linux-scsi, 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

On Thursday, May 02, 2013, Subhash Jadavani wrote:
> On 4/24/2013 9:36 PM, Seungwon Jeon wrote:
> > Add uic command operations including DME_XXX series.
> >
> > Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> > ---
> >   drivers/scsi/ufs/ufs-attrs.h |  129 ++++++++++++++++++++++++
> >   drivers/scsi/ufs/ufshcd.c    |  220 +++++++++++++++++++++++++++++++++++++++++-
> >   drivers/scsi/ufs/ufshcd.h    |   55 +++++++++++
> >   drivers/scsi/ufs/ufshci.h    |   19 ++++
> >   4 files changed, 422 insertions(+), 1 deletions(-)
> >   create mode 100644 drivers/scsi/ufs/ufs-attrs.h
> >
> > diff --git a/drivers/scsi/ufs/ufs-attrs.h b/drivers/scsi/ufs/ufs-attrs.h
> > new file mode 100644
> > index 0000000..562bb49
> > --- /dev/null
> > +++ b/drivers/scsi/ufs/ufs-attrs.h
> > @@ -0,0 +1,129 @@
> > +/*
> > + * drivers/scsi/ufs/ufs-attrs.h
> > + *
> > + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef _UFS_ATTRS_H_
> > +#define _UFS_ATTRS_H_
> 
> I don't see a need to add this file as part of this patch as there are
> no users of the same in this patch. So its better to remove from here
> and add it as separate patch when their real use arises.
Even though actual usage is not introduced here, dme_get{set} functions are introduced.
These attribute's ids will be used as argument of dme_get{set}.
So, I think definitions would be better to be in this patch.

> 
> > +
> > +/*
> > + * PHY Adpater attributes
> > + */
> > +#define PA_ACTIVETXDATALANES	0x1560
> > +#define PA_ACTIVERXDATALANES	0x1580
> > +#define PA_TXTRAILINGCLOCKS	0x1564
> > +#define PA_PHY_TYPE		0x1500
> > +#define PA_AVAILTXDATALANES	0x1520
> > +#define PA_AVAILRXDATALANES	0x1540
> > +#define PA_MINRXTRAILINGCLOCKS	0x1543
> > +#define PA_TXPWRSTATUS		0x1567
> > +#define PA_RXPWRSTATUS		0x1582
> > +#define PA_TXFORCECLOCK		0x1562
> > +#define PA_TXPWRMODE		0x1563
> > +#define PA_LEGACYDPHYESCDL	0x1570
> > +#define PA_MAXTXSPEEDFAST	0x1521
> > +#define PA_MAXTXSPEEDSLOW	0x1522
> > +#define PA_MAXRXSPEEDFAST	0x1541
> > +#define PA_MAXRXSPEEDSLOW	0x1542
> > +#define PA_TXLINKSTARTUPHS	0x1544
> > +#define PA_TXSPEEDFAST		0x1565
> > +#define PA_TXSPEEDSLOW		0x1566
> > +#define PA_REMOTEVERINFO	0x15A0
> > +#define PA_TXGEAR		0x1568
> > +#define PA_TXTERMINATION	0x1569
> > +#define PA_HSSERIES		0x156A
> > +#define PA_PWRMODE		0x1571
> > +#define PA_RXGEAR		0x1583
> > +#define PA_RXTERMINATION	0x1584
> > +#define PA_MAXRXPWMGEAR		0x1586
> > +#define PA_MAXRXHSGEAR		0x1587
> > +#define PA_RXHSUNTERMCAP	0x15A5
> > +#define PA_RXLSTERMCAP		0x15A6
> > +#define PA_PACPREQTIMEOUT	0x1590
> > +#define PA_PACPREQEOBTIMEOUT	0x1591
> > +#define PA_LOCALVERINFO		0x15A9
> > +#define PA_TACTIVATE		0x15A8
> > +#define PA_PACPFRAMECOUNT	0x15C0
> > +#define PA_PACPERRORCOUNT	0x15C1
> > +#define PA_PHYTESTCONTROL	0x15C2
> > +#define PA_PWRMODEUSERDATA0	0x15B0
> > +#define PA_PWRMODEUSERDATA1	0x15B1
> > +#define PA_PWRMODEUSERDATA2	0x15B2
> > +#define PA_PWRMODEUSERDATA3	0x15B3
> > +#define PA_PWRMODEUSERDATA4	0x15B4
> > +#define PA_PWRMODEUSERDATA5	0x15B5
> > +#define PA_PWRMODEUSERDATA6	0x15B6
> > +#define PA_PWRMODEUSERDATA7	0x15B7
> > +#define PA_PWRMODEUSERDATA8	0x15B8
> > +#define PA_PWRMODEUSERDATA9	0x15B9
> > +#define PA_PWRMODEUSERDATA10	0x15BA
> > +#define PA_PWRMODEUSERDATA11	0x15BB
> > +#define PA_CONNECTEDTXDATALANE	0x1561
> > +#define PA_CONNECTEDRXDATALANE	0x1581
> > +#define PA_LOGICALLANEMAP	0x15A1
> > +#define PA_SLEEPNOCONFIGTIME	0x15A2
> > +#define PA_STALLNOCONFIGTIME	0x15A3
> > +#define PA_SAVECONFIGTIME	0x15A4
> > +
> > +/*
> > + * Data Link Layer Attributes
> > + */
> > +#define DL_TC0TXFCTHRESHOLD	0x2040
> > +#define DL_FC0PROTTIMEOUTVAL	0x2041
> > +#define DL_TC0REPLAYTIMEOUTVAL	0x2042
> > +#define DL_AFC0REQTIMEOUTVAL	0x2043
> > +#define DL_AFC0CREDITTHRESHOLD	0x2044
> > +#define DL_TC0OUTACKTHRESHOLD	0x2045
> > +#define DL_TC1TXFCTHRESHOLD	0x2060
> > +#define DL_FC1PROTTIMEOUTVAL	0x2061
> > +#define DL_TC1REPLAYTIMEOUTVAL	0x2062
> > +#define DL_AFC1REQTIMEOUTVAL	0x2063
> > +#define DL_AFC1CREDITTHRESHOLD	0x2064
> > +#define DL_TC1OUTACKTHRESHOLD	0x2065
> > +#define DL_TXPREEMPTIONCAP	0x2000
> > +#define DL_TC0TXMAXSDUSIZE	0x2001
> > +#define DL_TC0RXINITCREDITVAL	0x2002
> > +#define DL_TC0TXBUFFERSIZE	0x2005
> > +#define DL_PEERTC0PRESENT	0x2046
> > +#define DL_PEERTC0RXINITCREVAL	0x2047
> > +#define DL_TC1TXMAXSDUSIZE	0x2003
> > +#define DL_TC1RXINITCREDITVAL	0x2004
> > +#define DL_TC1TXBUFFERSIZE	0x2006
> > +#define DL_PEERTC1PRESENT	0x2066
> > +#define DL_PEERTC1RXINITCREVAL	0x2067
> > +
> > +/*
> > + * Network Layer Attributes
> > + */
> > +#define N_DEVICEID		0x3000
> > +#define N_DEVICEID_VALID	0x3001
> > +#define N_TC0TXMAXSDUSIZE	0x3020
> > +#define N_TC1TXMAXSDUSIZE	0x3021
> > +
> > +/*
> > + * Transport Layer Attributes
> > + */
> > +#define T_NUMCPORTS		0x4000
> > +#define T_NUMTESTFEATURES	0x4001
> > +#define T_CONNECTIONSTATE	0x4020
> > +#define T_PEERDEVICEID		0x4021
> > +#define T_PEERCPORTID		0x4022
> > +#define T_TRAFFICCLASS		0x4023
> > +#define T_PROTOCOLID		0x4024
> > +#define T_CPORTFLAGS		0x4025
> > +#define T_TXTOKENVALUE		0x4026
> > +#define T_RXTOKENVALUE		0x4027
> > +#define T_LOCALBUFFERSPACE	0x4028
> > +#define T_PEERBUFFERSPACE	0x4029
> > +#define T_CREDITSTOSEND		0x402A
> > +#define T_CPORTMODE		0x402B
> > +#define T_TC0TXMAXSDUSIZE	0x4060
> > +#define T_TC1TXMAXSDUSIZE	0x4061
> > +
> > +#endif /* _UFS_ATTRS_H_ */
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index 76ff332..55575ea 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -37,6 +37,7 @@
> >
> >   #define UFSHCD_ENABLE_INTRS	(UTP_TRANSFER_REQ_COMPL |\
> >   				 UTP_TASK_REQ_COMPL |\
> > +				 UFSHCD_HIBERNATE_MASK |\
> >   				 UFSHCD_ERROR_MASK)
> >   #define UIC_CMD_TIMEOUT	100
> >
> > @@ -188,6 +189,31 @@ 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);
> > +}
> > +
> > +
> 
> Please remove one extra line space above.
Ok.

> 
> > +/**
> > + * 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
> > @@ -804,6 +830,195 @@ 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
> > + *
> > + * 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;
> > +	static const char *const action[] = {
> > +		"dme-set", "dme-peer-set"
> > +	};
> > +	const char *set = action[!!peer];
> > +	unsigned long flags;
> > +	int ret;
> > +
> > +	if (!ufshcd_ready_uic_cmd(hba))
> > +		return -EIO;
> > +
> > +	spin_lock_irqsave(hba->host->host_lock, flags);
> > +
> > +	/* form UIC command */
> > +	uic_cmd = &hba->active_uic_cmd;
> > +	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;
> > +
> > +	/* dispatch UIC commands to controller */
> > +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> > +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> > +
> > +	ret = ufshcd_wait_for_uic_cmd(hba);
> > +	dev_dbg(hba->dev, "%s: error code %d returned\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
> > + *
> > + * 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;
> > +	static const char *const action[] = {
> > +		"dme-get", "dme-peer-get"
> > +	};
> > +	const char *get = action[!!peer];
> > +	unsigned long flags;
> > +	int ret;
> > +
> > +	if (!ufshcd_ready_uic_cmd(hba))
> > +		return -EIO;
> > +
> > +	spin_lock_irqsave(hba->host->host_lock, flags);
> > +
> > +	/* form UIC command */
> > +	uic_cmd = &hba->active_uic_cmd;
> > +	uic_cmd->command = peer ?
> > +		UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
> > +	uic_cmd->argument1 = attr_sel;
> > +	uic_cmd->argument2 = 0;
> > +	uic_cmd->argument3 = 0;
> > +
> > +	/* dispatch UIC commands to controller */
> > +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> > +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> > +
> > +	ret = ufshcd_wait_for_uic_cmd(hba);
> > +	if (mib_val)
> > +		*mib_val = ufshcd_get_dme_attr_val(hba);
> > +
> > +	dev_dbg(hba->dev, "%s: error code %d returned\n", get, ret);
> > +
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(ufshcd_dme_xxx_get);
> > +
> > +/**
> > + * ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF
> > + * @hba: per adapter instance
> > + *
> > + * 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;
> > +	static const char *const action[] = {
> > +		"dme-power-on",
> > +		"dme-power-off",
> > +	};
> > +	const char *power = action[!!on];
> > +	unsigned long flags;
> > +	int ret;
> > +
> > +	if (!ufshcd_ready_uic_cmd(hba))
> > +		return -EIO;
> > +
> > +	spin_lock_irqsave(hba->host->host_lock, flags);
> > +
> > +	/* form UIC command */
> > +	uic_cmd = &hba->active_uic_cmd;
> > +	uic_cmd->command = on ?
> > +		UIC_CMD_DME_POWERON : UIC_CMD_DME_POWEROFF;
> > +	uic_cmd->argument1 = 0;
> > +	uic_cmd->argument2 = 0;
> > +	uic_cmd->argument3 = 0;
> > +
> > +	/* dispatch UIC commands to controller */
> > +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> > +
> > +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> > +
> > +	ret = ufshcd_wait_for_uic_cmd(hba);
> > +	if (ret)
> > +		dev_err(hba->dev, "%s: error code %d returned\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
> > + *
> > + * 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;
> > +	static const char *const action[] = {
> > +		"dme-hibernate-enter",
> > +		"dme-hibernate-exit"
> > +	};
> > +	const char *hibern8 = action[!!enter];
> > +	unsigned long flags;
> > +	u8 status;
> > +	int ret;
> > +
> > +	if (!ufshcd_ready_uic_cmd(hba))
> > +		return -EIO;
> > +
> > +	spin_lock_irqsave(hba->host->host_lock, flags);
> > +
> > +	/* form UIC command */
> > +	uic_cmd = &hba->active_uic_cmd;
> > +	uic_cmd->command = enter ?
> > +		UIC_CMD_DME_HIBER_ENTER : UIC_CMD_DME_HIBER_EXIT;
> > +	uic_cmd->argument1 = 0;
> > +	uic_cmd->argument2 = 0;
> > +	uic_cmd->argument3 = 0;
> > +
> > +	/* dispatch UIC commands to controller */
> > +	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> > +
> > +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> > +
> > +	ret= ufshcd_wait_for_uic_cmd(hba);
> > +	if (ret) {
> > +		dev_err(hba->dev, "%s: error code %d returned\n", hibern8, ret);
> > +		goto out;
> > +	}
> > +
> > +	init_completion(&hba->hibern8_done);
> > +
> > +	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:
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(ufshcd_dme_hibern8_xxx);
> > +
> > +/**
> >    * ufshcd_make_hba_operational - Make UFS controller operational
> >    * @hba: per adapter instance
> >    *
> > @@ -1238,6 +1453,9 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
> >   {
> >   	if (intr_status & UIC_COMMAND_COMPL)
> >   		complete(&hba->active_uic_cmd.done);
> > +
> > +	if (intr_status & UFSHCD_HIBERNATE_MASK)
> > +		complete(&hba->hibern8_done);
> >   }
> >
> >   /**
> > @@ -1362,7 +1580,7 @@ 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)
> > +	if (intr_status & UFSHCD_UIC_MASK)
> >   		ufshcd_uic_cmd_compl(hba, intr_status);
> >
> >   	if (intr_status & UTP_TASK_REQ_COMPL)
> > diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> > index 2fb4d94..5bf19f5 100644
> > --- a/drivers/scsi/ufs/ufshcd.h
> > +++ b/drivers/scsi/ufs/ufshcd.h
> > @@ -140,6 +140,7 @@ struct ufshcd_lrb {
> >    * @active_uic_cmd: handle of active 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
> >    * @link_startup_wq: Work queue for link start-up
> > @@ -177,6 +178,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;
> >
> > @@ -197,4 +200,56 @@ void ufshcd_remove(struct ufs_hba *);
> >   #define ufshcd_readl(hba, reg)	\
> >   	readl((hba)->mmio_base + (reg))
> >
> > +
> > +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);
> > +
> > +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);
> > +}
> > +
> > +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, u8 enter)
> > +{
> > +	return ufshcd_dme_hibern8_xxx(hba, 1);
> > +}
> > +
> > +static inline int ufshcd_dme_hibern8_exit(struct ufs_hba *hba, u8 enter)
> > +{
> > +	return ufshcd_dme_hibern8_xxx(hba, 0);
> > +}
> > +
> >   #endif /* End of Header */
> > diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
> > index d5c5f14..28ede2a 100644
> > --- a/drivers/scsi/ufs/ufshci.h
> > +++ b/drivers/scsi/ufs/ufshci.h
> > @@ -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
> > @@ -191,6 +206,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,
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 7/7] scsi: ufs: add dme control primitives
  2013-04-24 16:06 [PATCH 5/5] scsi: ufs: add dme operations Seungwon Jeon
                   ` (2 preceding siblings ...)
  2013-05-02 12:08 ` Subhash Jadavani
@ 2013-05-04  8:45 ` Seungwon Jeon
  2013-05-04 18:51   ` Sujit Reddy Thumma
  2013-05-06 10:41   ` merez
  2013-05-04  8:46 ` [PATCH v2 5/7] scsi: ufs: rework link start-up process Seungwon Jeon
  2013-05-04  8:46 ` [PATCH v2 6/7] scsi: ufs: add dme configuration primitives Seungwon Jeon
  5 siblings, 2 replies; 14+ messages in thread
From: Seungwon Jeon @ 2013-05-04  8:45 UTC (permalink / raw)
  To: linux-scsi
  Cc: 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

Implements 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.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
---
 drivers/scsi/ufs/ufshcd.c |  133 ++++++++++++++++++++++++++++++++++++++++++---
 drivers/scsi/ufs/ufshcd.h |   26 +++++++++
 drivers/scsi/ufs/ufshci.h |   15 +++++
 3 files changed, 166 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 956041c..54cd61a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -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
@@ -1161,6 +1174,104 @@ 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);
+	ret = __ufshcd_send_uic_cmd(hba, &uic_cmd);
+	if (ret) {
+		dev_err(hba->dev, "%s: error code %d\n", hibern8, ret);
+		goto out;
+	}
+
+	init_completion(&hba->hibern8_done);
+
+	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
  *
@@ -1617,14 +1728,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);
 }
 
 /**
@@ -1726,8 +1843,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);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index b47de70..c60f5f1 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -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);
 
 static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
 				 u8 attr_set, u32 mib_val)
@@ -246,4 +252,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 */
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index c7d6a1b..d60703f 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -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
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 5/7] scsi: ufs: rework link start-up process
  2013-04-24 16:06 [PATCH 5/5] scsi: ufs: add dme operations Seungwon Jeon
                   ` (3 preceding siblings ...)
  2013-05-04  8:45 ` [PATCH v2 7/7] scsi: ufs: add dme control primitives Seungwon Jeon
@ 2013-05-04  8:46 ` Seungwon Jeon
  2013-05-04  8:46 ` [PATCH v2 6/7] scsi: ufs: add dme configuration primitives Seungwon Jeon
  5 siblings, 0 replies; 14+ messages in thread
From: Seungwon Jeon @ 2013-05-04  8:46 UTC (permalink / raw)
  To: linux-scsi
  Cc: 'Vinayak Holikatti', 'Santosh Y',
	'Sujit Reddy Thumma', 'James E.J. Bottomley'

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 <tgih.jun@samsung.com>
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
---
 drivers/scsi/ufs/ufshcd.c |  287 ++++++++++++++++++++++++++++++---------------
 drivers/scsi/ufs/ufshcd.h |   10 +-
 2 files changed, 200 insertions(+), 97 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 442195c..9c94d42 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -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	500
 
 enum {
 	UFSHCD_MAX_CHANNEL	= 0,
@@ -410,24 +414,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
  *
@@ -971,34 +1066,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;
 }
 
 /**
@@ -1007,9 +1084,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
  */
@@ -1026,6 +1104,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
@@ -1039,17 +1133,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;
 }
@@ -1118,34 +1206,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;
 }
 
 /**
@@ -1185,12 +1268,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;
 }
 
@@ -1443,6 +1533,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
  */
@@ -1482,28 +1583,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
  */
@@ -1564,7 +1643,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);
@@ -1787,6 +1866,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,
@@ -1948,12 +2042,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) {
@@ -1974,14 +2070,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:
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index a874452..6095b3b 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -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 */
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 6/7] scsi: ufs: add dme configuration primitives
  2013-04-24 16:06 [PATCH 5/5] scsi: ufs: add dme operations Seungwon Jeon
                   ` (4 preceding siblings ...)
  2013-05-04  8:46 ` [PATCH v2 5/7] scsi: ufs: rework link start-up process Seungwon Jeon
@ 2013-05-04  8:46 ` Seungwon Jeon
  2013-05-06 10:40   ` merez
  5 siblings, 1 reply; 14+ messages in thread
From: Seungwon Jeon @ 2013-05-04  8:46 UTC (permalink / raw)
  To: linux-scsi
  Cc: 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

Implements 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.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
---
 drivers/scsi/ufs/ufshcd.c |   84 +++++++++++++++++++++++++++++
 drivers/scsi/ufs/ufshcd.h |   29 ++++++++++
 drivers/scsi/ufs/ufshci.h |    4 ++
 drivers/scsi/ufs/unipro.h |  129 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 246 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/ufs/unipro.h

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9c94d42..956041c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -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
@@ -1079,6 +1091,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
  *
@@ -1540,6 +1622,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);
 }
 
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 6095b3b..b47de70 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -217,4 +217,33 @@ 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);
+
+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 */
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index f1e1b74..c7d6a1b 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -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,
diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
new file mode 100644
index 0000000..9f55ac9
--- /dev/null
+++ b/drivers/scsi/ufs/unipro.h
@@ -0,0 +1,129 @@
+/*
+ * drivers/scsi/ufs/unipro.h
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _UNIPRO_H_
+#define _UNIPRO_H_
+
+/*
+ * PHY Adpater attributes
+ */
+#define PA_ACTIVETXDATALANES	0x1560
+#define PA_ACTIVERXDATALANES	0x1580
+#define PA_TXTRAILINGCLOCKS	0x1564
+#define PA_PHY_TYPE		0x1500
+#define PA_AVAILTXDATALANES	0x1520
+#define PA_AVAILRXDATALANES	0x1540
+#define PA_MINRXTRAILINGCLOCKS	0x1543
+#define PA_TXPWRSTATUS		0x1567
+#define PA_RXPWRSTATUS		0x1582
+#define PA_TXFORCECLOCK		0x1562
+#define PA_TXPWRMODE		0x1563
+#define PA_LEGACYDPHYESCDL	0x1570
+#define PA_MAXTXSPEEDFAST	0x1521
+#define PA_MAXTXSPEEDSLOW	0x1522
+#define PA_MAXRXSPEEDFAST	0x1541
+#define PA_MAXRXSPEEDSLOW	0x1542
+#define PA_TXLINKSTARTUPHS	0x1544
+#define PA_TXSPEEDFAST		0x1565
+#define PA_TXSPEEDSLOW		0x1566
+#define PA_REMOTEVERINFO	0x15A0
+#define PA_TXGEAR		0x1568
+#define PA_TXTERMINATION	0x1569
+#define PA_HSSERIES		0x156A
+#define PA_PWRMODE		0x1571
+#define PA_RXGEAR		0x1583
+#define PA_RXTERMINATION	0x1584
+#define PA_MAXRXPWMGEAR		0x1586
+#define PA_MAXRXHSGEAR		0x1587
+#define PA_RXHSUNTERMCAP	0x15A5
+#define PA_RXLSTERMCAP		0x15A6
+#define PA_PACPREQTIMEOUT	0x1590
+#define PA_PACPREQEOBTIMEOUT	0x1591
+#define PA_LOCALVERINFO		0x15A9
+#define PA_TACTIVATE		0x15A8
+#define PA_PACPFRAMECOUNT	0x15C0
+#define PA_PACPERRORCOUNT	0x15C1
+#define PA_PHYTESTCONTROL	0x15C2
+#define PA_PWRMODEUSERDATA0	0x15B0
+#define PA_PWRMODEUSERDATA1	0x15B1
+#define PA_PWRMODEUSERDATA2	0x15B2
+#define PA_PWRMODEUSERDATA3	0x15B3
+#define PA_PWRMODEUSERDATA4	0x15B4
+#define PA_PWRMODEUSERDATA5	0x15B5
+#define PA_PWRMODEUSERDATA6	0x15B6
+#define PA_PWRMODEUSERDATA7	0x15B7
+#define PA_PWRMODEUSERDATA8	0x15B8
+#define PA_PWRMODEUSERDATA9	0x15B9
+#define PA_PWRMODEUSERDATA10	0x15BA
+#define PA_PWRMODEUSERDATA11	0x15BB
+#define PA_CONNECTEDTXDATALANE	0x1561
+#define PA_CONNECTEDRXDATALANE	0x1581
+#define PA_LOGICALLANEMAP	0x15A1
+#define PA_SLEEPNOCONFIGTIME	0x15A2
+#define PA_STALLNOCONFIGTIME	0x15A3
+#define PA_SAVECONFIGTIME	0x15A4
+
+/*
+ * Data Link Layer Attributes
+ */
+#define DL_TC0TXFCTHRESHOLD	0x2040
+#define DL_FC0PROTTIMEOUTVAL	0x2041
+#define DL_TC0REPLAYTIMEOUTVAL	0x2042
+#define DL_AFC0REQTIMEOUTVAL	0x2043
+#define DL_AFC0CREDITTHRESHOLD	0x2044
+#define DL_TC0OUTACKTHRESHOLD	0x2045
+#define DL_TC1TXFCTHRESHOLD	0x2060
+#define DL_FC1PROTTIMEOUTVAL	0x2061
+#define DL_TC1REPLAYTIMEOUTVAL	0x2062
+#define DL_AFC1REQTIMEOUTVAL	0x2063
+#define DL_AFC1CREDITTHRESHOLD	0x2064
+#define DL_TC1OUTACKTHRESHOLD	0x2065
+#define DL_TXPREEMPTIONCAP	0x2000
+#define DL_TC0TXMAXSDUSIZE	0x2001
+#define DL_TC0RXINITCREDITVAL	0x2002
+#define DL_TC0TXBUFFERSIZE	0x2005
+#define DL_PEERTC0PRESENT	0x2046
+#define DL_PEERTC0RXINITCREVAL	0x2047
+#define DL_TC1TXMAXSDUSIZE	0x2003
+#define DL_TC1RXINITCREDITVAL	0x2004
+#define DL_TC1TXBUFFERSIZE	0x2006
+#define DL_PEERTC1PRESENT	0x2066
+#define DL_PEERTC1RXINITCREVAL	0x2067
+
+/*
+ * Network Layer Attributes
+ */
+#define N_DEVICEID		0x3000
+#define N_DEVICEID_VALID	0x3001
+#define N_TC0TXMAXSDUSIZE	0x3020
+#define N_TC1TXMAXSDUSIZE	0x3021
+
+/*
+ * Transport Layer Attributes
+ */
+#define T_NUMCPORTS		0x4000
+#define T_NUMTESTFEATURES	0x4001
+#define T_CONNECTIONSTATE	0x4020
+#define T_PEERDEVICEID		0x4021
+#define T_PEERCPORTID		0x4022
+#define T_TRAFFICCLASS		0x4023
+#define T_PROTOCOLID		0x4024
+#define T_CPORTFLAGS		0x4025
+#define T_TXTOKENVALUE		0x4026
+#define T_RXTOKENVALUE		0x4027
+#define T_LOCALBUFFERSPACE	0x4028
+#define T_PEERBUFFERSPACE	0x4029
+#define T_CREDITSTOSEND		0x402A
+#define T_CPORTMODE		0x402B
+#define T_TC0TXMAXSDUSIZE	0x4060
+#define T_TC1TXMAXSDUSIZE	0x4061
+
+#endif /* _UNIPRO_H_ */
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 7/7] scsi: ufs: add dme control primitives
  2013-05-04  8:45 ` [PATCH v2 7/7] scsi: ufs: add dme control primitives Seungwon Jeon
@ 2013-05-04 18:51   ` Sujit Reddy Thumma
  2013-05-06  3:12     ` Seungwon Jeon
  2013-05-06 10:41   ` merez
  1 sibling, 1 reply; 14+ messages in thread
From: Sujit Reddy Thumma @ 2013-05-04 18:51 UTC (permalink / raw)
  To: Seungwon Jeon
  Cc: linux-scsi, 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

On 5/4/2013 2:15 PM, Seungwon Jeon wrote:
> Implements 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.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> ---
>   drivers/scsi/ufs/ufshcd.c |  133 ++++++++++++++++++++++++++++++++++++++++++---
>   drivers/scsi/ufs/ufshcd.h |   26 +++++++++
>   drivers/scsi/ufs/ufshci.h |   15 +++++
>   3 files changed, 166 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 956041c..54cd61a 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -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
> @@ -1161,6 +1174,104 @@ 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)
Instead of "xxx" can we have meaningful name like "switch" or "toggle"?

> +{
> +	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);
> +	ret = __ufshcd_send_uic_cmd(hba, &uic_cmd);
> +	if (ret) {
> +		dev_err(hba->dev, "%s: error code %d\n", hibern8, ret);
> +		goto out;
> +	}
> +
> +	init_completion(&hba->hibern8_done);
Inititalizing here seems to be inappropriate, say you have back to back 
interrupts of UIC cmd and hibernate state enter/exit just before this 
init, there could be kernel crashes. Probably, you want to move this 
before sending uic cmd.

> +
> +	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
>    *
> @@ -1617,14 +1728,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);
>   }
>
>   /**
> @@ -1726,8 +1843,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);
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index b47de70..c60f5f1 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -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);
>
>   static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
>   				 u8 attr_set, u32 mib_val)
> @@ -246,4 +252,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 */
> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
> index c7d6a1b..d60703f 100644
> --- a/drivers/scsi/ufs/ufshci.h
> +++ b/drivers/scsi/ufs/ufshci.h
> @@ -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
>

-- 
Regards,
Sujit

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH v2 7/7] scsi: ufs: add dme control primitives
  2013-05-04 18:51   ` Sujit Reddy Thumma
@ 2013-05-06  3:12     ` Seungwon Jeon
  0 siblings, 0 replies; 14+ messages in thread
From: Seungwon Jeon @ 2013-05-06  3:12 UTC (permalink / raw)
  To: 'Sujit Reddy Thumma'
  Cc: linux-scsi, 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

On Sunday, May 05, 2013, Sujit Reddy Thumma wrote:
> On 5/4/2013 2:15 PM, Seungwon Jeon wrote:
> > Implements 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.
> >
> > Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> > ---
> >   drivers/scsi/ufs/ufshcd.c |  133 ++++++++++++++++++++++++++++++++++++++++++---
> >   drivers/scsi/ufs/ufshcd.h |   26 +++++++++
> >   drivers/scsi/ufs/ufshci.h |   15 +++++
> >   3 files changed, 166 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index 956041c..54cd61a 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -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
> > @@ -1161,6 +1174,104 @@ 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)
> Instead of "xxx" can we have meaningful name like "switch" or "toggle"?
It is just intended to express the standard's primitives name fully keeping intact.
For actual usage, this function is wrapped like the followings. 

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);
}

> 
> > +{
> > +	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);
> > +	ret = __ufshcd_send_uic_cmd(hba, &uic_cmd);
> > +	if (ret) {
> > +		dev_err(hba->dev, "%s: error code %d\n", hibern8, ret);
> > +		goto out;
> > +	}
> > +
> > +	init_completion(&hba->hibern8_done);
> Inititalizing here seems to be inappropriate, say you have back to back
> interrupts of UIC cmd and hibernate state enter/exit just before this
> init, there could be kernel crashes. Probably, you want to move this
> before sending uic cmd.
Yes, it makes sense.
If hibernation process is finished quickly after uic command is done,
it should be considered. I'll apply it.

Thanks,
Seungwon Jeon
> 
> > +
> > +	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
> >    *
> > @@ -1617,14 +1728,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);
> >   }
> >
> >   /**
> > @@ -1726,8 +1843,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);
> > diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> > index b47de70..c60f5f1 100644
> > --- a/drivers/scsi/ufs/ufshcd.h
> > +++ b/drivers/scsi/ufs/ufshcd.h
> > @@ -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);
> >
> >   static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
> >   				 u8 attr_set, u32 mib_val)
> > @@ -246,4 +252,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 */
> > diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
> > index c7d6a1b..d60703f 100644
> > --- a/drivers/scsi/ufs/ufshci.h
> > +++ b/drivers/scsi/ufs/ufshci.h
> > @@ -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
> >
> 
> --
> Regards,
> Sujit
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 6/7] scsi: ufs: add dme configuration primitives
  2013-05-04  8:46 ` [PATCH v2 6/7] scsi: ufs: add dme configuration primitives Seungwon Jeon
@ 2013-05-06 10:40   ` merez
  0 siblings, 0 replies; 14+ messages in thread
From: merez @ 2013-05-06 10:40 UTC (permalink / raw)
  To: Seungwon Jeon
  Cc: linux-scsi, 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

Tested-by: Maya Erez <merez@codeaurora.org>

> Implements 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.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> ---
>  drivers/scsi/ufs/ufshcd.c |   84 +++++++++++++++++++++++++++++
>  drivers/scsi/ufs/ufshcd.h |   29 ++++++++++
>  drivers/scsi/ufs/ufshci.h |    4 ++
>  drivers/scsi/ufs/unipro.h |  129
> +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 246 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/scsi/ufs/unipro.h
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 9c94d42..956041c 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -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
> @@ -1079,6 +1091,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
>   *
> @@ -1540,6 +1622,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);
>  }
>
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 6095b3b..b47de70 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -217,4 +217,33 @@ 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);
> +
> +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 */
> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
> index f1e1b74..c7d6a1b 100644
> --- a/drivers/scsi/ufs/ufshci.h
> +++ b/drivers/scsi/ufs/ufshci.h
> @@ -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,
> diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
> new file mode 100644
> index 0000000..9f55ac9
> --- /dev/null
> +++ b/drivers/scsi/ufs/unipro.h
> @@ -0,0 +1,129 @@
> +/*
> + * drivers/scsi/ufs/unipro.h
> + *
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef _UNIPRO_H_
> +#define _UNIPRO_H_
> +
> +/*
> + * PHY Adpater attributes
> + */
> +#define PA_ACTIVETXDATALANES	0x1560
> +#define PA_ACTIVERXDATALANES	0x1580
> +#define PA_TXTRAILINGCLOCKS	0x1564
> +#define PA_PHY_TYPE		0x1500
> +#define PA_AVAILTXDATALANES	0x1520
> +#define PA_AVAILRXDATALANES	0x1540
> +#define PA_MINRXTRAILINGCLOCKS	0x1543
> +#define PA_TXPWRSTATUS		0x1567
> +#define PA_RXPWRSTATUS		0x1582
> +#define PA_TXFORCECLOCK		0x1562
> +#define PA_TXPWRMODE		0x1563
> +#define PA_LEGACYDPHYESCDL	0x1570
> +#define PA_MAXTXSPEEDFAST	0x1521
> +#define PA_MAXTXSPEEDSLOW	0x1522
> +#define PA_MAXRXSPEEDFAST	0x1541
> +#define PA_MAXRXSPEEDSLOW	0x1542
> +#define PA_TXLINKSTARTUPHS	0x1544
> +#define PA_TXSPEEDFAST		0x1565
> +#define PA_TXSPEEDSLOW		0x1566
> +#define PA_REMOTEVERINFO	0x15A0
> +#define PA_TXGEAR		0x1568
> +#define PA_TXTERMINATION	0x1569
> +#define PA_HSSERIES		0x156A
> +#define PA_PWRMODE		0x1571
> +#define PA_RXGEAR		0x1583
> +#define PA_RXTERMINATION	0x1584
> +#define PA_MAXRXPWMGEAR		0x1586
> +#define PA_MAXRXHSGEAR		0x1587
> +#define PA_RXHSUNTERMCAP	0x15A5
> +#define PA_RXLSTERMCAP		0x15A6
> +#define PA_PACPREQTIMEOUT	0x1590
> +#define PA_PACPREQEOBTIMEOUT	0x1591
> +#define PA_LOCALVERINFO		0x15A9
> +#define PA_TACTIVATE		0x15A8
> +#define PA_PACPFRAMECOUNT	0x15C0
> +#define PA_PACPERRORCOUNT	0x15C1
> +#define PA_PHYTESTCONTROL	0x15C2
> +#define PA_PWRMODEUSERDATA0	0x15B0
> +#define PA_PWRMODEUSERDATA1	0x15B1
> +#define PA_PWRMODEUSERDATA2	0x15B2
> +#define PA_PWRMODEUSERDATA3	0x15B3
> +#define PA_PWRMODEUSERDATA4	0x15B4
> +#define PA_PWRMODEUSERDATA5	0x15B5
> +#define PA_PWRMODEUSERDATA6	0x15B6
> +#define PA_PWRMODEUSERDATA7	0x15B7
> +#define PA_PWRMODEUSERDATA8	0x15B8
> +#define PA_PWRMODEUSERDATA9	0x15B9
> +#define PA_PWRMODEUSERDATA10	0x15BA
> +#define PA_PWRMODEUSERDATA11	0x15BB
> +#define PA_CONNECTEDTXDATALANE	0x1561
> +#define PA_CONNECTEDRXDATALANE	0x1581
> +#define PA_LOGICALLANEMAP	0x15A1
> +#define PA_SLEEPNOCONFIGTIME	0x15A2
> +#define PA_STALLNOCONFIGTIME	0x15A3
> +#define PA_SAVECONFIGTIME	0x15A4
> +
> +/*
> + * Data Link Layer Attributes
> + */
> +#define DL_TC0TXFCTHRESHOLD	0x2040
> +#define DL_FC0PROTTIMEOUTVAL	0x2041
> +#define DL_TC0REPLAYTIMEOUTVAL	0x2042
> +#define DL_AFC0REQTIMEOUTVAL	0x2043
> +#define DL_AFC0CREDITTHRESHOLD	0x2044
> +#define DL_TC0OUTACKTHRESHOLD	0x2045
> +#define DL_TC1TXFCTHRESHOLD	0x2060
> +#define DL_FC1PROTTIMEOUTVAL	0x2061
> +#define DL_TC1REPLAYTIMEOUTVAL	0x2062
> +#define DL_AFC1REQTIMEOUTVAL	0x2063
> +#define DL_AFC1CREDITTHRESHOLD	0x2064
> +#define DL_TC1OUTACKTHRESHOLD	0x2065
> +#define DL_TXPREEMPTIONCAP	0x2000
> +#define DL_TC0TXMAXSDUSIZE	0x2001
> +#define DL_TC0RXINITCREDITVAL	0x2002
> +#define DL_TC0TXBUFFERSIZE	0x2005
> +#define DL_PEERTC0PRESENT	0x2046
> +#define DL_PEERTC0RXINITCREVAL	0x2047
> +#define DL_TC1TXMAXSDUSIZE	0x2003
> +#define DL_TC1RXINITCREDITVAL	0x2004
> +#define DL_TC1TXBUFFERSIZE	0x2006
> +#define DL_PEERTC1PRESENT	0x2066
> +#define DL_PEERTC1RXINITCREVAL	0x2067
> +
> +/*
> + * Network Layer Attributes
> + */
> +#define N_DEVICEID		0x3000
> +#define N_DEVICEID_VALID	0x3001
> +#define N_TC0TXMAXSDUSIZE	0x3020
> +#define N_TC1TXMAXSDUSIZE	0x3021
> +
> +/*
> + * Transport Layer Attributes
> + */
> +#define T_NUMCPORTS		0x4000
> +#define T_NUMTESTFEATURES	0x4001
> +#define T_CONNECTIONSTATE	0x4020
> +#define T_PEERDEVICEID		0x4021
> +#define T_PEERCPORTID		0x4022
> +#define T_TRAFFICCLASS		0x4023
> +#define T_PROTOCOLID		0x4024
> +#define T_CPORTFLAGS		0x4025
> +#define T_TXTOKENVALUE		0x4026
> +#define T_RXTOKENVALUE		0x4027
> +#define T_LOCALBUFFERSPACE	0x4028
> +#define T_PEERBUFFERSPACE	0x4029
> +#define T_CREDITSTOSEND		0x402A
> +#define T_CPORTMODE		0x402B
> +#define T_TC0TXMAXSDUSIZE	0x4060
> +#define T_TC1TXMAXSDUSIZE	0x4061
> +
> +#endif /* _UNIPRO_H_ */
> --
> 1.7.0.4
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> 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


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 7/7] scsi: ufs: add dme control primitives
  2013-05-04  8:45 ` [PATCH v2 7/7] scsi: ufs: add dme control primitives Seungwon Jeon
  2013-05-04 18:51   ` Sujit Reddy Thumma
@ 2013-05-06 10:41   ` merez
  1 sibling, 0 replies; 14+ messages in thread
From: merez @ 2013-05-06 10:41 UTC (permalink / raw)
  To: Seungwon Jeon
  Cc: linux-scsi, 'Vinayak Holikatti', 'Santosh Y',
	'James E.J. Bottomley'

Tested-by: Maya Erez <merez@codeaurora.org>

> Implements 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.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> ---
>  drivers/scsi/ufs/ufshcd.c |  133
> ++++++++++++++++++++++++++++++++++++++++++---
>  drivers/scsi/ufs/ufshcd.h |   26 +++++++++
>  drivers/scsi/ufs/ufshci.h |   15 +++++
>  3 files changed, 166 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 956041c..54cd61a 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -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
> @@ -1161,6 +1174,104 @@ 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);
> +	ret = __ufshcd_send_uic_cmd(hba, &uic_cmd);
> +	if (ret) {
> +		dev_err(hba->dev, "%s: error code %d\n", hibern8, ret);
> +		goto out;
> +	}
> +
> +	init_completion(&hba->hibern8_done);
> +
> +	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
>   *
> @@ -1617,14 +1728,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);
>  }
>
>  /**
> @@ -1726,8 +1843,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);
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index b47de70..c60f5f1 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -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);
>
>  static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
>  				 u8 attr_set, u32 mib_val)
> @@ -246,4 +252,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 */
> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
> index c7d6a1b..d60703f 100644
> --- a/drivers/scsi/ufs/ufshci.h
> +++ b/drivers/scsi/ufs/ufshci.h
> @@ -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
> --
> 1.7.0.4
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> 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


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-05-06 10:41 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-24 16:06 [PATCH 5/5] scsi: ufs: add dme operations Seungwon Jeon
2013-05-01  7:52 ` merez
2013-05-02  8:06 ` Santosh Y
2013-05-02  8:07   ` Santosh Y
2013-05-02 13:38     ` Seungwon Jeon
2013-05-02 12:08 ` Subhash Jadavani
2013-05-02 13:39   ` Seungwon Jeon
2013-05-04  8:45 ` [PATCH v2 7/7] scsi: ufs: add dme control primitives Seungwon Jeon
2013-05-04 18:51   ` Sujit Reddy Thumma
2013-05-06  3:12     ` Seungwon Jeon
2013-05-06 10:41   ` merez
2013-05-04  8:46 ` [PATCH v2 5/7] scsi: ufs: rework link start-up process Seungwon Jeon
2013-05-04  8:46 ` [PATCH v2 6/7] scsi: ufs: add dme configuration primitives Seungwon Jeon
2013-05-06 10:40   ` merez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox