All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes
@ 2013-06-26 17:09 Santosh Y
  2013-06-26 17:09 ` [PATCH 01/10] scsi: ufs: wrap the i/o access operations Santosh Y
                   ` (9 more replies)
  0 siblings, 10 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley; +Cc: linux-scsi, vinholikatti, Santosh Y

Hi James,

Sorry for the mail-id typo :-(. Resending the patches.
Please merge the following patches to 'misc' branch.

Thanks,
Santosh

Akinobu Mita (4):
  ufshcd-pltfrm: add missing empty slot in ufs_of_match[]
  ufs: fix register address in UIC error interrupt handling
  ufshcd-pltfrm: remove unnecessary dma_set_coherent_mask() call
  ufs: fix DMA mask setting

Seungwon Jeon (5):
  scsi: ufs: wrap the i/o access operations
  scsi: ufs: amend interrupt configuration
  scsi: ufs: remove version check before IS reg clear
  scsi: ufs: rework link start-up process
  scsi: ufs: use devres functions for ufshcd

Sujit Reddy Thumma (1):
  scsi: ufs: Fix the response UPIU length setting

 drivers/scsi/ufs/ufshcd-pci.c    |  27 ---
 drivers/scsi/ufs/ufshcd-pltfrm.c |  75 ++----
 drivers/scsi/ufs/ufshcd.c        | 484 +++++++++++++++++++++++++--------------
 drivers/scsi/ufs/ufshcd.h        |  21 +-
 drivers/scsi/ufs/ufshci.h        |   5 +-
 5 files changed, 351 insertions(+), 261 deletions(-)

-- 
1.8.3.1


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

* [PATCH 01/10] scsi: ufs: wrap the i/o access operations
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-26 17:09 ` [PATCH 02/10] scsi: ufs: amend interrupt configuration Santosh Y
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley; +Cc: linux-scsi, vinholikatti, Seungwon Jeon, Santosh Y

From: Seungwon Jeon <tgih.jun@samsung.com>

Simplify operations with hiding mmio_base.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Tested-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c32a478..871c2f0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -71,7 +71,7 @@ enum {
  */
 static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
 {
-	return readl(hba->mmio_base + REG_UFS_VERSION);
+	return ufshcd_readl(hba, REG_UFS_VERSION);
 }
 
 /**
@@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(struct ufs_hba *hba)
  */
 static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
 {
-	writel(~(1 << pos),
-		(hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_CLEAR));
+	ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
 }
 
 /**
@@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)
  */
 static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
 {
-	return readl(hba->mmio_base + REG_UIC_COMMAND_ARG_2) &
+	return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2) &
 	       MASK_UIC_COMMAND_RESULT;
 }
 
@@ -243,18 +242,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)
 {
 	switch (option) {
 	case INT_AGGR_RESET:
-		writel((INT_AGGR_ENABLE |
-			INT_AGGR_COUNTER_AND_TIMER_RESET),
-			(hba->mmio_base +
-			 REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+		ufshcd_writel(hba, INT_AGGR_ENABLE |
+			      INT_AGGR_COUNTER_AND_TIMER_RESET,
+			      REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
 		break;
 	case INT_AGGR_CONFIG:
-		writel((INT_AGGR_ENABLE |
-			INT_AGGR_PARAM_WRITE |
-			INT_AGGR_COUNTER_THRESHOLD_VALUE |
-			INT_AGGR_TIMEOUT_VALUE),
-			(hba->mmio_base +
-			 REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+		ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE |
+			      INT_AGGR_COUNTER_THRESHOLD_VALUE |
+			      INT_AGGR_TIMEOUT_VALUE,
+			      REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
 		break;
 	}
 }
@@ -267,12 +263,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)
  */
 static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
 {
-	writel(UTP_TASK_REQ_LIST_RUN_STOP_BIT,
-	       (hba->mmio_base +
-		REG_UTP_TASK_REQ_LIST_RUN_STOP));
-	writel(UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
-	       (hba->mmio_base +
-		REG_UTP_TRANSFER_REQ_LIST_RUN_STOP));
+	ufshcd_writel(hba, UTP_TASK_REQ_LIST_RUN_STOP_BIT,
+		      REG_UTP_TASK_REQ_LIST_RUN_STOP);
+	ufshcd_writel(hba, UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
+		      REG_UTP_TRANSFER_REQ_LIST_RUN_STOP);
 }
 
 /**
@@ -281,7 +275,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
  */
 static inline void ufshcd_hba_start(struct ufs_hba *hba)
 {
-	writel(CONTROLLER_ENABLE , (hba->mmio_base + REG_CONTROLLER_ENABLE));
+	ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE);
 }
 
 /**
@@ -292,7 +286,7 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)
  */
 static inline int ufshcd_is_hba_active(struct ufs_hba *hba)
 {
-	return (readl(hba->mmio_base + REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
+	return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
 }
 
 /**
@@ -304,8 +298,7 @@ static inline
 void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
 {
 	__set_bit(task_tag, &hba->outstanding_reqs);
-	writel((1 << task_tag),
-	       (hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL));
+	ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 }
 
 /**
@@ -329,8 +322,7 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp)
  */
 static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
 {
-	hba->capabilities =
-		readl(hba->mmio_base + REG_CONTROLLER_CAPABILITIES);
+	hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
 
 	/* nutrs and nutmrs are 0 based values */
 	hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
@@ -347,16 +339,13 @@ static inline void
 ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
 {
 	/* Write Args */
-	writel(uic_cmnd->argument1,
-	      (hba->mmio_base + REG_UIC_COMMAND_ARG_1));
-	writel(uic_cmnd->argument2,
-	      (hba->mmio_base + REG_UIC_COMMAND_ARG_2));
-	writel(uic_cmnd->argument3,
-	      (hba->mmio_base + REG_UIC_COMMAND_ARG_3));
+	ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1);
+	ufshcd_writel(hba, uic_cmnd->argument2, REG_UIC_COMMAND_ARG_2);
+	ufshcd_writel(hba, uic_cmnd->argument3, REG_UIC_COMMAND_ARG_3);
 
 	/* Write UIC Cmd */
-	writel((uic_cmnd->command & COMMAND_OPCODE_MASK),
-	       (hba->mmio_base + REG_UIC_COMMAND));
+	ufshcd_writel(hba, uic_cmnd->command & COMMAND_OPCODE_MASK,
+		      REG_UIC_COMMAND);
 }
 
 /**
@@ -408,16 +397,15 @@ static void ufshcd_int_config(struct ufs_hba *hba, u32 option)
 {
 	switch (option) {
 	case UFSHCD_INT_ENABLE:
-		writel(hba->int_enable_mask,
-		      (hba->mmio_base + REG_INTERRUPT_ENABLE));
+		ufshcd_writel(hba, hba->int_enable_mask, REG_INTERRUPT_ENABLE);
 		break;
 	case UFSHCD_INT_DISABLE:
 		if (hba->ufs_version == UFSHCI_VERSION_10)
-			writel(INTERRUPT_DISABLE_MASK_10,
-			      (hba->mmio_base + REG_INTERRUPT_ENABLE));
+			ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_10,
+				      REG_INTERRUPT_ENABLE);
 		else
-			writel(INTERRUPT_DISABLE_MASK_11,
-			       (hba->mmio_base + REG_INTERRUPT_ENABLE));
+			ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_11,
+				      REG_INTERRUPT_ENABLE);
 		break;
 	}
 }
@@ -703,7 +691,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
 	unsigned long flags;
 
 	/* check if controller is ready to accept UIC commands */
-	if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
+	if ((ufshcd_readl(hba, REG_CONTROLLER_STATUS) &
 	    UIC_COMMAND_READY) == 0x0) {
 		dev_err(hba->dev,
 			"Controller not ready"
@@ -748,7 +736,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
 	u32 reg;
 
 	/* check if device present */
-	reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
+	reg = ufshcd_readl(hba, REG_CONTROLLER_STATUS);
 	if (!ufshcd_is_device_present(reg)) {
 		dev_err(hba->dev, "cc: Device not present\n");
 		err = -ENXIO;
@@ -870,14 +858,14 @@ static int ufshcd_initialize_hba(struct ufs_hba *hba)
 		return -EIO;
 
 	/* Configure UTRL and UTMRL base address registers */
-	writel(lower_32_bits(hba->utrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
-	writel(upper_32_bits(hba->utrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
-	writel(lower_32_bits(hba->utmrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
-	writel(upper_32_bits(hba->utmrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
+	ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
+		      REG_UTP_TRANSFER_REQ_LIST_BASE_L);
+	ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
+		      REG_UTP_TRANSFER_REQ_LIST_BASE_H);
+	ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
+		      REG_UTP_TASK_REQ_LIST_BASE_L);
+	ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
+		      REG_UTP_TASK_REQ_LIST_BASE_H);
 
 	/* Initialize unipro link startup procedure */
 	return ufshcd_dme_link_startup(hba);
@@ -1169,8 +1157,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
 	int index;
 
 	lrb = hba->lrb;
-	tr_doorbell =
-		readl(hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL);
+	tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 	completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
 
 	for (index = 0; index < hba->nutrs; index++) {
@@ -1244,9 +1231,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba)
 		goto fatal_eh;
 
 	if (hba->errors & UIC_ERROR) {
-
-		reg = readl(hba->mmio_base +
-			    REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
+		reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
 		if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
 			goto fatal_eh;
 	}
@@ -1264,7 +1249,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba)
 {
 	u32 tm_doorbell;
 
-	tm_doorbell = readl(hba->mmio_base + REG_UTP_TASK_REQ_DOOR_BELL);
+	tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
 	hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;
 	wake_up_interruptible(&hba->ufshcd_tm_wait_queue);
 }
@@ -1305,15 +1290,14 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
 	struct ufs_hba *hba = __hba;
 
 	spin_lock(hba->host->host_lock);
-	intr_status = readl(hba->mmio_base + REG_INTERRUPT_STATUS);
+	intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
 
 	if (intr_status) {
 		ufshcd_sl_intr(hba, intr_status);
 
 		/* If UFSHCI 1.0 then clear interrupt status register */
 		if (hba->ufs_version == UFSHCI_VERSION_10)
-			writel(intr_status,
-			       (hba->mmio_base + REG_INTERRUPT_STATUS));
+			ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
 		retval = IRQ_HANDLED;
 	}
 	spin_unlock(hba->host->host_lock);
@@ -1378,8 +1362,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 
 	/* send command to the controller */
 	__set_bit(free_slot, &hba->outstanding_tasks);
-	writel((1 << free_slot),
-	       (hba->mmio_base + REG_UTP_TASK_REQ_DOOR_BELL));
+	ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL);
 
 	spin_unlock_irqrestore(host->host_lock, flags);
 
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 6b99a42..807dd2d 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -186,6 +186,11 @@ struct ufs_hba {
 	u32 errors;
 };
 
+#define ufshcd_writel(hba, val, reg)	\
+	writel((val), (hba)->mmio_base + (reg))
+#define ufshcd_readl(hba, reg)	\
+	readl((hba)->mmio_base + (reg))
+
 int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
 			unsigned int);
 void ufshcd_remove(struct ufs_hba *);
@@ -196,7 +201,7 @@ void ufshcd_remove(struct ufs_hba *);
  */
 static inline void ufshcd_hba_stop(struct ufs_hba *hba)
 {
-	writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
+	ufshcd_writel(hba, CONTROLLER_DISABLE,  REG_CONTROLLER_ENABLE);
 }
 
 #endif /* End of Header */
-- 
1.8.3.1


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

* [PATCH 02/10] scsi: ufs: amend interrupt configuration
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
  2013-06-26 17:09 ` [PATCH 01/10] scsi: ufs: wrap the i/o access operations Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-26 17:09 ` [PATCH 03/10] scsi: ufs: remove version check before IS reg clear Santosh Y
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley; +Cc: linux-scsi, vinholikatti, Seungwon Jeon, Santosh Y

From: Seungwon Jeon <tgih.jun@samsung.com>

It makes interrupt setting more flexible especially
for disabling. And wrong bit mask is fixed for ver 1.0.
[17:16] is added for mask.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Tested-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 871c2f0..1f1e085 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -35,6 +35,10 @@
 
 #include "ufshcd.h"
 
+#define UFSHCD_ENABLE_INTRS	(UTP_TRANSFER_REQ_COMPL |\
+				 UTP_TASK_REQ_COMPL |\
+				 UFSHCD_ERROR_MASK)
+
 enum {
 	UFSHCD_MAX_CHANNEL	= 0,
 	UFSHCD_MAX_ID		= 1,
@@ -64,6 +68,20 @@ enum {
 };
 
 /**
+ * ufshcd_get_intr_mask - Get the interrupt bit mask
+ * @hba - Pointer to adapter instance
+ *
+ * Returns interrupt bit mask per version
+ */
+static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
+{
+	if (hba->ufs_version == UFSHCI_VERSION_10)
+		return INTERRUPT_MASK_ALL_VER_10;
+	else
+		return INTERRUPT_MASK_ALL_VER_11;
+}
+
+/**
  * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
  * @hba - Pointer to adapter instance
  *
@@ -389,25 +407,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
 }
 
 /**
- * ufshcd_int_config - enable/disable interrupts
+ * ufshcd_enable_intr - enable interrupts
  * @hba: per adapter instance
- * @option: interrupt option
+ * @intrs: interrupt bits
  */
-static void ufshcd_int_config(struct ufs_hba *hba, u32 option)
+static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs)
 {
-	switch (option) {
-	case UFSHCD_INT_ENABLE:
-		ufshcd_writel(hba, hba->int_enable_mask, REG_INTERRUPT_ENABLE);
-		break;
-	case UFSHCD_INT_DISABLE:
-		if (hba->ufs_version == UFSHCI_VERSION_10)
-			ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_10,
-				      REG_INTERRUPT_ENABLE);
-		else
-			ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_11,
-				      REG_INTERRUPT_ENABLE);
-		break;
+	u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+	if (hba->ufs_version == UFSHCI_VERSION_10) {
+		u32 rw;
+		rw = set & INTERRUPT_MASK_RW_VER_10;
+		set = rw | ((set ^ intrs) & intrs);
+	} else {
+		set |= intrs;
+	}
+
+	ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
+}
+
+/**
+ * ufshcd_disable_intr - disable interrupts
+ * @hba: per adapter instance
+ * @intrs: interrupt bits
+ */
+static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
+{
+	u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+	if (hba->ufs_version == UFSHCI_VERSION_10) {
+		u32 rw;
+		rw = (set & INTERRUPT_MASK_RW_VER_10) &
+			~(intrs & INTERRUPT_MASK_RW_VER_10);
+		set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10);
+
+	} else {
+		set &= ~intrs;
 	}
+
+	ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
 }
 
 /**
@@ -709,8 +747,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
 	uic_cmd->argument3 = 0;
 
 	/* enable UIC related interrupts */
-	hba->int_enable_mask |= UIC_COMMAND_COMPL;
-	ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
+	ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
 
 	/* sending UIC commands to controller */
 	ufshcd_send_uic_command(hba, uic_cmd);
@@ -757,13 +794,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
 	}
 
 	/* Enable required interrupts */
-	hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL |
-				 UIC_ERROR |
-				 UTP_TASK_REQ_COMPL |
-				 DEVICE_FATAL_ERROR |
-				 CONTROLLER_FATAL_ERROR |
-				 SYSTEM_BUS_FATAL_ERROR);
-	ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
+	ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS);
 
 	/* Configure interrupt aggregation */
 	ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
@@ -1570,7 +1601,7 @@ static void ufshcd_hba_free(struct ufs_hba *hba)
 void ufshcd_remove(struct ufs_hba *hba)
 {
 	/* disable interrupts */
-	ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
+	ufshcd_disable_intr(hba, hba->intr_mask);
 
 	ufshcd_hba_stop(hba);
 	ufshcd_hba_free(hba);
@@ -1628,6 +1659,9 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
 	/* Get UFS version supported by the controller */
 	hba->ufs_version = ufshcd_get_ufs_version(hba);
 
+	/* Get Interrupt bit mask per version */
+	hba->intr_mask = ufshcd_get_intr_mask(hba);
+
 	/* Allocate memory for host memory space */
 	err = ufshcd_memory_alloc(hba);
 	if (err) {
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 807dd2d..4213600 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -139,7 +139,7 @@ struct ufshcd_lrb {
  * @ufshcd_tm_wait_queue: wait queue for task management
  * @tm_condition: condition variable for task management
  * @ufshcd_state: UFSHCD states
- * @int_enable_mask: Interrupt Mask Bits
+ * @intr_mask: Interrupt Mask Bits
  * @uic_workq: Work queue for UIC completion handling
  * @feh_workq: Work queue for fatal controller error handling
  * @errors: HBA errors
@@ -176,7 +176,7 @@ struct ufs_hba {
 	unsigned long tm_condition;
 
 	u32 ufshcd_state;
-	u32 int_enable_mask;
+	u32 intr_mask;
 
 	/* Work Queues */
 	struct work_struct uic_workq;
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 0c16484..d5c5f14 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -232,10 +232,11 @@ enum {
 /* Interrupt disable masks */
 enum {
 	/* Interrupt disable mask for UFSHCI v1.0 */
-	INTERRUPT_DISABLE_MASK_10	= 0xFFFF,
+	INTERRUPT_MASK_ALL_VER_10	= 0x30FFF,
+	INTERRUPT_MASK_RW_VER_10	= 0x30000,
 
 	/* Interrupt disable mask for UFSHCI v1.1 */
-	INTERRUPT_DISABLE_MASK_11	= 0x0,
+	INTERRUPT_MASK_ALL_VER_11	= 0x31FFF,
 };
 
 /*
-- 
1.8.3.1


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

* [PATCH 03/10] scsi: ufs: remove version check before IS reg clear
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
  2013-06-26 17:09 ` [PATCH 01/10] scsi: ufs: wrap the i/o access operations Santosh Y
  2013-06-26 17:09 ` [PATCH 02/10] scsi: ufs: amend interrupt configuration Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-26 17:09 ` [PATCH 04/10] scsi: ufs: rework link start-up process Santosh Y
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley; +Cc: linux-scsi, vinholikatti, Seungwon Jeon, Santosh Y

From: Seungwon Jeon <tgih.jun@samsung.com>

There is no need to check the version to clear
the interrupt status. And the order is changed
prior to actual handling.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Tested-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 1f1e085..2e02483 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1324,11 +1324,8 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
 	intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
 
 	if (intr_status) {
+		ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
 		ufshcd_sl_intr(hba, intr_status);
-
-		/* If UFSHCI 1.0 then clear interrupt status register */
-		if (hba->ufs_version == UFSHCI_VERSION_10)
-			ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
 		retval = IRQ_HANDLED;
 	}
 	spin_unlock(hba->host->host_lock);
-- 
1.8.3.1


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

* [PATCH 04/10] scsi: ufs: rework link start-up process
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
                   ` (2 preceding siblings ...)
  2013-06-26 17:09 ` [PATCH 03/10] scsi: ufs: remove version check before IS reg clear Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-26 17:09 ` [PATCH 05/10] scsi: ufs: Fix the response UPIU length setting Santosh Y
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, vinholikatti, Seungwon Jeon, Sujit Reddy Thumma, Santosh Y

From: Seungwon Jeon <tgih.jun@samsung.com>

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>
Tested-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2e02483..48a7645 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,
@@ -349,24 +353,122 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
 }
 
 /**
- * ufshcd_send_uic_command - Send UIC commands to unipro layers
+ * ufshcd_ready_for_uic_cmd - Check if controller is ready
+ *                            to accept UIC commands
  * @hba: per adapter instance
- * @uic_command: UIC command
+ * Return true on success, else false
+ */
+static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
+{
+	if (ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY)
+		return true;
+	else
+		return false;
+}
+
+/**
+ * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Mutex must be held.
  */
 static inline void
-ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
+ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
+	WARN_ON(hba->active_uic_cmd);
+
+	hba->active_uic_cmd = uic_cmd;
+
 	/* Write Args */
-	ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1);
-	ufshcd_writel(hba, uic_cmnd->argument2, REG_UIC_COMMAND_ARG_2);
-	ufshcd_writel(hba, uic_cmnd->argument3, REG_UIC_COMMAND_ARG_3);
+	ufshcd_writel(hba, uic_cmd->argument1, REG_UIC_COMMAND_ARG_1);
+	ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2);
+	ufshcd_writel(hba, uic_cmd->argument3, REG_UIC_COMMAND_ARG_3);
 
 	/* Write UIC Cmd */
-	ufshcd_writel(hba, uic_cmnd->command & COMMAND_OPCODE_MASK,
+	ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK,
 		      REG_UIC_COMMAND);
 }
 
 /**
+ * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command
+ * @hba: per adapter instance
+ * @uic_command: UIC command
+ *
+ * Must be called with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+	int ret;
+	unsigned long flags;
+
+	if (wait_for_completion_timeout(&uic_cmd->done,
+					msecs_to_jiffies(UIC_CMD_TIMEOUT)))
+		ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
+	else
+		ret = -ETIMEDOUT;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	hba->active_uic_cmd = NULL;
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	return ret;
+}
+
+/**
+ * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
+ * with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+	int ret;
+	unsigned long flags;
+
+	if (!ufshcd_ready_for_uic_cmd(hba)) {
+		dev_err(hba->dev,
+			"Controller not ready to accept UIC commands\n");
+		return -EIO;
+	}
+
+	init_completion(&uic_cmd->done);
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
+
+	return ret;
+}
+
+/**
+ * ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+	int ret;
+
+	mutex_lock(&hba->uic_cmd_mutex);
+	ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+	mutex_unlock(&hba->uic_cmd_mutex);
+
+	return ret;
+}
+
+/**
  * ufshcd_map_sg - Map scatter-gather list to prdt
  * @lrbp - pointer to local reference block
  *
@@ -725,34 +827,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;
-	}
+	uic_cmd.command = UIC_CMD_DME_LINK_STARTUP;
 
-	spin_lock_irqsave(hba->host->host_lock, flags);
-
-	/* form UIC command */
-	uic_cmd = &hba->active_uic_cmd;
-	uic_cmd->command = UIC_CMD_DME_LINK_STARTUP;
-	uic_cmd->argument1 = 0;
-	uic_cmd->argument2 = 0;
-	uic_cmd->argument3 = 0;
-
-	/* enable UIC related interrupts */
-	ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
-
-	/* sending UIC commands to controller */
-	ufshcd_send_uic_command(hba, uic_cmd);
-	spin_unlock_irqrestore(hba->host->host_lock, flags);
-	return 0;
+	ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+	if (ret)
+		dev_err(hba->dev,
+			"dme-link-startup: error code %d\n", ret);
+	return ret;
 }
 
 /**
@@ -761,9 +845,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
  */
@@ -780,6 +865,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
@@ -793,17 +894,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;
 }
@@ -872,34 +967,28 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
 }
 
 /**
- * ufshcd_initialize_hba - start the initialization process
+ * ufshcd_link_startup - Initialize unipro link startup
  * @hba: per adapter instance
  *
- * 1. Enable the controller via ufshcd_hba_enable.
- * 2. Program the Transfer Request List Address with the starting address of
- * UTRDL.
- * 3. Program the Task Management Request List Address with starting address
- * of UTMRDL.
- *
- * Returns 0 on success, non-zero value on failure.
+ * Returns 0 for success, non-zero in case of failure
  */
-static int ufshcd_initialize_hba(struct ufs_hba *hba)
+static int ufshcd_link_startup(struct ufs_hba *hba)
 {
-	if (ufshcd_hba_enable(hba))
-		return -EIO;
+	int ret;
 
-	/* Configure UTRL and UTMRL base address registers */
-	ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
-		      REG_UTP_TRANSFER_REQ_LIST_BASE_L);
-	ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
-		      REG_UTP_TRANSFER_REQ_LIST_BASE_H);
-	ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
-		      REG_UTP_TASK_REQ_LIST_BASE_L);
-	ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
-		      REG_UTP_TASK_REQ_LIST_BASE_H);
+	/* enable UIC related interrupts */
+	ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
+
+	ret = ufshcd_dme_link_startup(hba);
+	if (ret)
+		goto out;
+
+	ret = ufshcd_make_hba_operational(hba);
 
-	/* Initialize unipro link startup procedure */
-	return ufshcd_dme_link_startup(hba);
+out:
+	if (ret)
+		dev_err(hba->dev, "link startup failed %d\n", ret);
+	return ret;
 }
 
 /**
@@ -939,12 +1028,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;
 }
 
@@ -1176,6 +1272,19 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
 }
 
 /**
+ * ufshcd_uic_cmd_compl - handle completion of uic command
+ * @hba: per adapter instance
+ */
+static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)
+{
+	if (hba->active_uic_cmd) {
+		hba->active_uic_cmd->argument2 |=
+			ufshcd_get_uic_cmd_result(hba);
+		complete(&hba->active_uic_cmd->done);
+	}
+}
+
+/**
  * ufshcd_transfer_req_compl - handle SCSI and query command completion
  * @hba: per adapter instance
  */
@@ -1215,28 +1324,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
  */
@@ -1297,7 +1384,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);
@@ -1520,6 +1607,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,
@@ -1681,9 +1783,11 @@ 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 UIC command mutex */
+	mutex_init(&hba->uic_cmd_mutex);
+
 	/* IRQ registration */
 	err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
 	if (err) {
@@ -1704,14 +1808,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 4213600..49590ee 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>
@@ -75,6 +76,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;
@@ -83,6 +85,7 @@ struct uic_command {
 	u32 argument3;
 	int cmd_active;
 	int result;
+	struct completion done;
 };
 
 /**
@@ -136,11 +139,11 @@ struct ufshcd_lrb {
  * @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
  */
@@ -171,7 +174,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;
 
@@ -179,7 +184,6 @@ struct ufs_hba {
 	u32 intr_mask;
 
 	/* Work Queues */
-	struct work_struct uic_workq;
 	struct work_struct feh_workq;
 
 	/* HBA Errors */
-- 
1.8.3.1


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

* [PATCH 05/10] scsi: ufs: Fix the response UPIU length setting
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
                   ` (3 preceding siblings ...)
  2013-06-26 17:09 ` [PATCH 04/10] scsi: ufs: rework link start-up process Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-26 17:09 ` [PATCH 06/10] scsi: ufs: use devres functions for ufshcd Santosh Y
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, vinholikatti, Sujit Reddy Thumma, Maya Erez, Santosh Y

From: Sujit Reddy Thumma <sthumma@codeaurora.org>

The response UPIU length should be in DWORD and not in bytes.

Signed-off-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 48a7645..2230f14 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -802,7 +802,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
 		utrdlp[i].prd_table_offset =
 				cpu_to_le16((prdt_offset >> 2));
 		utrdlp[i].response_upiu_length =
-				cpu_to_le16(ALIGNED_UPIU_SIZE);
+				cpu_to_le16(ALIGNED_UPIU_SIZE >> 2);
 
 		hba->lrb[i].utr_descriptor_ptr = (utrdlp + i);
 		hba->lrb[i].ucd_cmd_ptr =
-- 
1.8.3.1


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

* [PATCH 06/10] scsi: ufs: use devres functions for ufshcd
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
                   ` (4 preceding siblings ...)
  2013-06-26 17:09 ` [PATCH 05/10] scsi: ufs: Fix the response UPIU length setting Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-27  4:31   ` [PATCH v2 " Seungwon Jeon
  2013-06-26 17:09 ` [PATCH 07/10] ufshcd-pltfrm: add missing empty slot in ufs_of_match[] Santosh Y
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley; +Cc: linux-scsi, vinholikatti, Seungwon Jeon, Santosh Y

From: Seungwon Jeon <tgih.jun@samsung.com>

This patch replaces normal calls for resource allocation with devm_*()
derivative functions. It makes resource freeing simpler.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index 5cb1d75..48be39a 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -92,7 +92,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)
 	struct ufs_hba *hba = pci_get_drvdata(pdev);
 
 	disable_irq(pdev->irq);
-	free_irq(pdev->irq, hba);
 	ufshcd_remove(hba);
 	pci_release_regions(pdev);
 	pci_set_drvdata(pdev, NULL);
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 3db2ee1..0e48827 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -33,9 +33,10 @@
  * this program.
  */
 
-#include "ufshcd.h"
 #include <linux/platform_device.h>
 
+#include "ufshcd.h"
+
 #ifdef CONFIG_PM
 /**
  * ufshcd_pltfrm_suspend - suspend power management function
@@ -97,62 +98,45 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
 	struct ufs_hba *hba;
 	void __iomem *mmio_base;
 	struct resource *mem_res;
-	struct resource *irq_res;
-	resource_size_t mem_size;
-	int err;
+	int irq, err;
 	struct device *dev = &pdev->dev;
 
 	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem_res) {
-		dev_err(&pdev->dev,
-			"Memory resource not available\n");
+		dev_err(dev, "Memory resource not available\n");
 		err = -ENODEV;
-		goto out_error;
+		goto out;
 	}
 
-	mem_size = resource_size(mem_res);
-	if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
-		dev_err(&pdev->dev,
-			"Cannot reserve the memory resource\n");
-		err = -EBUSY;
-		goto out_error;
+	mmio_base = devm_ioremap_resource(dev, mem_res);
+	if (IS_ERR(mmio_base)) {
+		dev_err(dev, "memory map failed\n");
+		err = PTR_ERR(mmio_base);
+		goto out;
 	}
 
-	mmio_base = ioremap_nocache(mem_res->start, mem_size);
-	if (!mmio_base) {
-		dev_err(&pdev->dev, "memory map failed\n");
-		err = -ENOMEM;
-		goto out_release_regions;
-	}
-
-	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!irq_res) {
-		dev_err(&pdev->dev, "IRQ resource not available\n");
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "IRQ resource not available\n");
 		err = -ENODEV;
-		goto out_iounmap;
+		goto out;
 	}
 
 	err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
 	if (err) {
-		dev_err(&pdev->dev, "set dma mask failed\n");
-		goto out_iounmap;
+		dev_err(dev, "set dma mask failed\n");
+		goto out;
 	}
 
-	err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
+	err = ufshcd_init(dev, &hba, mmio_base, irq);
 	if (err) {
-		dev_err(&pdev->dev, "Intialization failed\n");
-		goto out_iounmap;
+		dev_err(dev, "Intialization failed\n");
+		goto out;
 	}
 
 	platform_set_drvdata(pdev, hba);
 
-	return 0;
-
-out_iounmap:
-	iounmap(mmio_base);
-out_release_regions:
-	release_mem_region(mem_res->start, mem_size);
-out_error:
+out:
 	return err;
 }
 
@@ -164,26 +148,10 @@ out_error:
  */
 static int ufshcd_pltfrm_remove(struct platform_device *pdev)
 {
-	struct resource *mem_res;
-	resource_size_t mem_size;
 	struct ufs_hba *hba =  platform_get_drvdata(pdev);
 
 	disable_irq(hba->irq);
-
-	/* Some buggy controllers raise interrupt after
-	 * the resources are removed. So first we unregister the
-	 * irq handler and then the resources used by driver
-	 */
-
-	free_irq(hba->irq, hba);
 	ufshcd_remove(hba);
-	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem_res)
-		dev_err(&pdev->dev, "ufshcd: Memory resource not available\n");
-	else {
-		mem_size = resource_size(mem_res);
-		release_mem_region(mem_res->start, mem_size);
-	}
 	return 0;
 }
 
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2230f14..255f5be 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1789,7 +1789,7 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
 	mutex_init(&hba->uic_cmd_mutex);
 
 	/* IRQ registration */
-	err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+	err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
 	if (err) {
 		dev_err(hba->dev, "request irq failed\n");
 		goto out_lrb_free;
@@ -1799,13 +1799,13 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
 	err = scsi_init_shared_tag_map(host, host->can_queue);
 	if (err) {
 		dev_err(hba->dev, "init shared queue failed\n");
-		goto out_free_irq;
+		goto out_lrb_free;
 	}
 
 	err = scsi_add_host(host, hba->dev);
 	if (err) {
 		dev_err(hba->dev, "scsi_add_host failed\n");
-		goto out_free_irq;
+		goto out_lrb_free;
 	}
 
 	/* Host controller enable */
@@ -1823,8 +1823,6 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
 
 out_remove_scsi_host:
 	scsi_remove_host(hba->host);
-out_free_irq:
-	free_irq(irq, hba);
 out_lrb_free:
 	ufshcd_free_hba_memory(hba);
 out_disable:
-- 
1.8.3.1


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

* [PATCH 07/10] ufshcd-pltfrm: add missing empty slot in ufs_of_match[]
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
                   ` (5 preceding siblings ...)
  2013-06-26 17:09 ` [PATCH 06/10] scsi: ufs: use devres functions for ufshcd Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-26 17:09 ` [PATCH 08/10] ufs: fix register address in UIC error interrupt handling Santosh Y
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, vinholikatti, Akinobu Mita, James E.J. Bottomley, Santosh Y

From: Akinobu Mita <mita@fixstars.com>

of_match_table member in struct device_driver must be terminated by
empty slot as a sentinel.

Signed-off-by: Akinobu Mita <mita@fixstars.com>
Cc: Vinayak Holikatti <vinholikatti@gmail.com>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: linux-scsi@vger.kernel.org
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 0e48827..6829a16 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -157,6 +157,7 @@ static int ufshcd_pltfrm_remove(struct platform_device *pdev)
 
 static const struct of_device_id ufs_of_match[] = {
 	{ .compatible = "jedec,ufs-1.1"},
+	{},
 };
 
 static const struct dev_pm_ops ufshcd_dev_pm_ops = {
-- 
1.8.3.1


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

* [PATCH 08/10] ufs: fix register address in UIC error interrupt handling
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
                   ` (6 preceding siblings ...)
  2013-06-26 17:09 ` [PATCH 07/10] ufshcd-pltfrm: add missing empty slot in ufs_of_match[] Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-26 17:09 ` [PATCH 09/10] ufshcd-pltfrm: remove unnecessary dma_set_coherent_mask() call Santosh Y
  2013-06-26 17:09 ` [PATCH 10/10] ufs: fix DMA mask setting Santosh Y
  9 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, vinholikatti, Akinobu Mita, James E.J. Bottomley, Santosh Y

From: Akinobu Mita <mita@fixstars.com>

In UIC error interrupt handling, it checks if UIC data link layer error
code indicates PA_INIT_ERROR in order to determine whether a fatal error
handling is needed or not.

But the code tries to read UIC data link layer error code from wrong
REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER, it should be
REG_UIC_ERROR_CODE_DATA_LINK_LAYER.

Signed-off-by: Akinobu Mita <mita@fixstars.com>
Cc: Vinayak Holikatti <vinholikatti@gmail.com>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: linux-scsi@vger.kernel.org
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 255f5be..19618c6 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1349,7 +1349,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba)
 		goto fatal_eh;
 
 	if (hba->errors & UIC_ERROR) {
-		reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
+		reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER);
 		if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
 			goto fatal_eh;
 	}
-- 
1.8.3.1


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

* [PATCH 09/10] ufshcd-pltfrm: remove unnecessary dma_set_coherent_mask() call
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
                   ` (7 preceding siblings ...)
  2013-06-26 17:09 ` [PATCH 08/10] ufs: fix register address in UIC error interrupt handling Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-26 17:09 ` [PATCH 10/10] ufs: fix DMA mask setting Santosh Y
  9 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, vinholikatti, Akinobu Mita, James E.J. Bottomley, Santosh Y

From: Akinobu Mita <mita@fixstars.com>

Changing the device coherent dma mask to the value that currently set
has no effect.

Signed-off-by: Akinobu Mita <mita@fixstars.com>
Cc: Vinayak Holikatti <vinholikatti@gmail.com>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: linux-scsi@vger.kernel.org
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 6829a16..c42db40 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -122,12 +122,6 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
-	if (err) {
-		dev_err(dev, "set dma mask failed\n");
-		goto out;
-	}
-
 	err = ufshcd_init(dev, &hba, mmio_base, irq);
 	if (err) {
 		dev_err(dev, "Intialization failed\n");
-- 
1.8.3.1


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

* [PATCH 10/10] ufs: fix DMA mask setting
  2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
                   ` (8 preceding siblings ...)
  2013-06-26 17:09 ` [PATCH 09/10] ufshcd-pltfrm: remove unnecessary dma_set_coherent_mask() call Santosh Y
@ 2013-06-26 17:09 ` Santosh Y
  2013-06-28 20:37   ` James Bottomley
  9 siblings, 1 reply; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:09 UTC (permalink / raw)
  To: james.bottomley
  Cc: linux-scsi, vinholikatti, Akinobu Mita, James E.J. Bottomley, Santosh Y

From: Akinobu Mita <mita@fixstars.com>

If the controller doesn't support 64-bit addressing mode, it must not
set the DMA mask to 64-bit.  But it's unconditionally trying to set to
64-bit without checking 64-bit addressing support in the controller
capabilities.

It was correctly checked before commit 3b1d05807a9a68c6d0580e9248247a774a4d3be6
("[SCSI] ufs: Segregate PCI Specific Code"), this aims to restore
the correct behaviour.

To achieve this in a generic way, firstly we should push down the DMA
mask setting routine ufshcd_set_dma_mask() from PCI glue driver to core
driver in order to do it for both PCI glue driver and Platform glue
driver.  Secondly, we should change pci_ DMA mapping API to dma_ DMA
mapping API because core driver is independent of glue drivers.

Lastly, we need to relax dma_set_mask(dev, DMA_BIT_MASK(32)) error check
for platform devices on ARM, which do not have a valid dma_mask pointer.

Signed-off-by: Akinobu Mita <mita@fixstars.com>
Cc: Vinayak Holikatti <vinholikatti@gmail.com>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: linux-scsi@vger.kernel.org
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index 48be39a..64d36eb 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -100,26 +100,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)
 }
 
 /**
- * ufshcd_set_dma_mask - Set dma mask based on the controller
- *			 addressing capability
- * @pdev: PCI device structure
- *
- * Returns 0 for success, non-zero for failure
- */
-static int ufshcd_set_dma_mask(struct pci_dev *pdev)
-{
-	int err;
-
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
-		&& !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
-		return 0;
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (!err)
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-	return err;
-}
-
-/**
  * ufshcd_pci_probe - probe routine of the driver
  * @pdev: pointer to PCI device handle
  * @id: PCI device id
@@ -155,12 +135,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto out_release_regions;
 	}
 
-	err = ufshcd_set_dma_mask(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "set dma mask failed\n");
-		goto out_iounmap;
-	}
-
 	err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq);
 	if (err) {
 		dev_err(&pdev->dev, "Initialization failed\n");
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 19618c6..431ddb2 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1711,6 +1711,25 @@ void ufshcd_remove(struct ufs_hba *hba)
 EXPORT_SYMBOL_GPL(ufshcd_remove);
 
 /**
+ * ufshcd_set_dma_mask - Set dma mask based on the controller
+ *			 addressing capability
+ * @hba: per adapter instance
+ *
+ * Returns 0 for success, non-zero for failure
+ */
+static int ufshcd_set_dma_mask(struct ufs_hba *hba)
+{
+	if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
+		if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64)) &&
+		    !dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(64)))
+			return 0;
+	}
+	dma_set_mask(hba->dev, DMA_BIT_MASK(32));
+
+	return dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
+}
+
+/**
  * ufshcd_init - Driver initialization routine
  * @dev: pointer to device handle
  * @hba_handle: driver private handle
@@ -1761,6 +1780,12 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
 	/* Get Interrupt bit mask per version */
 	hba->intr_mask = ufshcd_get_intr_mask(hba);
 
+	err = ufshcd_set_dma_mask(hba);
+	if (err) {
+		dev_err(hba->dev, "set dma mask failed\n");
+		goto out_disable;
+	}
+
 	/* Allocate memory for host memory space */
 	err = ufshcd_memory_alloc(hba);
 	if (err) {
-- 
1.8.3.1


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

* [PATCH v2 06/10] scsi: ufs: use devres functions for ufshcd
  2013-06-26 17:09 ` [PATCH 06/10] scsi: ufs: use devres functions for ufshcd Santosh Y
@ 2013-06-27  4:31   ` Seungwon Jeon
  2013-07-29 19:17     ` Santosh Y
  0 siblings, 1 reply; 18+ messages in thread
From: Seungwon Jeon @ 2013-06-27  4:31 UTC (permalink / raw)
  To: 'James Bottomley'; +Cc: linux-scsi, 'Santosh Y', vinholikatti

This patch replaces normal calls for resource allocation with devm_*()
derivative functions. It makes resource freeing simpler.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Signed-off-by: Santosh Y <santoshsy@gmail.com>
---
Change in v2:
	[NOTE: There are no conflicts with the following series(07~10)]
	- Remove iounmap which is remained.
	- Apply devres to ufshcd_memory_alloc[dmam_alloc_coherent, devm_kzalloc]
	  Accordingly, 'free' related functions are removed.

 drivers/scsi/ufs/ufshcd-pci.c    |    1 -
 drivers/scsi/ufs/ufshcd-pltfrm.c |   72 +++++++++-----------------------
 drivers/scsi/ufs/ufshcd.c        |   86 ++++++++-----------------------------
 3 files changed, 39 insertions(+), 120 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index 5cb1d75..48be39a 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -92,7 +92,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)
 	struct ufs_hba *hba = pci_get_drvdata(pdev);
 
 	disable_irq(pdev->irq);
-	free_irq(pdev->irq, hba);
 	ufshcd_remove(hba);
 	pci_release_regions(pdev);
 	pci_set_drvdata(pdev, NULL);
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 3db2ee1..0e48827 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -33,9 +33,10 @@
  * this program.
  */
 
-#include "ufshcd.h"
 #include <linux/platform_device.h>
 
+#include "ufshcd.h"
+
 #ifdef CONFIG_PM
 /**
  * ufshcd_pltfrm_suspend - suspend power management function
@@ -97,62 +98,45 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
 	struct ufs_hba *hba;
 	void __iomem *mmio_base;
 	struct resource *mem_res;
-	struct resource *irq_res;
-	resource_size_t mem_size;
-	int err;
+	int irq, err;
 	struct device *dev = &pdev->dev;
 
 	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem_res) {
-		dev_err(&pdev->dev,
-			"Memory resource not available\n");
+		dev_err(dev, "Memory resource not available\n");
 		err = -ENODEV;
-		goto out_error;
+		goto out;
 	}
 
-	mem_size = resource_size(mem_res);
-	if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
-		dev_err(&pdev->dev,
-			"Cannot reserve the memory resource\n");
-		err = -EBUSY;
-		goto out_error;
+	mmio_base = devm_ioremap_resource(dev, mem_res);
+	if (IS_ERR(mmio_base)) {
+		dev_err(dev, "memory map failed\n");
+		err = PTR_ERR(mmio_base);
+		goto out;
 	}
 
-	mmio_base = ioremap_nocache(mem_res->start, mem_size);
-	if (!mmio_base) {
-		dev_err(&pdev->dev, "memory map failed\n");
-		err = -ENOMEM;
-		goto out_release_regions;
-	}
-
-	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!irq_res) {
-		dev_err(&pdev->dev, "IRQ resource not available\n");
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "IRQ resource not available\n");
 		err = -ENODEV;
-		goto out_iounmap;
+		goto out;
 	}
 
 	err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
 	if (err) {
-		dev_err(&pdev->dev, "set dma mask failed\n");
-		goto out_iounmap;
+		dev_err(dev, "set dma mask failed\n");
+		goto out;
 	}
 
-	err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
+	err = ufshcd_init(dev, &hba, mmio_base, irq);
 	if (err) {
-		dev_err(&pdev->dev, "Intialization failed\n");
-		goto out_iounmap;
+		dev_err(dev, "Intialization failed\n");
+		goto out;
 	}
 
 	platform_set_drvdata(pdev, hba);
 
-	return 0;
-
-out_iounmap:
-	iounmap(mmio_base);
-out_release_regions:
-	release_mem_region(mem_res->start, mem_size);
-out_error:
+out:
 	return err;
 }
 
@@ -164,26 +148,10 @@ out_error:
  */
 static int ufshcd_pltfrm_remove(struct platform_device *pdev)
 {
-	struct resource *mem_res;
-	resource_size_t mem_size;
 	struct ufs_hba *hba =  platform_get_drvdata(pdev);
 
 	disable_irq(hba->irq);
-
-	/* Some buggy controllers raise interrupt after
-	 * the resources are removed. So first we unregister the
-	 * irq handler and then the resources used by driver
-	 */
-
-	free_irq(hba->irq, hba);
 	ufshcd_remove(hba);
-	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem_res)
-		dev_err(&pdev->dev, "ufshcd: Memory resource not available\n");
-	else {
-		mem_size = resource_size(mem_res);
-		release_mem_region(mem_res->start, mem_size);
-	}
 	return 0;
 }
 
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2230f14..aba461f 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -191,38 +191,6 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
 }
 
 /**
- * ufshcd_free_hba_memory - Free allocated memory for LRB, request
- *			    and task lists
- * @hba: Pointer to adapter instance
- */
-static inline void ufshcd_free_hba_memory(struct ufs_hba *hba)
-{
-	size_t utmrdl_size, utrdl_size, ucdl_size;
-
-	kfree(hba->lrb);
-
-	if (hba->utmrdl_base_addr) {
-		utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
-		dma_free_coherent(hba->dev, utmrdl_size,
-				  hba->utmrdl_base_addr, hba->utmrdl_dma_addr);
-	}
-
-	if (hba->utrdl_base_addr) {
-		utrdl_size =
-		(sizeof(struct utp_transfer_req_desc) * hba->nutrs);
-		dma_free_coherent(hba->dev, utrdl_size,
-				  hba->utrdl_base_addr, hba->utrdl_dma_addr);
-	}
-
-	if (hba->ucdl_base_addr) {
-		ucdl_size =
-		(sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
-		dma_free_coherent(hba->dev, ucdl_size,
-				  hba->ucdl_base_addr, hba->ucdl_dma_addr);
-	}
-}
-
-/**
  * ufshcd_is_valid_req_rsp - checks if controller TR response is valid
  * @ucd_rsp_ptr: pointer to response UPIU
  *
@@ -690,10 +658,10 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
 
 	/* Allocate memory for UTP command descriptors */
 	ucdl_size = (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
-	hba->ucdl_base_addr = dma_alloc_coherent(hba->dev,
-						 ucdl_size,
-						 &hba->ucdl_dma_addr,
-						 GFP_KERNEL);
+	hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev,
+						  ucdl_size,
+						  &hba->ucdl_dma_addr,
+						  GFP_KERNEL);
 
 	/*
 	 * UFSHCI requires UTP command descriptor to be 128 byte aligned.
@@ -713,10 +681,10 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
 	 * UFSHCI requires 1024 byte alignment of UTRD
 	 */
 	utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
-	hba->utrdl_base_addr = dma_alloc_coherent(hba->dev,
-						  utrdl_size,
-						  &hba->utrdl_dma_addr,
-						  GFP_KERNEL);
+	hba->utrdl_base_addr = dmam_alloc_coherent(hba->dev,
+						   utrdl_size,
+						   &hba->utrdl_dma_addr,
+						   GFP_KERNEL);
 	if (!hba->utrdl_base_addr ||
 	    WARN_ON(hba->utrdl_dma_addr & (PAGE_SIZE - 1))) {
 		dev_err(hba->dev,
@@ -729,10 +697,10 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
 	 * UFSHCI requires 1024 byte alignment of UTMRD
 	 */
 	utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
-	hba->utmrdl_base_addr = dma_alloc_coherent(hba->dev,
-						   utmrdl_size,
-						   &hba->utmrdl_dma_addr,
-						   GFP_KERNEL);
+	hba->utmrdl_base_addr = dmam_alloc_coherent(hba->dev,
+						    utmrdl_size,
+						    &hba->utmrdl_dma_addr,
+						    GFP_KERNEL);
 	if (!hba->utmrdl_base_addr ||
 	    WARN_ON(hba->utmrdl_dma_addr & (PAGE_SIZE - 1))) {
 		dev_err(hba->dev,
@@ -741,14 +709,15 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
 	}
 
 	/* Allocate memory for local reference block */
-	hba->lrb = kcalloc(hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL);
+	hba->lrb = devm_kzalloc(hba->dev,
+				hba->nutrs * sizeof(struct ufshcd_lrb),
+				GFP_KERNEL);
 	if (!hba->lrb) {
 		dev_err(hba->dev, "LRB Memory allocation failed\n");
 		goto out;
 	}
 	return 0;
 out:
-	ufshcd_free_hba_memory(hba);
 	return -ENOMEM;
 }
 
@@ -1682,17 +1651,6 @@ int ufshcd_resume(struct ufs_hba *hba)
 EXPORT_SYMBOL_GPL(ufshcd_resume);
 
 /**
- * ufshcd_hba_free - free allocated memory for
- *			host memory space data structures
- * @hba: per adapter instance
- */
-static void ufshcd_hba_free(struct ufs_hba *hba)
-{
-	iounmap(hba->mmio_base);
-	ufshcd_free_hba_memory(hba);
-}
-
-/**
  * ufshcd_remove - de-allocate SCSI host and host memory space
  *		data structure memory
  * @hba - per adapter instance
@@ -1701,9 +1659,7 @@ void ufshcd_remove(struct ufs_hba *hba)
 {
 	/* disable interrupts */
 	ufshcd_disable_intr(hba, hba->intr_mask);
-
 	ufshcd_hba_stop(hba);
-	ufshcd_hba_free(hba);
 
 	scsi_remove_host(hba->host);
 	scsi_host_put(hba->host);
@@ -1789,23 +1745,23 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
 	mutex_init(&hba->uic_cmd_mutex);
 
 	/* IRQ registration */
-	err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+	err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
 	if (err) {
 		dev_err(hba->dev, "request irq failed\n");
-		goto out_lrb_free;
+		goto out_disable;
 	}
 
 	/* Enable SCSI tag mapping */
 	err = scsi_init_shared_tag_map(host, host->can_queue);
 	if (err) {
 		dev_err(hba->dev, "init shared queue failed\n");
-		goto out_free_irq;
+		goto out_disable;
 	}
 
 	err = scsi_add_host(host, hba->dev);
 	if (err) {
 		dev_err(hba->dev, "scsi_add_host failed\n");
-		goto out_free_irq;
+		goto out_disable;
 	}
 
 	/* Host controller enable */
@@ -1823,10 +1779,6 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
 
 out_remove_scsi_host:
 	scsi_remove_host(hba->host);
-out_free_irq:
-	free_irq(irq, hba);
-out_lrb_free:
-	ufshcd_free_hba_memory(hba);
 out_disable:
 	scsi_host_put(host);
 out_error:
-- 
1.7.0.4



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

* Re: [PATCH 10/10] ufs: fix DMA mask setting
  2013-06-26 17:09 ` [PATCH 10/10] ufs: fix DMA mask setting Santosh Y
@ 2013-06-28 20:37   ` James Bottomley
  2013-06-29  5:40     ` Akinobu Mita
  0 siblings, 1 reply; 18+ messages in thread
From: James Bottomley @ 2013-06-28 20:37 UTC (permalink / raw)
  To: Santosh Y; +Cc: linux-scsi, vinholikatti, Akinobu Mita

On Wed, 2013-06-26 at 22:39 +0530, Santosh Y wrote:
> index 19618c6..431ddb2 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -1711,6 +1711,25 @@ void ufshcd_remove(struct ufs_hba *hba)
>  EXPORT_SYMBOL_GPL(ufshcd_remove);
>  
>  /**
> + * ufshcd_set_dma_mask - Set dma mask based on the controller
> + *			 addressing capability
> + * @hba: per adapter instance
> + *
> + * Returns 0 for success, non-zero for failure
> + */
> +static int ufshcd_set_dma_mask(struct ufs_hba *hba)
> +{
> +	if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
> +		if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64)) &&
> +		    !dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(64)))
> +			return 0;
> +	}
> +	dma_set_mask(hba->dev, DMA_BIT_MASK(32));
> +
> +	return dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
> +}

This isn't right per the API spec.  The guarantee is that if
dma_set_mask() succeeds then dma_set_coherent_mask of the same mask will
succeed,  so this should read

	int err;

	if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
		if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64))) {
			dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(64)))
			return 0;
		}
	}
	err = dma_set_mask(hba->dev, DMA_BIT_MASK(32));
	if (!err)
		dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
	return err;

James



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

* Re: [PATCH 10/10] ufs: fix DMA mask setting
  2013-06-28 20:37   ` James Bottomley
@ 2013-06-29  5:40     ` Akinobu Mita
  2013-08-10  6:08       ` Sujit Reddy Thumma
  0 siblings, 1 reply; 18+ messages in thread
From: Akinobu Mita @ 2013-06-29  5:40 UTC (permalink / raw)
  To: James Bottomley; +Cc: Santosh Y, linux-scsi, vinholikatti

2013/6/29 James Bottomley <James.Bottomley@hansenpartnership.com>:
> On Wed, 2013-06-26 at 22:39 +0530, Santosh Y wrote:
>> index 19618c6..431ddb2 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -1711,6 +1711,25 @@ void ufshcd_remove(struct ufs_hba *hba)
>>  EXPORT_SYMBOL_GPL(ufshcd_remove);
>>
>>  /**
>> + * ufshcd_set_dma_mask - Set dma mask based on the controller
>> + *                    addressing capability
>> + * @hba: per adapter instance
>> + *
>> + * Returns 0 for success, non-zero for failure
>> + */
>> +static int ufshcd_set_dma_mask(struct ufs_hba *hba)
>> +{
>> +     if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
>> +             if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64)) &&
>> +                 !dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(64)))
>> +                     return 0;
>> +     }
>> +     dma_set_mask(hba->dev, DMA_BIT_MASK(32));
>> +
>> +     return dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
>> +}
>
> This isn't right per the API spec.  The guarantee is that if
> dma_set_mask() succeeds then dma_set_coherent_mask of the same mask will
> succeed,  so this should read
>
>         int err;
>
>         if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
>                 if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64))) {
>                         dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(64)))
>                         return 0;
>                 }
>         }
>         err = dma_set_mask(hba->dev, DMA_BIT_MASK(32));
>         if (!err)
>                 dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
>         return err;

Thanks for the explanation.  I agree that this is the correct definision
of ufshcd_set_dma_mask().

The reason that I omitted the error check on dma_set_mask(DMA_BIT_MASK(32))
in the patch was that I was seeing that error due to the luck of
valid dev->dma_mask pointer on OF platform devices although
dma_supported(DMA_BIT_MASK(32)) returns true.

However, now I think that I should investigate more about dev->dma_mask
issue rather than jumping into short-circuit fixing in the driver.  And
then I will revisit this.

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

* Re: [PATCH v2 06/10] scsi: ufs: use devres functions for ufshcd
  2013-06-27  4:31   ` [PATCH v2 " Seungwon Jeon
@ 2013-07-29 19:17     ` Santosh Y
  0 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-07-29 19:17 UTC (permalink / raw)
  To: Seungwon Jeon; +Cc: James Bottomley, linux-scsi, vinholikatti

On Thu, Jun 27, 2013 at 10:01 AM, Seungwon Jeon <tgih.jun@samsung.com> wrote:
> This patch replaces normal calls for resource allocation with devm_*()
> derivative functions. It makes resource freeing simpler.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> Signed-off-by: Santosh Y <santoshsy@gmail.com>
> ---
> Change in v2:
>         [NOTE: There are no conflicts with the following series(07~10)]
>         - Remove iounmap which is remained.
>         - Apply devres to ufshcd_memory_alloc[dmam_alloc_coherent, devm_kzalloc]
>           Accordingly, 'free' related functions are removed.
>
>  drivers/scsi/ufs/ufshcd-pci.c    |    1 -
>  drivers/scsi/ufs/ufshcd-pltfrm.c |   72 +++++++++-----------------------
>  drivers/scsi/ufs/ufshcd.c        |   86 ++++++++-----------------------------
>  3 files changed, 39 insertions(+), 120 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
> index 5cb1d75..48be39a 100644
> --- a/drivers/scsi/ufs/ufshcd-pci.c
> +++ b/drivers/scsi/ufs/ufshcd-pci.c
> @@ -92,7 +92,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)
>         struct ufs_hba *hba = pci_get_drvdata(pdev);
>
>         disable_irq(pdev->irq);
> -       free_irq(pdev->irq, hba);
>         ufshcd_remove(hba);
>         pci_release_regions(pdev);
>         pci_set_drvdata(pdev, NULL);
> diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
> index 3db2ee1..0e48827 100644
> --- a/drivers/scsi/ufs/ufshcd-pltfrm.c
> +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
> @@ -33,9 +33,10 @@
>   * this program.
>   */
>
> -#include "ufshcd.h"
>  #include <linux/platform_device.h>
>
> +#include "ufshcd.h"
> +
>  #ifdef CONFIG_PM
>  /**
>   * ufshcd_pltfrm_suspend - suspend power management function
> @@ -97,62 +98,45 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
>         struct ufs_hba *hba;
>         void __iomem *mmio_base;
>         struct resource *mem_res;
> -       struct resource *irq_res;
> -       resource_size_t mem_size;
> -       int err;
> +       int irq, err;
>         struct device *dev = &pdev->dev;
>
>         mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>         if (!mem_res) {
> -               dev_err(&pdev->dev,
> -                       "Memory resource not available\n");
> +               dev_err(dev, "Memory resource not available\n");
>                 err = -ENODEV;
> -               goto out_error;
> +               goto out;
>         }
>
> -       mem_size = resource_size(mem_res);
> -       if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
> -               dev_err(&pdev->dev,
> -                       "Cannot reserve the memory resource\n");
> -               err = -EBUSY;
> -               goto out_error;
> +       mmio_base = devm_ioremap_resource(dev, mem_res);
> +       if (IS_ERR(mmio_base)) {
> +               dev_err(dev, "memory map failed\n");
> +               err = PTR_ERR(mmio_base);
> +               goto out;
>         }
>
> -       mmio_base = ioremap_nocache(mem_res->start, mem_size);
> -       if (!mmio_base) {
> -               dev_err(&pdev->dev, "memory map failed\n");
> -               err = -ENOMEM;
> -               goto out_release_regions;
> -       }
> -
> -       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> -       if (!irq_res) {
> -               dev_err(&pdev->dev, "IRQ resource not available\n");
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq < 0) {
> +               dev_err(dev, "IRQ resource not available\n");
>                 err = -ENODEV;
> -               goto out_iounmap;
> +               goto out;
>         }
>
>         err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
>         if (err) {
> -               dev_err(&pdev->dev, "set dma mask failed\n");
> -               goto out_iounmap;
> +               dev_err(dev, "set dma mask failed\n");
> +               goto out;
>         }
>
> -       err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
> +       err = ufshcd_init(dev, &hba, mmio_base, irq);
>         if (err) {
> -               dev_err(&pdev->dev, "Intialization failed\n");
> -               goto out_iounmap;
> +               dev_err(dev, "Intialization failed\n");
> +               goto out;
>         }
>
>         platform_set_drvdata(pdev, hba);
>
> -       return 0;
> -
> -out_iounmap:
> -       iounmap(mmio_base);
> -out_release_regions:
> -       release_mem_region(mem_res->start, mem_size);
> -out_error:
> +out:
>         return err;
>  }
>
> @@ -164,26 +148,10 @@ out_error:
>   */
>  static int ufshcd_pltfrm_remove(struct platform_device *pdev)
>  {
> -       struct resource *mem_res;
> -       resource_size_t mem_size;
>         struct ufs_hba *hba =  platform_get_drvdata(pdev);
>
>         disable_irq(hba->irq);
> -
> -       /* Some buggy controllers raise interrupt after
> -        * the resources are removed. So first we unregister the
> -        * irq handler and then the resources used by driver
> -        */
> -
> -       free_irq(hba->irq, hba);
>         ufshcd_remove(hba);
> -       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -       if (!mem_res)
> -               dev_err(&pdev->dev, "ufshcd: Memory resource not available\n");
> -       else {
> -               mem_size = resource_size(mem_res);
> -               release_mem_region(mem_res->start, mem_size);
> -       }
>         return 0;
>  }
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 2230f14..aba461f 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -191,38 +191,6 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
>  }
>
>  /**
> - * ufshcd_free_hba_memory - Free allocated memory for LRB, request
> - *                         and task lists
> - * @hba: Pointer to adapter instance
> - */
> -static inline void ufshcd_free_hba_memory(struct ufs_hba *hba)
> -{
> -       size_t utmrdl_size, utrdl_size, ucdl_size;
> -
> -       kfree(hba->lrb);
> -
> -       if (hba->utmrdl_base_addr) {
> -               utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
> -               dma_free_coherent(hba->dev, utmrdl_size,
> -                                 hba->utmrdl_base_addr, hba->utmrdl_dma_addr);
> -       }
> -
> -       if (hba->utrdl_base_addr) {
> -               utrdl_size =
> -               (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
> -               dma_free_coherent(hba->dev, utrdl_size,
> -                                 hba->utrdl_base_addr, hba->utrdl_dma_addr);
> -       }
> -
> -       if (hba->ucdl_base_addr) {
> -               ucdl_size =
> -               (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
> -               dma_free_coherent(hba->dev, ucdl_size,
> -                                 hba->ucdl_base_addr, hba->ucdl_dma_addr);
> -       }
> -}
> -
> -/**
>   * ufshcd_is_valid_req_rsp - checks if controller TR response is valid
>   * @ucd_rsp_ptr: pointer to response UPIU
>   *
> @@ -690,10 +658,10 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>
>         /* Allocate memory for UTP command descriptors */
>         ucdl_size = (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
> -       hba->ucdl_base_addr = dma_alloc_coherent(hba->dev,
> -                                                ucdl_size,
> -                                                &hba->ucdl_dma_addr,
> -                                                GFP_KERNEL);
> +       hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev,
> +                                                 ucdl_size,
> +                                                 &hba->ucdl_dma_addr,
> +                                                 GFP_KERNEL);
>
>         /*
>          * UFSHCI requires UTP command descriptor to be 128 byte aligned.
> @@ -713,10 +681,10 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>          * UFSHCI requires 1024 byte alignment of UTRD
>          */
>         utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
> -       hba->utrdl_base_addr = dma_alloc_coherent(hba->dev,
> -                                                 utrdl_size,
> -                                                 &hba->utrdl_dma_addr,
> -                                                 GFP_KERNEL);
> +       hba->utrdl_base_addr = dmam_alloc_coherent(hba->dev,
> +                                                  utrdl_size,
> +                                                  &hba->utrdl_dma_addr,
> +                                                  GFP_KERNEL);
>         if (!hba->utrdl_base_addr ||
>             WARN_ON(hba->utrdl_dma_addr & (PAGE_SIZE - 1))) {
>                 dev_err(hba->dev,
> @@ -729,10 +697,10 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>          * UFSHCI requires 1024 byte alignment of UTMRD
>          */
>         utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
> -       hba->utmrdl_base_addr = dma_alloc_coherent(hba->dev,
> -                                                  utmrdl_size,
> -                                                  &hba->utmrdl_dma_addr,
> -                                                  GFP_KERNEL);
> +       hba->utmrdl_base_addr = dmam_alloc_coherent(hba->dev,
> +                                                   utmrdl_size,
> +                                                   &hba->utmrdl_dma_addr,
> +                                                   GFP_KERNEL);
>         if (!hba->utmrdl_base_addr ||
>             WARN_ON(hba->utmrdl_dma_addr & (PAGE_SIZE - 1))) {
>                 dev_err(hba->dev,
> @@ -741,14 +709,15 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>         }
>
>         /* Allocate memory for local reference block */
> -       hba->lrb = kcalloc(hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL);
> +       hba->lrb = devm_kzalloc(hba->dev,
> +                               hba->nutrs * sizeof(struct ufshcd_lrb),
> +                               GFP_KERNEL);
>         if (!hba->lrb) {
>                 dev_err(hba->dev, "LRB Memory allocation failed\n");
>                 goto out;
>         }
>         return 0;
>  out:
> -       ufshcd_free_hba_memory(hba);
>         return -ENOMEM;
>  }
>
> @@ -1682,17 +1651,6 @@ int ufshcd_resume(struct ufs_hba *hba)
>  EXPORT_SYMBOL_GPL(ufshcd_resume);
>
>  /**
> - * ufshcd_hba_free - free allocated memory for
> - *                     host memory space data structures
> - * @hba: per adapter instance
> - */
> -static void ufshcd_hba_free(struct ufs_hba *hba)
> -{
> -       iounmap(hba->mmio_base);
> -       ufshcd_free_hba_memory(hba);
> -}
> -
> -/**
>   * ufshcd_remove - de-allocate SCSI host and host memory space
>   *             data structure memory
>   * @hba - per adapter instance
> @@ -1701,9 +1659,7 @@ void ufshcd_remove(struct ufs_hba *hba)
>  {
>         /* disable interrupts */
>         ufshcd_disable_intr(hba, hba->intr_mask);
> -
>         ufshcd_hba_stop(hba);
> -       ufshcd_hba_free(hba);
>
>         scsi_remove_host(hba->host);
>         scsi_host_put(hba->host);
> @@ -1789,23 +1745,23 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
>         mutex_init(&hba->uic_cmd_mutex);
>
>         /* IRQ registration */
> -       err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
> +       err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
>         if (err) {
>                 dev_err(hba->dev, "request irq failed\n");
> -               goto out_lrb_free;
> +               goto out_disable;
>         }
>
>         /* Enable SCSI tag mapping */
>         err = scsi_init_shared_tag_map(host, host->can_queue);
>         if (err) {
>                 dev_err(hba->dev, "init shared queue failed\n");
> -               goto out_free_irq;
> +               goto out_disable;
>         }
>
>         err = scsi_add_host(host, hba->dev);
>         if (err) {
>                 dev_err(hba->dev, "scsi_add_host failed\n");
> -               goto out_free_irq;
> +               goto out_disable;
>         }
>
>         /* Host controller enable */
> @@ -1823,10 +1779,6 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
>
>  out_remove_scsi_host:
>         scsi_remove_host(hba->host);
> -out_free_irq:
> -       free_irq(irq, hba);
> -out_lrb_free:
> -       ufshcd_free_hba_memory(hba);
>  out_disable:
>         scsi_host_put(host);
>  out_error:
> --
> 1.7.0.4
>
>

Please resend the patch and re-base it on scsi 'misc' branch.

-- 
~Santosh

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

* Re: [PATCH 10/10] ufs: fix DMA mask setting
  2013-06-29  5:40     ` Akinobu Mita
@ 2013-08-10  6:08       ` Sujit Reddy Thumma
  2013-08-15 14:48         ` Akinobu Mita
  0 siblings, 1 reply; 18+ messages in thread
From: Sujit Reddy Thumma @ 2013-08-10  6:08 UTC (permalink / raw)
  To: Akinobu Mita; +Cc: James Bottomley, Santosh Y, linux-scsi, vinholikatti

On 6/29/2013 11:10 AM, Akinobu Mita wrote:
> 2013/6/29 James Bottomley <James.Bottomley@hansenpartnership.com>:
>> On Wed, 2013-06-26 at 22:39 +0530, Santosh Y wrote:
>>> index 19618c6..431ddb2 100644
>>> --- a/drivers/scsi/ufs/ufshcd.c
>>> +++ b/drivers/scsi/ufs/ufshcd.c
>>> @@ -1711,6 +1711,25 @@ void ufshcd_remove(struct ufs_hba *hba)
>>>   EXPORT_SYMBOL_GPL(ufshcd_remove);
>>>
>>>   /**
>>> + * ufshcd_set_dma_mask - Set dma mask based on the controller
>>> + *                    addressing capability
>>> + * @hba: per adapter instance
>>> + *
>>> + * Returns 0 for success, non-zero for failure
>>> + */
>>> +static int ufshcd_set_dma_mask(struct ufs_hba *hba)
>>> +{
>>> +     if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
>>> +             if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64)) &&
>>> +                 !dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(64)))
>>> +                     return 0;
>>> +     }
>>> +     dma_set_mask(hba->dev, DMA_BIT_MASK(32));
>>> +
>>> +     return dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
>>> +}
>>
>> This isn't right per the API spec.  The guarantee is that if
>> dma_set_mask() succeeds then dma_set_coherent_mask of the same mask will
>> succeed,  so this should read
>>
>>          int err;
>>
>>          if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
>>                  if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64))) {
>>                          dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(64)))
>>                          return 0;
>>                  }
>>          }
>>          err = dma_set_mask(hba->dev, DMA_BIT_MASK(32));
>>          if (!err)
>>                  dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
>>          return err;
>
> Thanks for the explanation.  I agree that this is the correct definision
> of ufshcd_set_dma_mask().
>
> The reason that I omitted the error check on dma_set_mask(DMA_BIT_MASK(32))
> in the patch was that I was seeing that error due to the luck of
> valid dev->dma_mask pointer on OF platform devices although
> dma_supported(DMA_BIT_MASK(32)) returns true.

The popular trick implemented for device-tree probed devices is -
dev->dma_mask = &dev->coherent_dma_mask;

If you don't agree with this you can have something like -
dev->dma_mask = devm_kzalloc(dev, sizeof(*dev->dma_mask), GFP_KERNEL);
See platform_device_register_full();

>
> However, now I think that I should investigate more about dev->dma_mask
> issue rather than jumping into short-circuit fixing in the driver.  And
> then I will revisit this.


-- 
Regards,
Sujit

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

* Re: [PATCH 10/10] ufs: fix DMA mask setting
  2013-08-10  6:08       ` Sujit Reddy Thumma
@ 2013-08-15 14:48         ` Akinobu Mita
  0 siblings, 0 replies; 18+ messages in thread
From: Akinobu Mita @ 2013-08-15 14:48 UTC (permalink / raw)
  To: Sujit Reddy Thumma
  Cc: Akinobu Mita, James Bottomley, Santosh Y, linux-scsi, vinholikatti

> On 6/29/2013 11:10 AM, Akinobu Mita wrote:
>> 2013/6/29 James Bottomley <James.Bottomley@hansenpartnership.com>:
>>> On Wed, 2013-06-26 at 22:39 +0530, Santosh Y wrote:
>>>> index 19618c6..431ddb2 100644
>>>> --- a/drivers/scsi/ufs/ufshcd.c
>>>> +++ b/drivers/scsi/ufs/ufshcd.c
>>>> @@ -1711,6 +1711,25 @@ void ufshcd_remove(struct ufs_hba *hba)
>>>>   EXPORT_SYMBOL_GPL(ufshcd_remove);
>>>>
>>>>   /**
>>>> + * ufshcd_set_dma_mask - Set dma mask based on the controller
>>>> + *                    addressing capability
>>>> + * @hba: per adapter instance
>>>> + *
>>>> + * Returns 0 for success, non-zero for failure
>>>> + */
>>>> +static int ufshcd_set_dma_mask(struct ufs_hba *hba)
>>>> +{
>>>> +     if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
>>>> +             if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64)) &&
>>>> +                 !dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(64)))
>>>> +                     return 0;
>>>> +     }
>>>> +     dma_set_mask(hba->dev, DMA_BIT_MASK(32));
>>>> +
>>>> +     return dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
>>>> +}
>>>
>>> This isn't right per the API spec.  The guarantee is that if
>>> dma_set_mask() succeeds then dma_set_coherent_mask of the same mask
>>> will
>>> succeed,  so this should read
>>>
>>>          int err;
>>>
>>>          if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
>>>                  if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64))) {
>>>                          dma_set_coherent_mask(hba->dev,
>>> DMA_BIT_MASK(64)))
>>>                          return 0;
>>>                  }
>>>          }
>>>          err = dma_set_mask(hba->dev, DMA_BIT_MASK(32));
>>>          if (!err)
>>>                  dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
>>>          return err;
>>
>> Thanks for the explanation.  I agree that this is the correct definision
>> of ufshcd_set_dma_mask().
>>
>> The reason that I omitted the error check on
>> dma_set_mask(DMA_BIT_MASK(32))
>> in the patch was that I was seeing that error due to the luck of
>> valid dev->dma_mask pointer on OF platform devices although
>> dma_supported(DMA_BIT_MASK(32)) returns true.
>
> The popular trick implemented for device-tree probed devices is -
> dev->dma_mask = &dev->coherent_dma_mask;

This looks the right solution for now.  I'll send revised patches that
include this trick in ufshcd-pltfrm and fixed ufshcd_set_dma_mask() as
James suggested above.


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

* [PATCH 10/10] ufs: fix DMA mask setting
  2013-06-26 17:03 [PATCH 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
@ 2013-06-26 17:04 ` Santosh Y
  0 siblings, 0 replies; 18+ messages in thread
From: Santosh Y @ 2013-06-26 17:04 UTC (permalink / raw)
  To: 00james.bottomley
  Cc: linux-scsi, vinholikatti, Akinobu Mita, James E.J. Bottomley, Santosh Y

From: Akinobu Mita <mita@fixstars.com>

If the controller doesn't support 64-bit addressing mode, it must not
set the DMA mask to 64-bit.  But it's unconditionally trying to set to
64-bit without checking 64-bit addressing support in the controller
capabilities.

It was correctly checked before commit 3b1d05807a9a68c6d0580e9248247a774a4d3be6
("[SCSI] ufs: Segregate PCI Specific Code"), this aims to restore
the correct behaviour.

To achieve this in a generic way, firstly we should push down the DMA
mask setting routine ufshcd_set_dma_mask() from PCI glue driver to core
driver in order to do it for both PCI glue driver and Platform glue
driver.  Secondly, we should change pci_ DMA mapping API to dma_ DMA
mapping API because core driver is independent of glue drivers.

Lastly, we need to relax dma_set_mask(dev, DMA_BIT_MASK(32)) error check
for platform devices on ARM, which do not have a valid dma_mask pointer.

Signed-off-by: Akinobu Mita <mita@fixstars.com>
Cc: Vinayak Holikatti <vinholikatti@gmail.com>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: linux-scsi@vger.kernel.org
Signed-off-by: Santosh Y <santoshsy@gmail.com>

diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index 48be39a..64d36eb 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -100,26 +100,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)
 }
 
 /**
- * ufshcd_set_dma_mask - Set dma mask based on the controller
- *			 addressing capability
- * @pdev: PCI device structure
- *
- * Returns 0 for success, non-zero for failure
- */
-static int ufshcd_set_dma_mask(struct pci_dev *pdev)
-{
-	int err;
-
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
-		&& !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
-		return 0;
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (!err)
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-	return err;
-}
-
-/**
  * ufshcd_pci_probe - probe routine of the driver
  * @pdev: pointer to PCI device handle
  * @id: PCI device id
@@ -155,12 +135,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto out_release_regions;
 	}
 
-	err = ufshcd_set_dma_mask(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "set dma mask failed\n");
-		goto out_iounmap;
-	}
-
 	err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq);
 	if (err) {
 		dev_err(&pdev->dev, "Initialization failed\n");
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 19618c6..431ddb2 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1711,6 +1711,25 @@ void ufshcd_remove(struct ufs_hba *hba)
 EXPORT_SYMBOL_GPL(ufshcd_remove);
 
 /**
+ * ufshcd_set_dma_mask - Set dma mask based on the controller
+ *			 addressing capability
+ * @hba: per adapter instance
+ *
+ * Returns 0 for success, non-zero for failure
+ */
+static int ufshcd_set_dma_mask(struct ufs_hba *hba)
+{
+	if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
+		if (!dma_set_mask(hba->dev, DMA_BIT_MASK(64)) &&
+		    !dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(64)))
+			return 0;
+	}
+	dma_set_mask(hba->dev, DMA_BIT_MASK(32));
+
+	return dma_set_coherent_mask(hba->dev, DMA_BIT_MASK(32));
+}
+
+/**
  * ufshcd_init - Driver initialization routine
  * @dev: pointer to device handle
  * @hba_handle: driver private handle
@@ -1761,6 +1780,12 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
 	/* Get Interrupt bit mask per version */
 	hba->intr_mask = ufshcd_get_intr_mask(hba);
 
+	err = ufshcd_set_dma_mask(hba);
+	if (err) {
+		dev_err(hba->dev, "set dma mask failed\n");
+		goto out_disable;
+	}
+
 	/* Allocate memory for host memory space */
 	err = ufshcd_memory_alloc(hba);
 	if (err) {
-- 
1.8.3.1


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

end of thread, other threads:[~2013-08-15 14:52 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-26 17:09 [PATCH RESEND 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
2013-06-26 17:09 ` [PATCH 01/10] scsi: ufs: wrap the i/o access operations Santosh Y
2013-06-26 17:09 ` [PATCH 02/10] scsi: ufs: amend interrupt configuration Santosh Y
2013-06-26 17:09 ` [PATCH 03/10] scsi: ufs: remove version check before IS reg clear Santosh Y
2013-06-26 17:09 ` [PATCH 04/10] scsi: ufs: rework link start-up process Santosh Y
2013-06-26 17:09 ` [PATCH 05/10] scsi: ufs: Fix the response UPIU length setting Santosh Y
2013-06-26 17:09 ` [PATCH 06/10] scsi: ufs: use devres functions for ufshcd Santosh Y
2013-06-27  4:31   ` [PATCH v2 " Seungwon Jeon
2013-07-29 19:17     ` Santosh Y
2013-06-26 17:09 ` [PATCH 07/10] ufshcd-pltfrm: add missing empty slot in ufs_of_match[] Santosh Y
2013-06-26 17:09 ` [PATCH 08/10] ufs: fix register address in UIC error interrupt handling Santosh Y
2013-06-26 17:09 ` [PATCH 09/10] ufshcd-pltfrm: remove unnecessary dma_set_coherent_mask() call Santosh Y
2013-06-26 17:09 ` [PATCH 10/10] ufs: fix DMA mask setting Santosh Y
2013-06-28 20:37   ` James Bottomley
2013-06-29  5:40     ` Akinobu Mita
2013-08-10  6:08       ` Sujit Reddy Thumma
2013-08-15 14:48         ` Akinobu Mita
  -- strict thread matches above, loose matches on Subject: below --
2013-06-26 17:03 [PATCH 00/10] scsi: ufs: link start-up rework and other fixes Santosh Y
2013-06-26 17:04 ` [PATCH 10/10] ufs: fix DMA mask setting Santosh Y

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.