linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V5 1/4] [SCSI] drivers/scsi/ufs: Seggregate PCI Specific Code
       [not found] <1356552955-18027-1-git-send-email-y>
@ 2012-12-26 20:15 ` vinholikatti
  2012-12-27 14:29   ` Subhash Jadavani
  2012-12-26 20:15 ` [PATCH V5 2/4] [SCSI] drivers/scsi/ufs: Separate PCI code into glue driver vinholikatti
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 16+ messages in thread
From: vinholikatti @ 2012-12-26 20:15 UTC (permalink / raw)
  To: james.bottomley; +Cc: linux-scsi, santoshsy, Vinayak Holikatti

From: Vinayak Holikatti <vinholikatti@gmail.com>

This patch seggregates the PCI specific code in ufshcd.c to make it
ready for splitting into core ufs driver and PCI glue driver. Also
copyright header modification to remove extra warranty disclaim.

Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
---
 drivers/scsi/ufs/Kconfig  |   50 +++----
 drivers/scsi/ufs/ufs.h    |   42 ++----
 drivers/scsi/ufs/ufshcd.c |  339 +++++++++++++++++++++++++++------------------
 drivers/scsi/ufs/ufshci.h |   42 ++----
 4 files changed, 255 insertions(+), 218 deletions(-)

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 8f27f9d..9c84569 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -2,45 +2,35 @@
 # Kernel configuration file for the UFS Host Controller
 #
 # This code is based on drivers/scsi/ufs/Kconfig
-# Copyright (C) 2011  Samsung Samsung India Software Operations
+# Copyright (C) 2011-2012 Samsung India Software Operations
+#
+# Authors:
+#	Santosh Yaraganavi <santosh.sy@samsung.com>
+#	Vinayak Holikatti <h.vinayak@samsung.com>
 #
-# Santosh Yaraganavi <santosh.sy@samsung.com>
-# Vinayak Holikatti <h.vinayak@samsung.com>
-
 # 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.
-
+# See the COPYING file in the top-level directory or visit
+# <http://www.gnu.org/licenses/gpl-2.0.html>
+#
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-
-# NO WARRANTY
-# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
-# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
-# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
-# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
-# solely responsible for determining the appropriateness of using and
-# distributing the Program and assumes all risks associated with its
-# exercise of rights under this Agreement, including but not limited to
-# the risks and costs of program errors, damage to or loss of data,
-# programs or equipment, and unavailability or interruption of operations.
-
-# DISCLAIMER OF LIABILITY
-# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
-# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
-# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
-# USA.
+#
+# This program is provided "AS IS" and "WITH ALL FAULTS" and
+# without warranty of any kind. You are solely responsible for
+# determining the appropriateness of using and distributing
+# the program and assume all risks associated with your exercise
+# of rights with respect to the program, including but not limited
+# to infringement of third party rights, the risks and costs of
+# program errors, damage to or loss of data, programs or equipment,
+# and unavailability or interruption of operations. Under no
+# circumstances will the contributor of this Program be liable for
+# any damages of any kind arising from your use or distribution of
+# this program.
 
 config SCSI_UFSHCD
 	tristate "Universal Flash Storage host controller driver"
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index b207529..4b3d611 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -4,43 +4,33 @@
  * This code is based on drivers/scsi/ufs/ufs.h
  * Copyright (C) 2011-2012 Samsung India Software Operations
  *
- * Santosh Yaraganavi <santosh.sy@samsung.com>
- * Vinayak Holikatti <h.vinayak@samsung.com>
+ * Authors:
+ *	Santosh Yaraganavi <santosh.sy@samsung.com>
+ *	Vinayak Holikatti <h.vinayak@samsung.com>
  *
  * 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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
  */
 
 #ifndef _UFS_H
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 58f4ba6..86b5b49 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4,43 +4,33 @@
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2012 Samsung India Software Operations
  *
- * Santosh Yaraganavi <santosh.sy@samsung.com>
- * Vinayak Holikatti <h.vinayak@samsung.com>
+ * Authors:
+ *	Santosh Yaraganavi <santosh.sy@samsung.com>
+ *	Vinayak Holikatti <h.vinayak@samsung.com>
  *
  * 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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
  */
 
 #include <linux/module.h>
@@ -129,7 +119,7 @@ struct uic_command {
  * @utrdl_dma_addr: UTRDL DMA address
  * @utmrdl_dma_addr: UTMRDL DMA address
  * @host: Scsi_Host instance of the driver
- * @pdev: PCI device handle
+ * @dev: device handle
  * @lrb: local reference block
  * @outstanding_tasks: Bits representing outstanding task requests
  * @outstanding_reqs: Bits representing outstanding transfer requests
@@ -159,7 +149,7 @@ struct ufs_hba {
 	dma_addr_t utmrdl_dma_addr;
 
 	struct Scsi_Host *host;
-	struct pci_dev *pdev;
+	struct device *dev;
 
 	struct ufshcd_lrb *lrb;
 
@@ -335,21 +325,21 @@ static inline void ufshcd_free_hba_memory(struct ufs_hba *hba)
 
 	if (hba->utmrdl_base_addr) {
 		utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
-		dma_free_coherent(&hba->pdev->dev, utmrdl_size,
+		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->pdev->dev, utrdl_size,
+		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->pdev->dev, ucdl_size,
+		dma_free_coherent(hba->dev, ucdl_size,
 				  hba->ucdl_base_addr, hba->ucdl_dma_addr);
 	}
 }
@@ -724,7 +714,7 @@ 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->pdev->dev,
+	hba->ucdl_base_addr = dma_alloc_coherent(hba->dev,
 						 ucdl_size,
 						 &hba->ucdl_dma_addr,
 						 GFP_KERNEL);
@@ -737,7 +727,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
 	 */
 	if (!hba->ucdl_base_addr ||
 	    WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Command Descriptor Memory allocation failed\n");
 		goto out;
 	}
@@ -747,13 +737,13 @@ 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->pdev->dev,
+	hba->utrdl_base_addr = dma_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->pdev->dev,
+		dev_err(hba->dev,
 			"Transfer Descriptor Memory allocation failed\n");
 		goto out;
 	}
@@ -763,13 +753,13 @@ 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->pdev->dev,
+	hba->utmrdl_base_addr = dma_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->pdev->dev,
+		dev_err(hba->dev,
 		"Task Management Descriptor Memory allocation failed\n");
 		goto out;
 	}
@@ -777,7 +767,7 @@ 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);
 	if (!hba->lrb) {
-		dev_err(&hba->pdev->dev, "LRB Memory allocation failed\n");
+		dev_err(hba->dev, "LRB Memory allocation failed\n");
 		goto out;
 	}
 	return 0;
@@ -867,7 +857,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
 	/* check if controller is ready to accept UIC commands */
 	if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
 	    UIC_COMMAND_READY) == 0x0) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Controller not ready"
 			" to accept UIC commands\n");
 		return -EIO;
@@ -912,7 +902,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
 	/* check if device present */
 	reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
 	if (!ufshcd_is_device_present(reg)) {
-		dev_err(&hba->pdev->dev, "cc: Device not present\n");
+		dev_err(hba->dev, "cc: Device not present\n");
 		err = -ENXIO;
 		goto out;
 	}
@@ -924,7 +914,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
 	if (!(ufshcd_get_lists_status(reg))) {
 		ufshcd_enable_run_stop_reg(hba);
 	} else {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Host controller not ready to process requests");
 		err = -EIO;
 		goto out;
@@ -1005,7 +995,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
 		if (retry) {
 			retry--;
 		} else {
-			dev_err(&hba->pdev->dev,
+			dev_err(hba->dev,
 				"Controller enable failed\n");
 			return -EIO;
 		}
@@ -1084,7 +1074,7 @@ static int ufshcd_do_reset(struct ufs_hba *hba)
 
 	/* start the initialization process */
 	if (ufshcd_initialize_hba(hba)) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Reset: Controller initialization failed\n");
 		return FAILED;
 	}
@@ -1167,7 +1157,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index)
 			task_result = SUCCESS;
 	} else {
 		task_result = FAILED;
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"trc: Invalid ocs = %x\n", ocs_value);
 	}
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -1281,7 +1271,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
 		/* check if the returned transfer response is valid */
 		result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
 		if (result) {
-			dev_err(&hba->pdev->dev,
+			dev_err(hba->dev,
 				"Invalid response = %x\n", result);
 			break;
 		}
@@ -1310,7 +1300,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
 	case OCS_FATAL_ERROR:
 	default:
 		result |= DID_ERROR << 16;
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 		"OCS error from controller = %x\n", ocs);
 		break;
 	} /* end of switch */
@@ -1374,7 +1364,7 @@ static void ufshcd_uic_cc_handler (struct work_struct *work)
 	    !(ufshcd_get_uic_cmd_result(hba))) {
 
 		if (ufshcd_make_hba_operational(hba))
-			dev_err(&hba->pdev->dev,
+			dev_err(hba->dev,
 				"cc: hba not operational state\n");
 		return;
 	}
@@ -1509,7 +1499,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 	free_slot = ufshcd_get_tm_free_slot(hba);
 	if (free_slot >= hba->nutmrs) {
 		spin_unlock_irqrestore(host->host_lock, flags);
-		dev_err(&hba->pdev->dev, "Task management queue full\n");
+		dev_err(hba->dev, "Task management queue full\n");
 		err = FAILED;
 		goto out;
 	}
@@ -1552,7 +1542,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 					 &hba->tm_condition) != 0),
 					 60 * HZ);
 	if (!err) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Task management command timed-out\n");
 		err = FAILED;
 		goto out;
@@ -1688,23 +1678,22 @@ static struct scsi_host_template ufshcd_driver_template = {
 };
 
 /**
- * ufshcd_shutdown - main function to put the controller in reset state
+ * ufshcd_pci_shutdown - main function to put the controller in reset state
  * @pdev: pointer to PCI device handle
  */
-static void ufshcd_shutdown(struct pci_dev *pdev)
+static void ufshcd_pci_shutdown(struct pci_dev *pdev)
 {
 	ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
 }
 
-#ifdef CONFIG_PM
 /**
  * ufshcd_suspend - suspend power management function
- * @pdev: pointer to PCI device handle
+ * @hba: per adapter instance
  * @state: power state
  *
  * Returns -ENOSYS
  */
-static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
+int ufshcd_suspend(struct ufs_hba *hba, pm_message_t state)
 {
 	/*
 	 * TODO:
@@ -1717,14 +1706,15 @@ static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
 
 	return -ENOSYS;
 }
+EXPORT_SYMBOL_GPL(ufshcd_suspend);
 
 /**
  * ufshcd_resume - resume power management function
- * @pdev: pointer to PCI device handle
+ * @hba: per adapter instance
  *
  * Returns -ENOSYS
  */
-static int ufshcd_resume(struct pci_dev *pdev)
+int ufshcd_resume(struct ufs_hba *hba)
 {
 	/*
 	 * TODO:
@@ -1737,6 +1727,43 @@ static int ufshcd_resume(struct pci_dev *pdev)
 
 	return -ENOSYS;
 }
+EXPORT_SYMBOL_GPL(ufshcd_resume);
+
+#ifdef CONFIG_PM
+/**
+ * ufshcd_pci_suspend - suspend power management function
+ * @pdev: pointer to PCI device handle
+ * @state: power state
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_suspend
+	 * 2. Do bus specific power management
+	 */
+
+	return -ENOSYS;
+}
+
+/**
+ * ufshcd_pci_resume - resume power management function
+ * @pdev: pointer to PCI device handle
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pci_resume(struct pci_dev *pdev)
+{
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_resume.
+	 * 2. Do bus specific wake up
+	 */
+
+	return -ENOSYS;
+}
 #endif /* CONFIG_PM */
 
 /**
@@ -1748,27 +1775,38 @@ static void ufshcd_hba_free(struct ufs_hba *hba)
 {
 	iounmap(hba->mmio_base);
 	ufshcd_free_hba_memory(hba);
-	pci_release_regions(hba->pdev);
 }
 
 /**
- * ufshcd_remove - de-allocate PCI/SCSI host and host memory space
+ * ufshcd_remove - de-allocate SCSI host and host memory space
  *		data structure memory
- * @pdev - pointer to PCI handle
+ * @hba - per adapter instance
  */
-static void ufshcd_remove(struct pci_dev *pdev)
+void ufshcd_remove(struct ufs_hba *hba)
 {
-	struct ufs_hba *hba = pci_get_drvdata(pdev);
-
 	/* disable interrupts */
 	ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
-	free_irq(pdev->irq, hba);
 
 	ufshcd_hba_stop(hba);
 	ufshcd_hba_free(hba);
 
 	scsi_remove_host(hba->host);
 	scsi_host_put(hba->host);
+}
+EXPORT_SYMBOL_GPL(ufshcd_remove);
+
+/**
+ * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
+ *		data structure memory
+ * @pdev - pointer to PCI handle
+ */
+static void ufshcd_pci_remove(struct pci_dev *pdev)
+{
+	struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+	free_irq(pdev->irq, hba);
+	ufshcd_remove(hba);
+	pci_release_regions(pdev);
 	pci_set_drvdata(pdev, NULL);
 	pci_clear_master(pdev);
 	pci_disable_device(pdev);
@@ -1781,75 +1819,52 @@ static void ufshcd_remove(struct pci_dev *pdev)
  *
  * Returns 0 for success, non-zero for failure
  */
-static int ufshcd_set_dma_mask(struct ufs_hba *hba)
+static int ufshcd_set_dma_mask(struct pci_dev *pdev)
 {
 	int err;
-	u64 dma_mask;
-
-	/*
-	 * If controller supports 64 bit addressing mode, then set the DMA
-	 * mask to 64-bit, else set the DMA mask to 32-bit
-	 */
-	if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT)
-		dma_mask = DMA_BIT_MASK(64);
-	else
-		dma_mask = DMA_BIT_MASK(32);
-
-	err = pci_set_dma_mask(hba->pdev, dma_mask);
-	if (err)
-		return err;
-
-	err = pci_set_consistent_dma_mask(hba->pdev, dma_mask);
 
+	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_probe - probe routine of the driver
- * @pdev: pointer to PCI device handle
- * @id: PCI device id
- *
+ * ufshcd_init - Driver initialization routine
+ * @dev: pointer to device handle
+ * @hba_handle: driver private handle
+ * @mmio_base: base register address
+ * @irq_line: Interrupt line of device
  * Returns 0 on success, non-zero value on failure
  */
-static int __devinit
-ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
+		 void __iomem *mmio_base, unsigned int irq_line)
 {
 	struct Scsi_Host *host;
 	struct ufs_hba *hba;
 	int err;
 
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "pci_enable_device failed\n");
+	if (!dev && !mmio_base) {
+		dev_err(dev,
+		"Invalid memory reference for dev or mmio_base NULL\n");
+		err = -ENODEV;
 		goto out_error;
 	}
 
-	pci_set_master(pdev);
-
 	host = scsi_host_alloc(&ufshcd_driver_template,
 				sizeof(struct ufs_hba));
 	if (!host) {
-		dev_err(&pdev->dev, "scsi_host_alloc failed\n");
+		dev_err(dev, "scsi_host_alloc failed\n");
 		err = -ENOMEM;
-		goto out_disable;
+		goto out_error;
 	}
 	hba = shost_priv(host);
-
-	err = pci_request_regions(pdev, UFSHCD);
-	if (err < 0) {
-		dev_err(&pdev->dev, "request regions failed\n");
-		goto out_host_put;
-	}
-
-	hba->mmio_base = pci_ioremap_bar(pdev, 0);
-	if (!hba->mmio_base) {
-		dev_err(&pdev->dev, "memory map failed\n");
-		err = -ENOMEM;
-		goto out_release_regions;
-	}
-
 	hba->host = host;
-	hba->pdev = pdev;
+	hba->dev = dev;
+	hba->mmio_base = mmio_base;
 
 	/* Read capabilities registers */
 	ufshcd_hba_capabilities(hba);
@@ -1857,17 +1872,11 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	/* Get UFS version supported by the controller */
 	hba->ufs_version = ufshcd_get_ufs_version(hba);
 
-	err = ufshcd_set_dma_mask(hba);
-	if (err) {
-		dev_err(&pdev->dev, "set dma mask failed\n");
-		goto out_iounmap;
-	}
-
 	/* Allocate memory for host memory space */
 	err = ufshcd_memory_alloc(hba);
 	if (err) {
-		dev_err(&pdev->dev, "Memory allocation failed\n");
-		goto out_iounmap;
+		dev_err(hba->dev, "Memory allocation failed\n");
+		goto out_disable;
 	}
 
 	/* Configure LRB */
@@ -1889,46 +1898,104 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
 
 	/* IRQ registration */
-	err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+	err = request_irq(irq_line, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
 	if (err) {
-		dev_err(&pdev->dev, "request irq failed\n");
+		dev_err(hba->dev, "request irq failed\n");
 		goto out_lrb_free;
 	}
 
 	/* Enable SCSI tag mapping */
 	err = scsi_init_shared_tag_map(host, host->can_queue);
 	if (err) {
-		dev_err(&pdev->dev, "init shared queue failed\n");
+		dev_err(hba->dev, "init shared queue failed\n");
 		goto out_free_irq;
 	}
 
-	pci_set_drvdata(pdev, hba);
-
-	err = scsi_add_host(host, &pdev->dev);
+	err = scsi_add_host(host, hba->dev);
 	if (err) {
-		dev_err(&pdev->dev, "scsi_add_host failed\n");
+		dev_err(hba->dev, "scsi_add_host failed\n");
 		goto out_free_irq;
 	}
 
 	/* Initialization routine */
 	err = ufshcd_initialize_hba(hba);
 	if (err) {
-		dev_err(&pdev->dev, "Initialization failed\n");
-		goto out_free_irq;
+		dev_err(hba->dev, "Initialization failed\n");
+		goto out_remove_scsi_host;
 	}
+	*hba_handle = hba;
 
 	return 0;
 
+out_remove_scsi_host:
+	scsi_remove_host(hba->host);
 out_free_irq:
-	free_irq(pdev->irq, hba);
+	free_irq(irq_line, hba);
 out_lrb_free:
 	ufshcd_free_hba_memory(hba);
+out_disable:
+	scsi_host_put(host);
+out_error:
+	return err;
+}
+EXPORT_SYMBOL_GPL(ufshcd_init);
+
+/**
+ * ufshcd_pci_probe - probe routine of the driver
+ * @pdev: pointer to PCI device handle
+ * @id: PCI device id
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int __devinit
+ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct ufs_hba *hba;
+	void __iomem *mmio_base;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "pci_enable_device failed\n");
+		goto out_error;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_request_regions(pdev, UFSHCD);
+	if (err < 0) {
+		dev_err(&pdev->dev, "request regions failed\n");
+		goto out_disable;
+	}
+
+	mmio_base = pci_ioremap_bar(pdev, 0);
+	if (!mmio_base) {
+		dev_err(&pdev->dev, "memory map failed\n");
+		err = -ENOMEM;
+		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, "%s:%d %sInitialization failed\n",
+				__FILE__, __LINE__, __func__);
+		goto out_iounmap;
+	}
+
+	pci_set_drvdata(pdev, hba);
+
+	return 0;
+
 out_iounmap:
-	iounmap(hba->mmio_base);
+	iounmap(mmio_base);
 out_release_regions:
 	pci_release_regions(pdev);
-out_host_put:
-	scsi_host_put(host);
 out_disable:
 	pci_clear_master(pdev);
 	pci_disable_device(pdev);
@@ -1946,19 +2013,19 @@ MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
 static struct pci_driver ufshcd_pci_driver = {
 	.name = UFSHCD,
 	.id_table = ufshcd_pci_tbl,
-	.probe = ufshcd_probe,
-	.remove = __devexit_p(ufshcd_remove),
-	.shutdown = ufshcd_shutdown,
+	.probe = ufshcd_pci_probe,
+	.remove = __devexit_p(ufshcd_pci_remove),
+	.shutdown = ufshcd_pci_shutdown,
 #ifdef CONFIG_PM
-	.suspend = ufshcd_suspend,
-	.resume = ufshcd_resume,
+	.suspend = ufshcd_pci_suspend,
+	.resume = ufshcd_pci_resume,
 #endif
 };
 
 module_pci_driver(ufshcd_pci_driver);
 
-MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, "
-	      "Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
 MODULE_DESCRIPTION("Generic UFS host controller driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 6e3510f..1cc1e00 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -4,43 +4,33 @@
  * This code is based on drivers/scsi/ufs/ufshci.h
  * Copyright (C) 2011-2012 Samsung India Software Operations
  *
- * Santosh Yaraganavi <santosh.sy@samsung.com>
- * Vinayak Holikatti <h.vinayak@samsung.com>
+ * Authors:
+ *	Santosh Yaraganavi <santosh.sy@samsung.com>
+ *	Vinayak Holikatti <h.vinayak@samsung.com>
  *
  * 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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
  */
 
 #ifndef _UFSHCI_H
-- 
1.7.5.4


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

* [PATCH V5 2/4] [SCSI] drivers/scsi/ufs: Separate PCI code into glue driver
       [not found] <1356552955-18027-1-git-send-email-y>
  2012-12-26 20:15 ` [PATCH V5 1/4] [SCSI] drivers/scsi/ufs: Seggregate PCI Specific Code vinholikatti
@ 2012-12-26 20:15 ` vinholikatti
  2012-12-27 15:05   ` Subhash Jadavani
  2012-12-26 20:15 ` [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd vinholikatti
  2012-12-26 20:15 ` [PATCH V5 4/4] [SCSI] ufs: Correct the expected data transfer size vinholikatti
  3 siblings, 1 reply; 16+ messages in thread
From: vinholikatti @ 2012-12-26 20:15 UTC (permalink / raw)
  To: james.bottomley; +Cc: linux-scsi, santoshsy, Vinayak Holikatti

From: Vinayak Holikatti <vinholikatti@gmail.com>

This patch separates PCI code from ufshcd.c and makes it as a
core driver module and adds a new file ufshcd-pci.c as PCI glue
driver.

Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
---
 drivers/scsi/ufs/Kconfig      |   26 +++-
 drivers/scsi/ufs/Makefile     |    1 +
 drivers/scsi/ufs/ufshcd-pci.c |  211 +++++++++++++++++++++++++++
 drivers/scsi/ufs/ufshcd.c     |  323 +----------------------------------------
 drivers/scsi/ufs/ufshcd.h     |  200 +++++++++++++++++++++++++
 5 files changed, 437 insertions(+), 324 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufshcd-pci.c
 create mode 100644 drivers/scsi/ufs/ufshcd.h

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 9c84569..d77ae97 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -33,7 +33,27 @@
 # this program.
 
 config SCSI_UFSHCD
-	tristate "Universal Flash Storage host controller driver"
-	depends on PCI && SCSI
+	tristate "Universal Flash Storage Controller Driver Core"
+	depends on SCSI
 	---help---
-	This is a generic driver which supports PCIe UFS Host controllers.
+	This selects the support for UFS devices in Linux, say Y and make
+	  sure that you know the name of your UFS host adapter (the card
+	  inside your computer that "speaks" the UFS protocol, also
+	  called UFS Host Controller), because you will be asked for it.
+	  The module will be called ufshcd.
+
+	  To compile this driver as a module, choose M here and read
+	  <file:Documentation/scsi/ufs.txt>.
+	  However, do not compile this as a module if your root file system
+	  (the one containing the directory /) is located on a UFS device.
+
+config SCSI_UFSHCD_PCI
+	tristate "PCI bus based UFS Controller support"
+	depends on SCSI_UFSHCD && PCI
+	---help---
+	This selects the PCI UFS Host Controller Interface.
+	  Most controllers found today are PCI devices.
+
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index adf7895..9eda0df 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,2 +1,3 @@
 # UFSHCD makefile
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
new file mode 100644
index 0000000..ba86b5e
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -0,0 +1,211 @@
+/*
+ * Universal Flash Storage Host controller driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd-pci.c
+ * Copyright (C) 2011-2012 Samsung India Software Operations
+ *
+ * Authors:
+ *	Santosh Yaraganavi <santosh.sy@samsung.com>
+ *	Vinayak Holikatti <h.vinayak@samsung.com>
+ *
+ * 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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
+ */
+
+#include "ufshcd.h"
+#include <linux/pci.h>
+
+#ifdef CONFIG_PM
+/**
+ * ufshcd_pci_suspend - suspend power management function
+ * @pdev: pointer to PCI device handle
+ * @state: power state
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_suspend
+	 * 2. Do bus specific power management
+	 */
+
+	return -ENOSYS;
+}
+
+/**
+ * ufshcd_pci_resume - resume power management function
+ * @pdev: pointer to PCI device handle
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pci_resume(struct pci_dev *pdev)
+{
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_resume.
+	 * 2. Do bus specific wake up
+	 */
+
+	return -ENOSYS;
+}
+#endif /* CONFIG_PM */
+
+/**
+ * ufshcd_pci_shutdown - main function to put the controller in reset state
+ * @pdev: pointer to PCI device handle
+ */
+static void ufshcd_pci_shutdown(struct pci_dev *pdev)
+{
+	ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
+}
+
+/**
+ * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
+ *		data structure memory
+ * @pdev - pointer to PCI handle
+ */
+static void ufshcd_pci_remove(struct pci_dev *pdev)
+{
+	struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+	free_irq(pdev->irq, hba);
+	ufshcd_remove(hba);
+	pci_release_regions(pdev);
+	pci_set_drvdata(pdev, NULL);
+	pci_clear_master(pdev);
+	pci_disable_device(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
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int __devinit
+ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct ufs_hba *hba;
+	void __iomem *mmio_base;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "pci_enable_device failed\n");
+		goto out_error;
+	}
+
+	pci_set_master(pdev);
+
+
+	err = pci_request_regions(pdev, UFSHCD);
+	if (err < 0) {
+		dev_err(&pdev->dev, "request regions failed\n");
+		goto out_disable;
+	}
+
+	mmio_base = pci_ioremap_bar(pdev, 0);
+	if (!mmio_base) {
+		dev_err(&pdev->dev, "memory map failed\n");
+		err = -ENOMEM;
+		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, "%s:%d %sInitialization failed\n",
+				__FILE__, __LINE__, __func__);
+		goto out_iounmap;
+	}
+
+	pci_set_drvdata(pdev, hba);
+
+	return 0;
+
+out_iounmap:
+	iounmap(mmio_base);
+out_release_regions:
+	pci_release_regions(pdev);
+out_disable:
+	pci_clear_master(pdev);
+	pci_disable_device(pdev);
+out_error:
+	return err;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
+	{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ }	/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
+
+static struct pci_driver ufshcd_pci_driver = {
+	.name = UFSHCD,
+	.id_table = ufshcd_pci_tbl,
+	.probe = ufshcd_pci_probe,
+	.remove = __devexit_p(ufshcd_pci_remove),
+	.shutdown = ufshcd_pci_shutdown,
+#ifdef CONFIG_PM
+	.suspend = ufshcd_pci_suspend,
+	.resume = ufshcd_pci_resume,
+#endif
+};
+
+module_pci_driver(ufshcd_pci_driver);
+
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("PCI based UFS host controller driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 86b5b49..5d2d9e6 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -33,35 +33,7 @@
  * this program.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/bitops.h>
-
-#include <asm/irq.h>
-#include <asm/byteorder.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_eh.h>
-
-#include "ufs.h"
-#include "ufshci.h"
-
-#define UFSHCD "ufshcd"
-#define UFSHCD_DRIVER_VERSION "0.1"
+#include "ufshcd.h"
 
 enum {
 	UFSHCD_MAX_CHANNEL	= 0,
@@ -92,121 +64,6 @@ enum {
 };
 
 /**
- * struct uic_command - UIC command structure
- * @command: UIC command
- * @argument1: UIC command argument 1
- * @argument2: UIC command argument 2
- * @argument3: UIC command argument 3
- * @cmd_active: Indicate if UIC command is outstanding
- * @result: UIC command result
- */
-struct uic_command {
-	u32 command;
-	u32 argument1;
-	u32 argument2;
-	u32 argument3;
-	int cmd_active;
-	int result;
-};
-
-/**
- * struct ufs_hba - per adapter private structure
- * @mmio_base: UFSHCI base register address
- * @ucdl_base_addr: UFS Command Descriptor base address
- * @utrdl_base_addr: UTP Transfer Request Descriptor base address
- * @utmrdl_base_addr: UTP Task Management Descriptor base address
- * @ucdl_dma_addr: UFS Command Descriptor DMA address
- * @utrdl_dma_addr: UTRDL DMA address
- * @utmrdl_dma_addr: UTMRDL DMA address
- * @host: Scsi_Host instance of the driver
- * @dev: device handle
- * @lrb: local reference block
- * @outstanding_tasks: Bits representing outstanding task requests
- * @outstanding_reqs: Bits representing outstanding transfer requests
- * @capabilities: UFS Controller Capabilities
- * @nutrs: Transfer Request Queue depth supported by controller
- * @nutmrs: Task Management Queue depth supported by controller
- * @active_uic_cmd: handle of active UIC command
- * @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
- * @uic_workq: Work queue for UIC completion handling
- * @feh_workq: Work queue for fatal controller error handling
- * @errors: HBA errors
- */
-struct ufs_hba {
-	void __iomem *mmio_base;
-
-	/* Virtual memory reference */
-	struct utp_transfer_cmd_desc *ucdl_base_addr;
-	struct utp_transfer_req_desc *utrdl_base_addr;
-	struct utp_task_req_desc *utmrdl_base_addr;
-
-	/* DMA memory reference */
-	dma_addr_t ucdl_dma_addr;
-	dma_addr_t utrdl_dma_addr;
-	dma_addr_t utmrdl_dma_addr;
-
-	struct Scsi_Host *host;
-	struct device *dev;
-
-	struct ufshcd_lrb *lrb;
-
-	unsigned long outstanding_tasks;
-	unsigned long outstanding_reqs;
-
-	u32 capabilities;
-	int nutrs;
-	int nutmrs;
-	u32 ufs_version;
-
-	struct uic_command active_uic_cmd;
-	wait_queue_head_t ufshcd_tm_wait_queue;
-	unsigned long tm_condition;
-
-	u32 ufshcd_state;
-	u32 int_enable_mask;
-
-	/* Work Queues */
-	struct work_struct uic_workq;
-	struct work_struct feh_workq;
-
-	/* HBA Errors */
-	u32 errors;
-};
-
-/**
- * struct ufshcd_lrb - local reference block
- * @utr_descriptor_ptr: UTRD address of the command
- * @ucd_cmd_ptr: UCD address of the command
- * @ucd_rsp_ptr: Response UPIU address for this command
- * @ucd_prdt_ptr: PRDT address of the command
- * @cmd: pointer to SCSI command
- * @sense_buffer: pointer to sense buffer address of the SCSI command
- * @sense_bufflen: Length of the sense buffer
- * @scsi_status: SCSI status of the command
- * @command_type: SCSI, UFS, Query.
- * @task_tag: Task tag of the command
- * @lun: LUN of the command
- */
-struct ufshcd_lrb {
-	struct utp_transfer_req_desc *utr_descriptor_ptr;
-	struct utp_upiu_cmd *ucd_cmd_ptr;
-	struct utp_upiu_rsp *ucd_rsp_ptr;
-	struct ufshcd_sg_entry *ucd_prdt_ptr;
-
-	struct scsi_cmnd *cmd;
-	u8 *sense_buffer;
-	unsigned int sense_bufflen;
-	int scsi_status;
-
-	int command_type;
-	int task_tag;
-	unsigned int lun;
-};
-
-/**
  * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
  * @hba - Pointer to adapter instance
  *
@@ -419,15 +276,6 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
 }
 
 /**
- * ufshcd_hba_stop - Send controller to reset state
- * @hba: per adapter instance
- */
-static inline void ufshcd_hba_stop(struct ufs_hba *hba)
-{
-	writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
-}
-
-/**
  * ufshcd_hba_start - Start controller initialization sequence
  * @hba: per adapter instance
  */
@@ -1678,15 +1526,6 @@ static struct scsi_host_template ufshcd_driver_template = {
 };
 
 /**
- * ufshcd_pci_shutdown - main function to put the controller in reset state
- * @pdev: pointer to PCI device handle
- */
-static void ufshcd_pci_shutdown(struct pci_dev *pdev)
-{
-	ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
-}
-
-/**
  * ufshcd_suspend - suspend power management function
  * @hba: per adapter instance
  * @state: power state
@@ -1729,43 +1568,6 @@ int ufshcd_resume(struct ufs_hba *hba)
 }
 EXPORT_SYMBOL_GPL(ufshcd_resume);
 
-#ifdef CONFIG_PM
-/**
- * ufshcd_pci_suspend - suspend power management function
- * @pdev: pointer to PCI device handle
- * @state: power state
- *
- * Returns -ENOSYS
- */
-static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	/*
-	 * TODO:
-	 * 1. Call ufshcd_suspend
-	 * 2. Do bus specific power management
-	 */
-
-	return -ENOSYS;
-}
-
-/**
- * ufshcd_pci_resume - resume power management function
- * @pdev: pointer to PCI device handle
- *
- * Returns -ENOSYS
- */
-static int ufshcd_pci_resume(struct pci_dev *pdev)
-{
-	/*
-	 * TODO:
-	 * 1. Call ufshcd_resume.
-	 * 2. Do bus specific wake up
-	 */
-
-	return -ENOSYS;
-}
-#endif /* CONFIG_PM */
-
 /**
  * ufshcd_hba_free - free allocated memory for
  *			host memory space data structures
@@ -1796,43 +1598,6 @@ void ufshcd_remove(struct ufs_hba *hba)
 EXPORT_SYMBOL_GPL(ufshcd_remove);
 
 /**
- * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
- *		data structure memory
- * @pdev - pointer to PCI handle
- */
-static void ufshcd_pci_remove(struct pci_dev *pdev)
-{
-	struct ufs_hba *hba = pci_get_drvdata(pdev);
-
-	free_irq(pdev->irq, hba);
-	ufshcd_remove(hba);
-	pci_release_regions(pdev);
-	pci_set_drvdata(pdev, NULL);
-	pci_clear_master(pdev);
-	pci_disable_device(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_init - Driver initialization routine
  * @dev: pointer to device handle
  * @hba_handle: driver private handle
@@ -1940,92 +1705,8 @@ out_error:
 }
 EXPORT_SYMBOL_GPL(ufshcd_init);
 
-/**
- * ufshcd_pci_probe - probe routine of the driver
- * @pdev: pointer to PCI device handle
- * @id: PCI device id
- *
- * Returns 0 on success, non-zero value on failure
- */
-static int __devinit
-ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct ufs_hba *hba;
-	void __iomem *mmio_base;
-	int err;
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "pci_enable_device failed\n");
-		goto out_error;
-	}
-
-	pci_set_master(pdev);
-
-	err = pci_request_regions(pdev, UFSHCD);
-	if (err < 0) {
-		dev_err(&pdev->dev, "request regions failed\n");
-		goto out_disable;
-	}
-
-	mmio_base = pci_ioremap_bar(pdev, 0);
-	if (!mmio_base) {
-		dev_err(&pdev->dev, "memory map failed\n");
-		err = -ENOMEM;
-		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, "%s:%d %sInitialization failed\n",
-				__FILE__, __LINE__, __func__);
-		goto out_iounmap;
-	}
-
-	pci_set_drvdata(pdev, hba);
-
-	return 0;
-
-out_iounmap:
-	iounmap(mmio_base);
-out_release_regions:
-	pci_release_regions(pdev);
-out_disable:
-	pci_clear_master(pdev);
-	pci_disable_device(pdev);
-out_error:
-	return err;
-}
-
-static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
-	{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ }	/* terminate list */
-};
-
-MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
-
-static struct pci_driver ufshcd_pci_driver = {
-	.name = UFSHCD,
-	.id_table = ufshcd_pci_tbl,
-	.probe = ufshcd_pci_probe,
-	.remove = __devexit_p(ufshcd_pci_remove),
-	.shutdown = ufshcd_pci_shutdown,
-#ifdef CONFIG_PM
-	.suspend = ufshcd_pci_suspend,
-	.resume = ufshcd_pci_resume,
-#endif
-};
-
-module_pci_driver(ufshcd_pci_driver);
-
 MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
 MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
-MODULE_DESCRIPTION("Generic UFS host controller driver");
+MODULE_DESCRIPTION("Generic Core UFS host controller driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
new file mode 100644
index 0000000..1829e93
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -0,0 +1,200 @@
+/*
+ * Universal Flash Storage Host controller driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd.h
+ * Copyright (C) 2011-2012 Samsung India Software Operations
+ *
+ * Authors:
+ *	Santosh Yaraganavi <santosh.sy@samsung.com>
+ *	Vinayak Holikatti <h.vinayak@samsung.com>
+ *
+ * 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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
+ */
+
+#ifndef _UFSHCD_H
+#define _UFSHCD_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+
+#include <asm/irq.h>
+#include <asm/byteorder.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_eh.h>
+
+#include "ufs.h"
+#include "ufshci.h"
+
+#define UFSHCD "ufshcd"
+#define UFSHCD_DRIVER_VERSION "0.2"
+
+/**
+ * struct uic_command - UIC command structure
+ * @command: UIC command
+ * @argument1: UIC command argument 1
+ * @argument2: UIC command argument 2
+ * @argument3: UIC command argument 3
+ * @cmd_active: Indicate if UIC command is outstanding
+ * @result: UIC command result
+ */
+struct uic_command {
+	u32 command;
+	u32 argument1;
+	u32 argument2;
+	u32 argument3;
+	int cmd_active;
+	int result;
+};
+
+/**
+ * struct ufshcd_lrb - local reference block
+ * @utr_descriptor_ptr: UTRD address of the command
+ * @ucd_cmd_ptr: UCD address of the command
+ * @ucd_rsp_ptr: Response UPIU address for this command
+ * @ucd_prdt_ptr: PRDT address of the command
+ * @cmd: pointer to SCSI command
+ * @sense_buffer: pointer to sense buffer address of the SCSI command
+ * @sense_bufflen: Length of the sense buffer
+ * @scsi_status: SCSI status of the command
+ * @command_type: SCSI, UFS, Query.
+ * @task_tag: Task tag of the command
+ * @lun: LUN of the command
+ */
+struct ufshcd_lrb {
+	struct utp_transfer_req_desc *utr_descriptor_ptr;
+	struct utp_upiu_cmd *ucd_cmd_ptr;
+	struct utp_upiu_rsp *ucd_rsp_ptr;
+	struct ufshcd_sg_entry *ucd_prdt_ptr;
+
+	struct scsi_cmnd *cmd;
+	u8 *sense_buffer;
+	unsigned int sense_bufflen;
+	int scsi_status;
+
+	int command_type;
+	int task_tag;
+	unsigned int lun;
+};
+
+
+/**
+ * struct ufs_hba - per adapter private structure
+ * @mmio_base: UFSHCI base register address
+ * @ucdl_base_addr: UFS Command Descriptor base address
+ * @utrdl_base_addr: UTP Transfer Request Descriptor base address
+ * @utmrdl_base_addr: UTP Task Management Descriptor base address
+ * @ucdl_dma_addr: UFS Command Descriptor DMA address
+ * @utrdl_dma_addr: UTRDL DMA address
+ * @utmrdl_dma_addr: UTMRDL DMA address
+ * @host: Scsi_Host instance of the driver
+ * @dev: device handle
+ * @lrb: local reference block
+ * @outstanding_tasks: Bits representing outstanding task requests
+ * @outstanding_reqs: Bits representing outstanding transfer requests
+ * @capabilities: UFS Controller Capabilities
+ * @nutrs: Transfer Request Queue depth supported by controller
+ * @nutmrs: Task Management Queue depth supported by controller
+ * @active_uic_cmd: handle of active UIC command
+ * @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
+ * @uic_workq: Work queue for UIC completion handling
+ * @feh_workq: Work queue for fatal controller error handling
+ * @errors: HBA errors
+ */
+struct ufs_hba {
+	void __iomem *mmio_base;
+
+	/* Virtual memory reference */
+	struct utp_transfer_cmd_desc *ucdl_base_addr;
+	struct utp_transfer_req_desc *utrdl_base_addr;
+	struct utp_task_req_desc *utmrdl_base_addr;
+
+	/* DMA memory reference */
+	dma_addr_t ucdl_dma_addr;
+	dma_addr_t utrdl_dma_addr;
+	dma_addr_t utmrdl_dma_addr;
+
+	struct Scsi_Host *host;
+	struct device *dev;
+
+	struct ufshcd_lrb *lrb;
+
+	unsigned long outstanding_tasks;
+	unsigned long outstanding_reqs;
+
+	u32 capabilities;
+	int nutrs;
+	int nutmrs;
+	unsigned int irq;
+	u32 ufs_version;
+
+	struct uic_command active_uic_cmd;
+	wait_queue_head_t ufshcd_tm_wait_queue;
+	unsigned long tm_condition;
+
+	u32 ufshcd_state;
+	u32 int_enable_mask;
+
+	/* Work Queues */
+	struct work_struct uic_workq;
+	struct work_struct feh_workq;
+
+	/* HBA Errors */
+	u32 errors;
+};
+
+int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
+			unsigned int);
+void ufshcd_remove(struct ufs_hba *);
+
+/**
+ * ufshcd_hba_stop - Send controller to reset state
+ * @hba: per adapter instance
+ */
+static inline void ufshcd_hba_stop(struct ufs_hba *hba)
+{
+	writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
+}
+
+#endif /* End of Header */
-- 
1.7.5.4


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

* [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd
       [not found] <1356552955-18027-1-git-send-email-y>
  2012-12-26 20:15 ` [PATCH V5 1/4] [SCSI] drivers/scsi/ufs: Seggregate PCI Specific Code vinholikatti
  2012-12-26 20:15 ` [PATCH V5 2/4] [SCSI] drivers/scsi/ufs: Separate PCI code into glue driver vinholikatti
@ 2012-12-26 20:15 ` vinholikatti
  2012-12-27 14:58   ` Subhash Jadavani
  2012-12-26 20:15 ` [PATCH V5 4/4] [SCSI] ufs: Correct the expected data transfer size vinholikatti
  3 siblings, 1 reply; 16+ messages in thread
From: vinholikatti @ 2012-12-26 20:15 UTC (permalink / raw)
  To: james.bottomley; +Cc: linux-scsi, santoshsy, Vinayak Holikatti

From: Vinayak Holikatti <vinholikatti@gmail.com>

This patch adds Platform glue driver for ufshcd.

Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
---
 drivers/scsi/ufs/Kconfig         |   11 ++
 drivers/scsi/ufs/Makefile        |    1 +
 drivers/scsi/ufs/ufshcd-pltfrm.c |  205 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 217 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufshcd-pltfrm.c

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index d77ae97..96e1721 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -57,3 +57,14 @@ config SCSI_UFSHCD_PCI
 	  If you have a controller with this interface, say Y or M here.
 
 	  If unsure, say N.
+
+config SCSI_UFSHCD_PLATFORM
+	tristate "Platform based UFS Controller support"
+	depends on SCSI_UFSHCD
+	---help---
+	This selects the UFS host controller support. If you have a
+	   platform with UFS controller, say Y or M here.
+
+	   If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 9eda0df..1e5bd48 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,3 +1,4 @@
 # UFSHCD makefile
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
+obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
new file mode 100644
index 0000000..94acfdc
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -0,0 +1,205 @@
+/*
+ * Universal Flash Storage Host controller driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
+ * Copyright (C) 2011-2012 Samsung India Software Operations
+ *
+ * Authors:
+ *	Santosh Yaraganavi <santosh.sy@samsung.com>
+ *	Vinayak Holikatti <h.vinayak@samsung.com>
+ *
+ * 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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
+ */
+
+#include "ufshcd.h"
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_PM
+/**
+ * ufshcd_pltfrm_suspend - suspend power management function
+ * @pdev: pointer to Platform device handle
+ * @mesg: power state
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pltfrm_suspend(struct platform_device *pdev,
+				 pm_message_t mesg)
+{
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_suspend
+	 * 2. Do bus specific power management
+	 */
+
+	return -ENOSYS;
+}
+
+/**
+ * ufshcd_pltfrm_resume - resume power management function
+ * @pdev: pointer to Platform device handle
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pltfrm_resume(struct platform_device *pdev)
+{
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_resume.
+	 * 2. Do bus specific wake up
+	 */
+
+	return -ENOSYS;
+}
+#endif
+
+/**
+ * ufshcd_pltfrm_probe - probe routine of the driver
+ * @pdev: pointer to Platform device handle
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int __devinit
+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;
+	struct device *dev = &pdev->dev;
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_res) {
+		dev_err(&pdev->dev,
+			"%s: Memory resource not available\n", __FILE__);
+		err = -ENODEV;
+		goto out_error;
+	}
+
+	mem_size = resource_size(mem_res);
+	if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
+		dev_err(&pdev->dev,
+			"ufshcd: Cannot reserve the memory resource\n");
+		err = -EBUSY;
+		goto out_error;
+	}
+
+	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, "ufshcd: IRQ resource not available\n");
+		err = -ENODEV;
+		goto out_iounmap;
+	}
+
+	err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
+	if (err) {
+		dev_err(&pdev->dev, "set dma mask failed\n");
+		goto out_iounmap;
+	}
+
+	err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
+	if (err) {
+		dev_err(&pdev->dev, "%s: Intialization failed\n",
+			__FILE__);
+		goto out_iounmap;
+	}
+
+	platform_set_drvdata(pdev, hba);
+
+	return 0;
+
+out_iounmap:
+	iounmap(mmio_base);
+out_release_regions:
+	release_mem_region(mem_res->start, mem_size);
+out_error:
+	return err;
+}
+
+/**
+ * ufshcd_pltfrm_remove - remove platform driver routine
+ * @pdev: pointer to platform device handle
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int __devexit ufshcd_pltfrm_remove(struct platform_device *pdev)
+{
+	struct resource *mem_res;
+	struct resource *irq_res;
+	resource_size_t mem_size;
+	struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+	if (!irq_res)
+		dev_err(&pdev->dev, "ufshcd: IRQ resource not available\n");
+	else
+		free_irq(irq_res->start, hba);
+
+	ufshcd_remove(hba);
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_res)
+		dev_err(&pdev->dev, "ufshcd: Memory resource not available\n");
+	else {
+		mem_size = resource_size(mem_res);
+		release_mem_region(mem_res->start, mem_size);
+	}
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static const struct of_device_id ufs_of_match[] = {
+	{ .compatible = "jedec,ufs-1.1"},
+};
+
+static struct platform_driver ufshcd_pltfrm_driver = {
+	.probe	= ufshcd_pltfrm_probe,
+	.remove	= __devexit_p(ufshcd_pltfrm_remove),
+#ifdef CONFIG_PM
+	.suspend = ufshcd_pltfrm_suspend,
+	.resume = ufshcd_pltfrm_resume,
+#endif
+	.driver	= {
+		.name	= "ufshcd",
+		.owner	= THIS_MODULE,
+		.of_match_table = ufs_of_match,
+	},
+};
+
+module_platform_driver(ufshcd_pltfrm_driver);
+
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("Platform based UFS host controller driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(UFSHCD_DRIVER_VERSION);
-- 
1.7.5.4


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

* [PATCH V5 4/4] [SCSI] ufs: Correct the expected data transfer size
       [not found] <1356552955-18027-1-git-send-email-y>
                   ` (2 preceding siblings ...)
  2012-12-26 20:15 ` [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd vinholikatti
@ 2012-12-26 20:15 ` vinholikatti
  3 siblings, 0 replies; 16+ messages in thread
From: vinholikatti @ 2012-12-26 20:15 UTC (permalink / raw)
  To: james.bottomley; +Cc: linux-scsi, santoshsy, Vinayak Holikatti

From: Vinayak Holikatti <vinholikatti@gmail.com>

This patch corrects the expected data transfer size of the
command UPIU. The current implementation of cmd->transfersize
is wrong as it probably equal to sector size. With this
implementation the transfer size is updated correctly

Reported-by: KOBAYASHI Yoshitake <yoshitake.kobayashi@toshiba.co.jp>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
---
 drivers/scsi/ufs/ufshcd.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d2d9e6..933338e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -478,7 +478,7 @@ static void ufshcd_compose_upiu(struct ufshcd_lrb *lrbp)
 		ucd_cmd_ptr->header.dword_2 = 0;
 
 		ucd_cmd_ptr->exp_data_transfer_len =
-			cpu_to_be32(lrbp->cmd->transfersize);
+			cpu_to_be32(lrbp->cmd->sdb.length);
 
 		memcpy(ucd_cmd_ptr->cdb,
 		       lrbp->cmd->cmnd,
-- 
1.7.5.4


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

* Re: [PATCH V5 1/4] [SCSI] drivers/scsi/ufs: Seggregate PCI Specific Code
  2012-12-26 20:15 ` [PATCH V5 1/4] [SCSI] drivers/scsi/ufs: Seggregate PCI Specific Code vinholikatti
@ 2012-12-27 14:29   ` Subhash Jadavani
  2013-01-04  7:00     ` vinayak holikatti
  0 siblings, 1 reply; 16+ messages in thread
From: Subhash Jadavani @ 2012-12-27 14:29 UTC (permalink / raw)
  To: vinholikatti; +Cc: james.bottomley, linux-scsi, santoshsy


Few comments inline:

On 12/27/2012 1:45 AM, vinholikatti@gmail.com wrote:
> From: Vinayak Holikatti <vinholikatti@gmail.com>
>
> This patch seggregates the PCI specific code in ufshcd.c to make it
> ready for splitting into core ufs driver and PCI glue driver. Also
> copyright header modification to remove extra warranty disclaim.
>
> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
> Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
> Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
> ---
>   drivers/scsi/ufs/Kconfig  |   50 +++----
>   drivers/scsi/ufs/ufs.h    |   42 ++----
>   drivers/scsi/ufs/ufshcd.c |  339 +++++++++++++++++++++++++++------------------
>   drivers/scsi/ufs/ufshci.h |   42 ++----
>   4 files changed, 255 insertions(+), 218 deletions(-)
>
> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
> index 8f27f9d..9c84569 100644
> --- a/drivers/scsi/ufs/Kconfig
> +++ b/drivers/scsi/ufs/Kconfig
> @@ -2,45 +2,35 @@
>   # Kernel configuration file for the UFS Host Controller
>   #
>   # This code is based on drivers/scsi/ufs/Kconfig
> -# Copyright (C) 2011  Samsung Samsung India Software Operations
> +# Copyright (C) 2011-2012 Samsung India Software Operations
> +#
> +# Authors:
> +#	Santosh Yaraganavi <santosh.sy@samsung.com>
> +#	Vinayak Holikatti <h.vinayak@samsung.com>
>   #
> -# Santosh Yaraganavi <santosh.sy@samsung.com>
> -# Vinayak Holikatti <h.vinayak@samsung.com>
> -
>   # 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.
> -
> +# See the COPYING file in the top-level directory or visit
> +# <http://www.gnu.org/licenses/gpl-2.0.html>
> +#
>   # This program is distributed in the hope that it will be useful,
>   # but WITHOUT ANY WARRANTY; without even the implied warranty of
>   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>   # GNU General Public License for more details.
> -
> -# NO WARRANTY
> -# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
> -# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
> -# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
> -# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
> -# solely responsible for determining the appropriateness of using and
> -# distributing the Program and assumes all risks associated with its
> -# exercise of rights under this Agreement, including but not limited to
> -# the risks and costs of program errors, damage to or loss of data,
> -# programs or equipment, and unavailability or interruption of operations.
> -
> -# DISCLAIMER OF LIABILITY
> -# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
> -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> -# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
> -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> -# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> -# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
> -# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
> -
> -# You should have received a copy of the GNU General Public License
> -# along with this program; if not, write to the Free Software
> -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
> -# USA.
> +#
> +# This program is provided "AS IS" and "WITH ALL FAULTS" and
> +# without warranty of any kind. You are solely responsible for
> +# determining the appropriateness of using and distributing
> +# the program and assume all risks associated with your exercise
> +# of rights with respect to the program, including but not limited
> +# to infringement of third party rights, the risks and costs of
> +# program errors, damage to or loss of data, programs or equipment,
> +# and unavailability or interruption of operations. Under no
> +# circumstances will the contributor of this Program be liable for
> +# any damages of any kind arising from your use or distribution of
> +# this program.
>   
>   config SCSI_UFSHCD
>   	tristate "Universal Flash Storage host controller driver"
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index b207529..4b3d611 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -4,43 +4,33 @@
>    * This code is based on drivers/scsi/ufs/ufs.h
>    * Copyright (C) 2011-2012 Samsung India Software Operations
>    *
> - * Santosh Yaraganavi <santosh.sy@samsung.com>
> - * Vinayak Holikatti <h.vinayak@samsung.com>
> + * Authors:
> + *	Santosh Yaraganavi <santosh.sy@samsung.com>
> + *	Vinayak Holikatti <h.vinayak@samsung.com>
>    *
>    * 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.
> + * See the COPYING file in the top-level directory or visit
> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>    *
>    * This program is distributed in the hope that it will be useful,
>    * but WITHOUT ANY WARRANTY; without even the implied warranty of
>    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>    * GNU General Public License for more details.
>    *
> - * NO WARRANTY
> - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
> - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
> - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
> - * solely responsible for determining the appropriateness of using and
> - * distributing the Program and assumes all risks associated with its
> - * exercise of rights under this Agreement, including but not limited to
> - * the risks and costs of program errors, damage to or loss of data,
> - * programs or equipment, and unavailability or interruption of operations.
> -
> - * DISCLAIMER OF LIABILITY
> - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
> - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
> - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
> - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
> -
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
> - * USA.
> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
> + * without warranty of any kind. You are solely responsible for
> + * determining the appropriateness of using and distributing
> + * the program and assume all risks associated with your exercise
> + * of rights with respect to the program, including but not limited
> + * to infringement of third party rights, the risks and costs of
> + * program errors, damage to or loss of data, programs or equipment,
> + * and unavailability or interruption of operations. Under no
> + * circumstances will the contributor of this Program be liable for
> + * any damages of any kind arising from your use or distribution of
> + * this program.
>    */
>   
>   #ifndef _UFS_H
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 58f4ba6..86b5b49 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -4,43 +4,33 @@
>    * This code is based on drivers/scsi/ufs/ufshcd.c
>    * Copyright (C) 2011-2012 Samsung India Software Operations
>    *
> - * Santosh Yaraganavi <santosh.sy@samsung.com>
> - * Vinayak Holikatti <h.vinayak@samsung.com>
> + * Authors:
> + *	Santosh Yaraganavi <santosh.sy@samsung.com>
> + *	Vinayak Holikatti <h.vinayak@samsung.com>
>    *
>    * 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.
> + * See the COPYING file in the top-level directory or visit
> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>    *
>    * This program is distributed in the hope that it will be useful,
>    * but WITHOUT ANY WARRANTY; without even the implied warranty of
>    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>    * GNU General Public License for more details.
>    *
> - * NO WARRANTY
> - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
> - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
> - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
> - * solely responsible for determining the appropriateness of using and
> - * distributing the Program and assumes all risks associated with its
> - * exercise of rights under this Agreement, including but not limited to
> - * the risks and costs of program errors, damage to or loss of data,
> - * programs or equipment, and unavailability or interruption of operations.
> -
> - * DISCLAIMER OF LIABILITY
> - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
> - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
> - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
> - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
> -
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
> - * USA.
> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
> + * without warranty of any kind. You are solely responsible for
> + * determining the appropriateness of using and distributing
> + * the program and assume all risks associated with your exercise
> + * of rights with respect to the program, including but not limited
> + * to infringement of third party rights, the risks and costs of
> + * program errors, damage to or loss of data, programs or equipment,
> + * and unavailability or interruption of operations. Under no
> + * circumstances will the contributor of this Program be liable for
> + * any damages of any kind arising from your use or distribution of
> + * this program.
>    */
>   
>   #include <linux/module.h>
> @@ -129,7 +119,7 @@ struct uic_command {
>    * @utrdl_dma_addr: UTRDL DMA address
>    * @utmrdl_dma_addr: UTMRDL DMA address
>    * @host: Scsi_Host instance of the driver
> - * @pdev: PCI device handle
> + * @dev: device handle
>    * @lrb: local reference block
>    * @outstanding_tasks: Bits representing outstanding task requests
>    * @outstanding_reqs: Bits representing outstanding transfer requests
> @@ -159,7 +149,7 @@ struct ufs_hba {
>   	dma_addr_t utmrdl_dma_addr;
>   
>   	struct Scsi_Host *host;
> -	struct pci_dev *pdev;
> +	struct device *dev;
>   
>   	struct ufshcd_lrb *lrb;
>   
> @@ -335,21 +325,21 @@ static inline void ufshcd_free_hba_memory(struct ufs_hba *hba)
>   
>   	if (hba->utmrdl_base_addr) {
>   		utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
> -		dma_free_coherent(&hba->pdev->dev, utmrdl_size,
> +		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->pdev->dev, utrdl_size,
> +		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->pdev->dev, ucdl_size,
> +		dma_free_coherent(hba->dev, ucdl_size,
>   				  hba->ucdl_base_addr, hba->ucdl_dma_addr);
>   	}
>   }
> @@ -724,7 +714,7 @@ 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->pdev->dev,
> +	hba->ucdl_base_addr = dma_alloc_coherent(hba->dev,
>   						 ucdl_size,
>   						 &hba->ucdl_dma_addr,
>   						 GFP_KERNEL);
> @@ -737,7 +727,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>   	 */
>   	if (!hba->ucdl_base_addr ||
>   	    WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) {
> -		dev_err(&hba->pdev->dev,
> +		dev_err(hba->dev,
>   			"Command Descriptor Memory allocation failed\n");
>   		goto out;
>   	}
> @@ -747,13 +737,13 @@ 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->pdev->dev,
> +	hba->utrdl_base_addr = dma_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->pdev->dev,
> +		dev_err(hba->dev,
>   			"Transfer Descriptor Memory allocation failed\n");
>   		goto out;
>   	}
> @@ -763,13 +753,13 @@ 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->pdev->dev,
> +	hba->utmrdl_base_addr = dma_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->pdev->dev,
> +		dev_err(hba->dev,
>   		"Task Management Descriptor Memory allocation failed\n");
>   		goto out;
>   	}
> @@ -777,7 +767,7 @@ 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);
>   	if (!hba->lrb) {
> -		dev_err(&hba->pdev->dev, "LRB Memory allocation failed\n");
> +		dev_err(hba->dev, "LRB Memory allocation failed\n");
>   		goto out;
>   	}
>   	return 0;
> @@ -867,7 +857,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
>   	/* check if controller is ready to accept UIC commands */
>   	if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
>   	    UIC_COMMAND_READY) == 0x0) {
> -		dev_err(&hba->pdev->dev,
> +		dev_err(hba->dev,
>   			"Controller not ready"
>   			" to accept UIC commands\n");
>   		return -EIO;
> @@ -912,7 +902,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
>   	/* check if device present */
>   	reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
>   	if (!ufshcd_is_device_present(reg)) {
> -		dev_err(&hba->pdev->dev, "cc: Device not present\n");
> +		dev_err(hba->dev, "cc: Device not present\n");
>   		err = -ENXIO;
>   		goto out;
>   	}
> @@ -924,7 +914,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
>   	if (!(ufshcd_get_lists_status(reg))) {
>   		ufshcd_enable_run_stop_reg(hba);
>   	} else {
> -		dev_err(&hba->pdev->dev,
> +		dev_err(hba->dev,
>   			"Host controller not ready to process requests");
>   		err = -EIO;
>   		goto out;
> @@ -1005,7 +995,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
>   		if (retry) {
>   			retry--;
>   		} else {
> -			dev_err(&hba->pdev->dev,
> +			dev_err(hba->dev,
>   				"Controller enable failed\n");
>   			return -EIO;
>   		}
> @@ -1084,7 +1074,7 @@ static int ufshcd_do_reset(struct ufs_hba *hba)
>   
>   	/* start the initialization process */
>   	if (ufshcd_initialize_hba(hba)) {
> -		dev_err(&hba->pdev->dev,
> +		dev_err(hba->dev,
>   			"Reset: Controller initialization failed\n");
>   		return FAILED;
>   	}
> @@ -1167,7 +1157,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index)
>   			task_result = SUCCESS;
>   	} else {
>   		task_result = FAILED;
> -		dev_err(&hba->pdev->dev,
> +		dev_err(hba->dev,
>   			"trc: Invalid ocs = %x\n", ocs_value);
>   	}
>   	spin_unlock_irqrestore(hba->host->host_lock, flags);
> @@ -1281,7 +1271,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
>   		/* check if the returned transfer response is valid */
>   		result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
>   		if (result) {
> -			dev_err(&hba->pdev->dev,
> +			dev_err(hba->dev,
>   				"Invalid response = %x\n", result);
>   			break;
>   		}
> @@ -1310,7 +1300,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
>   	case OCS_FATAL_ERROR:
>   	default:
>   		result |= DID_ERROR << 16;
> -		dev_err(&hba->pdev->dev,
> +		dev_err(hba->dev,
>   		"OCS error from controller = %x\n", ocs);
>   		break;
>   	} /* end of switch */
> @@ -1374,7 +1364,7 @@ static void ufshcd_uic_cc_handler (struct work_struct *work)
>   	    !(ufshcd_get_uic_cmd_result(hba))) {
>   
>   		if (ufshcd_make_hba_operational(hba))
> -			dev_err(&hba->pdev->dev,
> +			dev_err(hba->dev,
>   				"cc: hba not operational state\n");
>   		return;
>   	}
> @@ -1509,7 +1499,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
>   	free_slot = ufshcd_get_tm_free_slot(hba);
>   	if (free_slot >= hba->nutmrs) {
>   		spin_unlock_irqrestore(host->host_lock, flags);
> -		dev_err(&hba->pdev->dev, "Task management queue full\n");
> +		dev_err(hba->dev, "Task management queue full\n");
>   		err = FAILED;
>   		goto out;
>   	}
> @@ -1552,7 +1542,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
>   					 &hba->tm_condition) != 0),
>   					 60 * HZ);
>   	if (!err) {
> -		dev_err(&hba->pdev->dev,
> +		dev_err(hba->dev,
>   			"Task management command timed-out\n");
>   		err = FAILED;
>   		goto out;
> @@ -1688,23 +1678,22 @@ static struct scsi_host_template ufshcd_driver_template = {
>   };
>   
>   /**
> - * ufshcd_shutdown - main function to put the controller in reset state
> + * ufshcd_pci_shutdown - main function to put the controller in reset state
>    * @pdev: pointer to PCI device handle
>    */
> -static void ufshcd_shutdown(struct pci_dev *pdev)
> +static void ufshcd_pci_shutdown(struct pci_dev *pdev)
>   {
>   	ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
>   }
>   
> -#ifdef CONFIG_PM
>   /**
>    * ufshcd_suspend - suspend power management function
> - * @pdev: pointer to PCI device handle
> + * @hba: per adapter instance
>    * @state: power state
>    *
>    * Returns -ENOSYS
>    */
> -static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
> +int ufshcd_suspend(struct ufs_hba *hba, pm_message_t state)
>   {
>   	/*
>   	 * TODO:
> @@ -1717,14 +1706,15 @@ static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
>   
>   	return -ENOSYS;
>   }
> +EXPORT_SYMBOL_GPL(ufshcd_suspend);
>   
>   /**
>    * ufshcd_resume - resume power management function
> - * @pdev: pointer to PCI device handle
> + * @hba: per adapter instance
>    *
>    * Returns -ENOSYS
>    */
> -static int ufshcd_resume(struct pci_dev *pdev)
> +int ufshcd_resume(struct ufs_hba *hba)
>   {
>   	/*
>   	 * TODO:
> @@ -1737,6 +1727,43 @@ static int ufshcd_resume(struct pci_dev *pdev)
>   
>   	return -ENOSYS;
>   }
> +EXPORT_SYMBOL_GPL(ufshcd_resume);
> +
> +#ifdef CONFIG_PM
> +/**
> + * ufshcd_pci_suspend - suspend power management function
> + * @pdev: pointer to PCI device handle
> + * @state: power state
> + *
> + * Returns -ENOSYS
> + */
> +static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
> +{
> +	/*
> +	 * TODO:
> +	 * 1. Call ufshcd_suspend
> +	 * 2. Do bus specific power management
> +	 */
> +
> +	return -ENOSYS;
> +}
> +
> +/**
> + * ufshcd_pci_resume - resume power management function
> + * @pdev: pointer to PCI device handle
> + *
> + * Returns -ENOSYS
> + */
> +static int ufshcd_pci_resume(struct pci_dev *pdev)
> +{
> +	/*
> +	 * TODO:
> +	 * 1. Call ufshcd_resume.
Full stop can be removed to be consistant with other comments in this file.
> +	 * 2. Do bus specific wake up
> +	 */
> +
> +	return -ENOSYS;
> +}
>   #endif /* CONFIG_PM */
>   
>   /**
> @@ -1748,27 +1775,38 @@ static void ufshcd_hba_free(struct ufs_hba *hba)
>   {
>   	iounmap(hba->mmio_base);
>   	ufshcd_free_hba_memory(hba);
> -	pci_release_regions(hba->pdev);
>   }
>   
>   /**
> - * ufshcd_remove - de-allocate PCI/SCSI host and host memory space
> + * ufshcd_remove - de-allocate SCSI host and host memory space
>    *		data structure memory
> - * @pdev - pointer to PCI handle
> + * @hba - per adapter instance
>    */
> -static void ufshcd_remove(struct pci_dev *pdev)
> +void ufshcd_remove(struct ufs_hba *hba)
>   {
> -	struct ufs_hba *hba = pci_get_drvdata(pdev);
> -
>   	/* disable interrupts */
>   	ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
> -	free_irq(pdev->irq, hba);
>   
>   	ufshcd_hba_stop(hba);
>   	ufshcd_hba_free(hba);
>   
>   	scsi_remove_host(hba->host);
>   	scsi_host_put(hba->host);
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_remove);
> +
> +/**
> + * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
> + *		data structure memory
> + * @pdev - pointer to PCI handle
> + */
> +static void ufshcd_pci_remove(struct pci_dev *pdev)
> +{
> +	struct ufs_hba *hba = pci_get_drvdata(pdev);
> +
> +	free_irq(pdev->irq, hba);
> +	ufshcd_remove(hba);
> +	pci_release_regions(pdev);
>   	pci_set_drvdata(pdev, NULL);
>   	pci_clear_master(pdev);
>   	pci_disable_device(pdev);
> @@ -1781,75 +1819,52 @@ static void ufshcd_remove(struct pci_dev *pdev)
>    *
>    * Returns 0 for success, non-zero for failure
>    */
> -static int ufshcd_set_dma_mask(struct ufs_hba *hba)
> +static int ufshcd_set_dma_mask(struct pci_dev *pdev)
>   {
>   	int err;
> -	u64 dma_mask;
> -
> -	/*
> -	 * If controller supports 64 bit addressing mode, then set the DMA
> -	 * mask to 64-bit, else set the DMA mask to 32-bit
> -	 */
> -	if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT)
> -		dma_mask = DMA_BIT_MASK(64);
> -	else
> -		dma_mask = DMA_BIT_MASK(32);
> -
> -	err = pci_set_dma_mask(hba->pdev, dma_mask);
> -	if (err)
> -		return err;
> -
> -	err = pci_set_consistent_dma_mask(hba->pdev, dma_mask);
>   
> +	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_probe - probe routine of the driver
> - * @pdev: pointer to PCI device handle
> - * @id: PCI device id
> - *
> + * ufshcd_init - Driver initialization routine
> + * @dev: pointer to device handle
> + * @hba_handle: driver private handle
> + * @mmio_base: base register address
> + * @irq_line: Interrupt line of device
>    * Returns 0 on success, non-zero value on failure
>    */
> -static int __devinit
> -ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
> +		 void __iomem *mmio_base, unsigned int irq_line)
Just irq should be enough: s/irq_line/irq
>   {
>   	struct Scsi_Host *host;
>   	struct ufs_hba *hba;
>   	int err;
>   
> -	err = pci_enable_device(pdev);
> -	if (err) {
> -		dev_err(&pdev->dev, "pci_enable_device failed\n");
> +	if (!dev && !mmio_base) {
> +		dev_err(dev,
> +		"Invalid memory reference for dev or mmio_base NULL\n");
Better to have "!dev" and "!mmio_base" seperate to print out exact error.

> +		err = -ENODEV;
>   		goto out_error;
>   	}
>   
> -	pci_set_master(pdev);
> -
>   	host = scsi_host_alloc(&ufshcd_driver_template,
>   				sizeof(struct ufs_hba));
>   	if (!host) {
> -		dev_err(&pdev->dev, "scsi_host_alloc failed\n");
> +		dev_err(dev, "scsi_host_alloc failed\n");
>   		err = -ENOMEM;
> -		goto out_disable;
> +		goto out_error;
>   	}
>   	hba = shost_priv(host);
> -
> -	err = pci_request_regions(pdev, UFSHCD);
> -	if (err < 0) {
> -		dev_err(&pdev->dev, "request regions failed\n");
> -		goto out_host_put;
> -	}
> -
> -	hba->mmio_base = pci_ioremap_bar(pdev, 0);
> -	if (!hba->mmio_base) {
> -		dev_err(&pdev->dev, "memory map failed\n");
> -		err = -ENOMEM;
> -		goto out_release_regions;
> -	}
> -
>   	hba->host = host;
> -	hba->pdev = pdev;
> +	hba->dev = dev;
> +	hba->mmio_base = mmio_base;
>   
>   	/* Read capabilities registers */
>   	ufshcd_hba_capabilities(hba);
> @@ -1857,17 +1872,11 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>   	/* Get UFS version supported by the controller */
>   	hba->ufs_version = ufshcd_get_ufs_version(hba);
>   
> -	err = ufshcd_set_dma_mask(hba);
> -	if (err) {
> -		dev_err(&pdev->dev, "set dma mask failed\n");
> -		goto out_iounmap;
> -	}
> -
>   	/* Allocate memory for host memory space */
>   	err = ufshcd_memory_alloc(hba);
>   	if (err) {
> -		dev_err(&pdev->dev, "Memory allocation failed\n");
> -		goto out_iounmap;
> +		dev_err(hba->dev, "Memory allocation failed\n");
> +		goto out_disable;
>   	}
>   
>   	/* Configure LRB */
> @@ -1889,46 +1898,104 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>   	INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
>   
>   	/* IRQ registration */
> -	err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
> +	err = request_irq(irq_line, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
irq flags is set to IRQF_SHARED. Not sure why? Is there any specific 
reason? I don't see any shared interrupt handler for same irq line here?

Here irq name is "UFSHCD" but say if we more than 1 instances of the UFS 
controllers on same chipset then it would have seperate irq numbers as 
well so to differnentiate them uniquely (when we do "cat 
/proc/interrupts"), it's better to name the irq uniquely for each 
instances of UFS controllers.

>   	if (err) {
> -		dev_err(&pdev->dev, "request irq failed\n");
> +		dev_err(hba->dev, "request irq failed\n");
>   		goto out_lrb_free;
>   	}
>   
>   	/* Enable SCSI tag mapping */
>   	err = scsi_init_shared_tag_map(host, host->can_queue);
>   	if (err) {
> -		dev_err(&pdev->dev, "init shared queue failed\n");
> +		dev_err(hba->dev, "init shared queue failed\n");
>   		goto out_free_irq;
>   	}
>   
> -	pci_set_drvdata(pdev, hba);
> -
> -	err = scsi_add_host(host, &pdev->dev);
> +	err = scsi_add_host(host, hba->dev);
>   	if (err) {
> -		dev_err(&pdev->dev, "scsi_add_host failed\n");
> +		dev_err(hba->dev, "scsi_add_host failed\n");
>   		goto out_free_irq;
>   	}
>   
>   	/* Initialization routine */
>   	err = ufshcd_initialize_hba(hba);
>   	if (err) {
> -		dev_err(&pdev->dev, "Initialization failed\n");
> -		goto out_free_irq;
> +		dev_err(hba->dev, "Initialization failed\n");
> +		goto out_remove_scsi_host;
>   	}
> +	*hba_handle = hba;
>   
>   	return 0;
>   
> +out_remove_scsi_host:
> +	scsi_remove_host(hba->host);
>   out_free_irq:
> -	free_irq(pdev->irq, hba);
> +	free_irq(irq_line, hba);
>   out_lrb_free:
>   	ufshcd_free_hba_memory(hba);
> +out_disable:
> +	scsi_host_put(host);
> +out_error:
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_init);
> +
> +/**
> + * ufshcd_pci_probe - probe routine of the driver
> + * @pdev: pointer to PCI device handle
> + * @id: PCI device id
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +static int __devinit
> +ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +{
> +	struct ufs_hba *hba;
> +	void __iomem *mmio_base;
> +	int err;
> +
> +	err = pci_enable_device(pdev);
> +	if (err) {
> +		dev_err(&pdev->dev, "pci_enable_device failed\n");
> +		goto out_error;
> +	}
> +
> +	pci_set_master(pdev);
> +
> +	err = pci_request_regions(pdev, UFSHCD);
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "request regions failed\n");
> +		goto out_disable;
> +	}
> +
> +	mmio_base = pci_ioremap_bar(pdev, 0);
> +	if (!mmio_base) {
> +		dev_err(&pdev->dev, "memory map failed\n");
> +		err = -ENOMEM;
> +		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, "%s:%d %sInitialization failed\n",
> +				__FILE__, __LINE__, __func__);
> +		goto out_iounmap;
> +	}
> +
> +	pci_set_drvdata(pdev, hba);
> +
> +	return 0;
> +
>   out_iounmap:
> -	iounmap(hba->mmio_base);
> +	iounmap(mmio_base);
>   out_release_regions:
>   	pci_release_regions(pdev);
> -out_host_put:
> -	scsi_host_put(host);
>   out_disable:
>   	pci_clear_master(pdev);
>   	pci_disable_device(pdev);
> @@ -1946,19 +2013,19 @@ MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
>   static struct pci_driver ufshcd_pci_driver = {
>   	.name = UFSHCD,
>   	.id_table = ufshcd_pci_tbl,
> -	.probe = ufshcd_probe,
> -	.remove = __devexit_p(ufshcd_remove),
> -	.shutdown = ufshcd_shutdown,
> +	.probe = ufshcd_pci_probe,
> +	.remove = __devexit_p(ufshcd_pci_remove),
> +	.shutdown = ufshcd_pci_shutdown,
>   #ifdef CONFIG_PM
> -	.suspend = ufshcd_suspend,
> -	.resume = ufshcd_resume,
> +	.suspend = ufshcd_pci_suspend,
> +	.resume = ufshcd_pci_resume,
>   #endif
>   };
>   
>   module_pci_driver(ufshcd_pci_driver);
>   
> -MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, "
> -	      "Vinayak Holikatti <h.vinayak@samsung.com>");
> +MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
> +MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
>   MODULE_DESCRIPTION("Generic UFS host controller driver");
>   MODULE_LICENSE("GPL");
>   MODULE_VERSION(UFSHCD_DRIVER_VERSION);
> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
> index 6e3510f..1cc1e00 100644
> --- a/drivers/scsi/ufs/ufshci.h
> +++ b/drivers/scsi/ufs/ufshci.h
> @@ -4,43 +4,33 @@
>    * This code is based on drivers/scsi/ufs/ufshci.h
>    * Copyright (C) 2011-2012 Samsung India Software Operations
>    *
> - * Santosh Yaraganavi <santosh.sy@samsung.com>
> - * Vinayak Holikatti <h.vinayak@samsung.com>
> + * Authors:
> + *	Santosh Yaraganavi <santosh.sy@samsung.com>
> + *	Vinayak Holikatti <h.vinayak@samsung.com>
>    *
>    * 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.
> + * See the COPYING file in the top-level directory or visit
> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>    *
>    * This program is distributed in the hope that it will be useful,
>    * but WITHOUT ANY WARRANTY; without even the implied warranty of
>    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>    * GNU General Public License for more details.
>    *
> - * NO WARRANTY
> - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
> - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
> - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
> - * solely responsible for determining the appropriateness of using and
> - * distributing the Program and assumes all risks associated with its
> - * exercise of rights under this Agreement, including but not limited to
> - * the risks and costs of program errors, damage to or loss of data,
> - * programs or equipment, and unavailability or interruption of operations.
> -
> - * DISCLAIMER OF LIABILITY
> - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
> - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
> - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
> - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
> -
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
> - * USA.
> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
> + * without warranty of any kind. You are solely responsible for
> + * determining the appropriateness of using and distributing
> + * the program and assume all risks associated with your exercise
> + * of rights with respect to the program, including but not limited
> + * to infringement of third party rights, the risks and costs of
> + * program errors, damage to or loss of data, programs or equipment,
> + * and unavailability or interruption of operations. Under no
> + * circumstances will the contributor of this Program be liable for
> + * any damages of any kind arising from your use or distribution of
> + * this program.
>    */
>   
>   #ifndef _UFSHCI_H


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

* Re: [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd
  2012-12-26 20:15 ` [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd vinholikatti
@ 2012-12-27 14:58   ` Subhash Jadavani
  2013-01-04  7:37     ` vinayak holikatti
  0 siblings, 1 reply; 16+ messages in thread
From: Subhash Jadavani @ 2012-12-27 14:58 UTC (permalink / raw)
  To: vinholikatti; +Cc: james.bottomley, linux-scsi, santoshsy

On 12/27/2012 1:45 AM, vinholikatti@gmail.com wrote:
> From: Vinayak Holikatti <vinholikatti@gmail.com>
>
> This patch adds Platform glue driver for ufshcd.
>
> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
> Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
> Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
> ---
>   drivers/scsi/ufs/Kconfig         |   11 ++
>   drivers/scsi/ufs/Makefile        |    1 +
>   drivers/scsi/ufs/ufshcd-pltfrm.c |  205 ++++++++++++++++++++++++++++++++++++++
>   3 files changed, 217 insertions(+), 0 deletions(-)
>   create mode 100644 drivers/scsi/ufs/ufshcd-pltfrm.c
>
> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
> index d77ae97..96e1721 100644
> --- a/drivers/scsi/ufs/Kconfig
> +++ b/drivers/scsi/ufs/Kconfig
> @@ -57,3 +57,14 @@ config SCSI_UFSHCD_PCI
>   	  If you have a controller with this interface, say Y or M here.
>   
>   	  If unsure, say N.
> +
> +config SCSI_UFSHCD_PLATFORM
> +	tristate "Platform based UFS Controller support"
This may sound more explicit: s/"Platform based"/"Platform bus based"
> +	depends on SCSI_UFSHCD
> +	---help---
> +	This selects the UFS host controller support. If you have a
> +	   platform with UFS controller, say Y or M here.
s/"If you have a platform with UFS controller,"/"If you have UFS 
controller on platform bus,"
> +
> +	   If you have a controller with this interface, say Y or M here.
Why do we need this line? we already one comment above.
> +
> +	  If unsure, say N.
> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> index 9eda0df..1e5bd48 100644
> --- a/drivers/scsi/ufs/Makefile
> +++ b/drivers/scsi/ufs/Makefile
> @@ -1,3 +1,4 @@
>   # UFSHCD makefile
>   obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
>   obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> +obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
> diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
> new file mode 100644
> index 0000000..94acfdc
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
> @@ -0,0 +1,205 @@
> +/*
> + * Universal Flash Storage Host controller driver
Please add some comment to indicate that this is platform bus UFS host 
controller driver.
> + *
> + * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
> + * Copyright (C) 2011-2012 Samsung India Software Operations
> + *
> + * Authors:
> + *	Santosh Yaraganavi <santosh.sy@samsung.com>
> + *	Vinayak Holikatti <h.vinayak@samsung.com>
> + *
> + * 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.
> + * See the COPYING file in the top-level directory or visit
> + * <http://www.gnu.org/licenses/gpl-2.0.html>
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
> + * without warranty of any kind. You are solely responsible for
> + * determining the appropriateness of using and distributing
> + * the program and assume all risks associated with your exercise
> + * of rights with respect to the program, including but not limited
> + * to infringement of third party rights, the risks and costs of
> + * program errors, damage to or loss of data, programs or equipment,
> + * and unavailability or interruption of operations. Under no
> + * circumstances will the contributor of this Program be liable for
> + * any damages of any kind arising from your use or distribution of
> + * this program.
> + */
> +
> +#include "ufshcd.h"
> +#include <linux/platform_device.h>
> +
> +#ifdef CONFIG_PM
> +/**
> + * ufshcd_pltfrm_suspend - suspend power management function
> + * @pdev: pointer to Platform device handle
> + * @mesg: power state
> + *
> + * Returns -ENOSYS
> + */
> +static int ufshcd_pltfrm_suspend(struct platform_device *pdev,
> +				 pm_message_t mesg)
> +{
> +	/*
> +	 * TODO:
> +	 * 1. Call ufshcd_suspend
> +	 * 2. Do bus specific power management
> +	 */
> +
> +	return -ENOSYS;
> +}
> +
> +/**
> + * ufshcd_pltfrm_resume - resume power management function
> + * @pdev: pointer to Platform device handle
> + *
> + * Returns -ENOSYS
> + */
> +static int ufshcd_pltfrm_resume(struct platform_device *pdev)
> +{
> +	/*
> +	 * TODO:
> +	 * 1. Call ufshcd_resume.
> +	 * 2. Do bus specific wake up
> +	 */
> +
> +	return -ENOSYS;
> +}
> +#endif
> +
> +/**
> + * ufshcd_pltfrm_probe - probe routine of the driver
> + * @pdev: pointer to Platform device handle
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +static int __devinit
> +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;
> +	struct device *dev = &pdev->dev;
> +
> +	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem_res) {
> +		dev_err(&pdev->dev,
> +			"%s: Memory resource not available\n", __FILE__);
Why would we print the file name? Won't the device name prefix enough in 
debug message?
> +		err = -ENODEV;
> +		goto out_error;
> +	}
> +
> +	mem_size = resource_size(mem_res);
> +	if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
you may want to use the UFSHCD macro:   s/"ufshcd"/UFSHCD

> +		dev_err(&pdev->dev,
> +			"ufshcd: Cannot reserve the memory resource\n");

"ufshcd:" prefix may not be required here as the device name prefix 
should be enough to know the context of the error.
> +		err = -EBUSY;
> +		goto out_error;
> +	}
> +
> +	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, "ufshcd: IRQ resource not available\n");

Same as above. "ufshcd:" prefix may not be required here as the device 
name prefix should be enough to know the context of the error.

> +		err = -ENODEV;
> +		goto out_iounmap;
> +	}
> +
> +	err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
> +	if (err) {
> +		dev_err(&pdev->dev, "set dma mask failed\n");
> +		goto out_iounmap;
> +	}
> +
> +	err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
> +	if (err) {
> +		dev_err(&pdev->dev, "%s: Intialization failed\n",
> +			__FILE__);

Again, not sure why we would need to prefix the file name here.

> +		goto out_iounmap;
> +	}
> +
> +	platform_set_drvdata(pdev, hba);
> +
> +	return 0;
> +
> +out_iounmap:
> +	iounmap(mmio_base);
> +out_release_regions:
> +	release_mem_region(mem_res->start, mem_size);
> +out_error:
> +	return err;
> +}
> +
> +/**
> + * ufshcd_pltfrm_remove - remove platform driver routine
> + * @pdev: pointer to platform device handle
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +static int __devexit ufshcd_pltfrm_remove(struct platform_device *pdev)
> +{
> +	struct resource *mem_res;
> +	struct resource *irq_res;
> +	resource_size_t mem_size;
> +	struct ufs_hba *hba =  platform_get_drvdata(pdev);
> +
> +	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
It would be better to save the irq number under "struct ufs_hba" during 
probe. So here during remove you just need simply need to call the 
"free_irq(irq_res->start, hba)"
> +
> +	if (!irq_res)
> +		dev_err(&pdev->dev, "ufshcd: IRQ resource not available\n");
> +	else
> +		free_irq(irq_res->start, hba);
> +
> +	ufshcd_remove(hba);
Remove should be exactly opposite of probe(). So shouldn't you call the 
ufshcd_remove() first and then free_irq() after that.
> +	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
You might want to save the pointer to mem_res in "struct ufs_hba" during 
probe and may use the same here.
> +	if (!mem_res)
> +		dev_err(&pdev->dev, "ufshcd: Memory resource not available\n");
> +	else {
> +		mem_size = resource_size(mem_res);
> +		release_mem_region(mem_res->start, mem_size);
> +	}
> +	platform_set_drvdata(pdev, NULL);
> +	return 0;
> +}
> +
> +static const struct of_device_id ufs_of_match[] = {
> +	{ .compatible = "jedec,ufs-1.1"},
> +};
> +
> +static struct platform_driver ufshcd_pltfrm_driver = {
> +	.probe	= ufshcd_pltfrm_probe,
> +	.remove	= __devexit_p(ufshcd_pltfrm_remove),
> +#ifdef CONFIG_PM
> +	.suspend = ufshcd_pltfrm_suspend,
> +	.resume = ufshcd_pltfrm_resume,
> +#endif
> +	.driver	= {
> +		.name	= "ufshcd",
> +		.owner	= THIS_MODULE,
> +		.of_match_table = ufs_of_match,
> +	},
> +};
> +
> +module_platform_driver(ufshcd_pltfrm_driver);
> +
> +MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
> +MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
> +MODULE_DESCRIPTION("Platform based UFS host controller driver");

s/"Platform based"/"Platform Bus based"

> +MODULE_LICENSE("GPL");
> +MODULE_VERSION(UFSHCD_DRIVER_VERSION);
You want to keep the same driver version as the UFS core driver?


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

* Re: [PATCH V5 2/4] [SCSI] drivers/scsi/ufs: Separate PCI code into glue driver
  2012-12-26 20:15 ` [PATCH V5 2/4] [SCSI] drivers/scsi/ufs: Separate PCI code into glue driver vinholikatti
@ 2012-12-27 15:05   ` Subhash Jadavani
  0 siblings, 0 replies; 16+ messages in thread
From: Subhash Jadavani @ 2012-12-27 15:05 UTC (permalink / raw)
  To: vinholikatti; +Cc: james.bottomley, linux-scsi, santoshsy

On 12/27/2012 1:45 AM, vinholikatti@gmail.com wrote:
> From: Vinayak Holikatti <vinholikatti@gmail.com>
>
> This patch separates PCI code from ufshcd.c and makes it as a
> core driver module and adds a new file ufshcd-pci.c as PCI glue
> driver.
>
> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
> Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
> Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
> ---
>   drivers/scsi/ufs/Kconfig      |   26 +++-
>   drivers/scsi/ufs/Makefile     |    1 +
>   drivers/scsi/ufs/ufshcd-pci.c |  211 +++++++++++++++++++++++++++
>   drivers/scsi/ufs/ufshcd.c     |  323 +----------------------------------------
>   drivers/scsi/ufs/ufshcd.h     |  200 +++++++++++++++++++++++++
>   5 files changed, 437 insertions(+), 324 deletions(-)
>   create mode 100644 drivers/scsi/ufs/ufshcd-pci.c
>   create mode 100644 drivers/scsi/ufs/ufshcd.h
>
> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
> index 9c84569..d77ae97 100644
> --- a/drivers/scsi/ufs/Kconfig
> +++ b/drivers/scsi/ufs/Kconfig
> @@ -33,7 +33,27 @@
>   # this program.
>   
>   config SCSI_UFSHCD
> -	tristate "Universal Flash Storage host controller driver"
> -	depends on PCI && SCSI
> +	tristate "Universal Flash Storage Controller Driver Core"
> +	depends on SCSI
>   	---help---
> -	This is a generic driver which supports PCIe UFS Host controllers.
> +	This selects the support for UFS devices in Linux, say Y and make
> +	  sure that you know the name of your UFS host adapter (the card
> +	  inside your computer that "speaks" the UFS protocol, also
> +	  called UFS Host Controller), because you will be asked for it.
> +	  The module will be called ufshcd.
> +
> +	  To compile this driver as a module, choose M here and read
> +	  <file:Documentation/scsi/ufs.txt>.
> +	  However, do not compile this as a module if your root file system
> +	  (the one containing the directory /) is located on a UFS device.
> +
> +config SCSI_UFSHCD_PCI
> +	tristate "PCI bus based UFS Controller support"
> +	depends on SCSI_UFSHCD && PCI
> +	---help---
> +	This selects the PCI UFS Host Controller Interface.
> +	  Most controllers found today are PCI devices.
It would be better to remove this line "Most controllers found today are 
PCI devices" from here.
> +
> +	  If you have a controller with this interface, say Y or M here.
> +
> +	  If unsure, say N.
> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> index adf7895..9eda0df 100644
> --- a/drivers/scsi/ufs/Makefile
> +++ b/drivers/scsi/ufs/Makefile
> @@ -1,2 +1,3 @@
>   # UFSHCD makefile
>   obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
> +obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
> new file mode 100644
> index 0000000..ba86b5e
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufshcd-pci.c
> @@ -0,0 +1,211 @@
> +/*
> + * Universal Flash Storage Host controller driver
You may want to specify PCI somewhere in above comment line.
> + *
> + * This code is based on drivers/scsi/ufs/ufshcd-pci.c
> + * Copyright (C) 2011-2012 Samsung India Software Operations
> + *
> + * Authors:
> + *	Santosh Yaraganavi <santosh.sy@samsung.com>
> + *	Vinayak Holikatti <h.vinayak@samsung.com>
> + *
> + * 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.
> + * See the COPYING file in the top-level directory or visit
> + * <http://www.gnu.org/licenses/gpl-2.0.html>
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
> + * without warranty of any kind. You are solely responsible for
> + * determining the appropriateness of using and distributing
> + * the program and assume all risks associated with your exercise
> + * of rights with respect to the program, including but not limited
> + * to infringement of third party rights, the risks and costs of
> + * program errors, damage to or loss of data, programs or equipment,
> + * and unavailability or interruption of operations. Under no
> + * circumstances will the contributor of this Program be liable for
> + * any damages of any kind arising from your use or distribution of
> + * this program.
> + */
> +
> +#include "ufshcd.h"
> +#include <linux/pci.h>
> +
> +#ifdef CONFIG_PM
> +/**
> + * ufshcd_pci_suspend - suspend power management function
> + * @pdev: pointer to PCI device handle
> + * @state: power state
> + *
> + * Returns -ENOSYS
> + */
> +static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
> +{
> +	/*
> +	 * TODO:
> +	 * 1. Call ufshcd_suspend
> +	 * 2. Do bus specific power management
> +	 */
> +
> +	return -ENOSYS;
> +}
> +
> +/**
> + * ufshcd_pci_resume - resume power management function
> + * @pdev: pointer to PCI device handle
> + *
> + * Returns -ENOSYS
> + */
> +static int ufshcd_pci_resume(struct pci_dev *pdev)
> +{
> +	/*
> +	 * TODO:
> +	 * 1. Call ufshcd_resume.
> +	 * 2. Do bus specific wake up
> +	 */
> +
> +	return -ENOSYS;
> +}
> +#endif /* CONFIG_PM */
> +
> +/**
> + * ufshcd_pci_shutdown - main function to put the controller in reset state
> + * @pdev: pointer to PCI device handle
> + */
> +static void ufshcd_pci_shutdown(struct pci_dev *pdev)
> +{
> +	ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
> +}
> +
> +/**
> + * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
> + *		data structure memory
> + * @pdev - pointer to PCI handle
> + */
> +static void ufshcd_pci_remove(struct pci_dev *pdev)
> +{
> +	struct ufs_hba *hba = pci_get_drvdata(pdev);
> +
> +	free_irq(pdev->irq, hba);
> +	ufshcd_remove(hba);
> +	pci_release_regions(pdev);
> +	pci_set_drvdata(pdev, NULL);
> +	pci_clear_master(pdev);
> +	pci_disable_device(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
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +static int __devinit
> +ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +{
> +	struct ufs_hba *hba;
> +	void __iomem *mmio_base;
> +	int err;
> +
> +	err = pci_enable_device(pdev);
> +	if (err) {
> +		dev_err(&pdev->dev, "pci_enable_device failed\n");
> +		goto out_error;
> +	}
> +
> +	pci_set_master(pdev);
> +
> +
> +	err = pci_request_regions(pdev, UFSHCD);
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "request regions failed\n");
> +		goto out_disable;
> +	}
> +
> +	mmio_base = pci_ioremap_bar(pdev, 0);
> +	if (!mmio_base) {
> +		dev_err(&pdev->dev, "memory map failed\n");
> +		err = -ENOMEM;
> +		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, "%s:%d %sInitialization failed\n",
> +				__FILE__, __LINE__, __func__);
> +		goto out_iounmap;
> +	}
> +
> +	pci_set_drvdata(pdev, hba);
> +
> +	return 0;
> +
> +out_iounmap:
> +	iounmap(mmio_base);
> +out_release_regions:
> +	pci_release_regions(pdev);
> +out_disable:
> +	pci_clear_master(pdev);
> +	pci_disable_device(pdev);
> +out_error:
> +	return err;
> +}
> +
> +static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
> +	{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> +	{ }	/* terminate list */
> +};
> +
> +MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
> +
> +static struct pci_driver ufshcd_pci_driver = {
> +	.name = UFSHCD,
> +	.id_table = ufshcd_pci_tbl,
> +	.probe = ufshcd_pci_probe,
> +	.remove = __devexit_p(ufshcd_pci_remove),
> +	.shutdown = ufshcd_pci_shutdown,
> +#ifdef CONFIG_PM
> +	.suspend = ufshcd_pci_suspend,
> +	.resume = ufshcd_pci_resume,
> +#endif
> +};
> +
> +module_pci_driver(ufshcd_pci_driver);
> +
> +MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
> +MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
> +MODULE_DESCRIPTION("PCI based UFS host controller driver");
> +MODULE_LICENSE("GPL");
> +MODULE_VERSION(UFSHCD_DRIVER_VERSION);
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 86b5b49..5d2d9e6 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -33,35 +33,7 @@
>    * this program.
>    */
>   
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/init.h>
> -#include <linux/pci.h>
> -#include <linux/interrupt.h>
> -#include <linux/io.h>
> -#include <linux/delay.h>
> -#include <linux/slab.h>
> -#include <linux/spinlock.h>
> -#include <linux/workqueue.h>
> -#include <linux/errno.h>
> -#include <linux/types.h>
> -#include <linux/wait.h>
> -#include <linux/bitops.h>
> -
> -#include <asm/irq.h>
> -#include <asm/byteorder.h>
> -#include <scsi/scsi.h>
> -#include <scsi/scsi_cmnd.h>
> -#include <scsi/scsi_host.h>
> -#include <scsi/scsi_tcq.h>
> -#include <scsi/scsi_dbg.h>
> -#include <scsi/scsi_eh.h>
> -
> -#include "ufs.h"
> -#include "ufshci.h"
> -
> -#define UFSHCD "ufshcd"
> -#define UFSHCD_DRIVER_VERSION "0.1"
> +#include "ufshcd.h"
>   
>   enum {
>   	UFSHCD_MAX_CHANNEL	= 0,
> @@ -92,121 +64,6 @@ enum {
>   };
>   
>   /**
> - * struct uic_command - UIC command structure
> - * @command: UIC command
> - * @argument1: UIC command argument 1
> - * @argument2: UIC command argument 2
> - * @argument3: UIC command argument 3
> - * @cmd_active: Indicate if UIC command is outstanding
> - * @result: UIC command result
> - */
> -struct uic_command {
> -	u32 command;
> -	u32 argument1;
> -	u32 argument2;
> -	u32 argument3;
> -	int cmd_active;
> -	int result;
> -};
> -
> -/**
> - * struct ufs_hba - per adapter private structure
> - * @mmio_base: UFSHCI base register address
> - * @ucdl_base_addr: UFS Command Descriptor base address
> - * @utrdl_base_addr: UTP Transfer Request Descriptor base address
> - * @utmrdl_base_addr: UTP Task Management Descriptor base address
> - * @ucdl_dma_addr: UFS Command Descriptor DMA address
> - * @utrdl_dma_addr: UTRDL DMA address
> - * @utmrdl_dma_addr: UTMRDL DMA address
> - * @host: Scsi_Host instance of the driver
> - * @dev: device handle
> - * @lrb: local reference block
> - * @outstanding_tasks: Bits representing outstanding task requests
> - * @outstanding_reqs: Bits representing outstanding transfer requests
> - * @capabilities: UFS Controller Capabilities
> - * @nutrs: Transfer Request Queue depth supported by controller
> - * @nutmrs: Task Management Queue depth supported by controller
> - * @active_uic_cmd: handle of active UIC command
> - * @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
> - * @uic_workq: Work queue for UIC completion handling
> - * @feh_workq: Work queue for fatal controller error handling
> - * @errors: HBA errors
> - */
> -struct ufs_hba {
> -	void __iomem *mmio_base;
> -
> -	/* Virtual memory reference */
> -	struct utp_transfer_cmd_desc *ucdl_base_addr;
> -	struct utp_transfer_req_desc *utrdl_base_addr;
> -	struct utp_task_req_desc *utmrdl_base_addr;
> -
> -	/* DMA memory reference */
> -	dma_addr_t ucdl_dma_addr;
> -	dma_addr_t utrdl_dma_addr;
> -	dma_addr_t utmrdl_dma_addr;
> -
> -	struct Scsi_Host *host;
> -	struct device *dev;
> -
> -	struct ufshcd_lrb *lrb;
> -
> -	unsigned long outstanding_tasks;
> -	unsigned long outstanding_reqs;
> -
> -	u32 capabilities;
> -	int nutrs;
> -	int nutmrs;
> -	u32 ufs_version;
> -
> -	struct uic_command active_uic_cmd;
> -	wait_queue_head_t ufshcd_tm_wait_queue;
> -	unsigned long tm_condition;
> -
> -	u32 ufshcd_state;
> -	u32 int_enable_mask;
> -
> -	/* Work Queues */
> -	struct work_struct uic_workq;
> -	struct work_struct feh_workq;
> -
> -	/* HBA Errors */
> -	u32 errors;
> -};
> -
> -/**
> - * struct ufshcd_lrb - local reference block
> - * @utr_descriptor_ptr: UTRD address of the command
> - * @ucd_cmd_ptr: UCD address of the command
> - * @ucd_rsp_ptr: Response UPIU address for this command
> - * @ucd_prdt_ptr: PRDT address of the command
> - * @cmd: pointer to SCSI command
> - * @sense_buffer: pointer to sense buffer address of the SCSI command
> - * @sense_bufflen: Length of the sense buffer
> - * @scsi_status: SCSI status of the command
> - * @command_type: SCSI, UFS, Query.
> - * @task_tag: Task tag of the command
> - * @lun: LUN of the command
> - */
> -struct ufshcd_lrb {
> -	struct utp_transfer_req_desc *utr_descriptor_ptr;
> -	struct utp_upiu_cmd *ucd_cmd_ptr;
> -	struct utp_upiu_rsp *ucd_rsp_ptr;
> -	struct ufshcd_sg_entry *ucd_prdt_ptr;
> -
> -	struct scsi_cmnd *cmd;
> -	u8 *sense_buffer;
> -	unsigned int sense_bufflen;
> -	int scsi_status;
> -
> -	int command_type;
> -	int task_tag;
> -	unsigned int lun;
> -};
> -
> -/**
>    * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
>    * @hba - Pointer to adapter instance
>    *
> @@ -419,15 +276,6 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
>   }
>   
>   /**
> - * ufshcd_hba_stop - Send controller to reset state
> - * @hba: per adapter instance
> - */
> -static inline void ufshcd_hba_stop(struct ufs_hba *hba)
> -{
> -	writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
> -}
> -
> -/**
>    * ufshcd_hba_start - Start controller initialization sequence
>    * @hba: per adapter instance
>    */
> @@ -1678,15 +1526,6 @@ static struct scsi_host_template ufshcd_driver_template = {
>   };
>   
>   /**
> - * ufshcd_pci_shutdown - main function to put the controller in reset state
> - * @pdev: pointer to PCI device handle
> - */
> -static void ufshcd_pci_shutdown(struct pci_dev *pdev)
> -{
> -	ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
> -}
> -
> -/**
>    * ufshcd_suspend - suspend power management function
>    * @hba: per adapter instance
>    * @state: power state
> @@ -1729,43 +1568,6 @@ int ufshcd_resume(struct ufs_hba *hba)
>   }
>   EXPORT_SYMBOL_GPL(ufshcd_resume);
>   
> -#ifdef CONFIG_PM
> -/**
> - * ufshcd_pci_suspend - suspend power management function
> - * @pdev: pointer to PCI device handle
> - * @state: power state
> - *
> - * Returns -ENOSYS
> - */
> -static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
> -{
> -	/*
> -	 * TODO:
> -	 * 1. Call ufshcd_suspend
> -	 * 2. Do bus specific power management
> -	 */
> -
> -	return -ENOSYS;
> -}
> -
> -/**
> - * ufshcd_pci_resume - resume power management function
> - * @pdev: pointer to PCI device handle
> - *
> - * Returns -ENOSYS
> - */
> -static int ufshcd_pci_resume(struct pci_dev *pdev)
> -{
> -	/*
> -	 * TODO:
> -	 * 1. Call ufshcd_resume.
> -	 * 2. Do bus specific wake up
> -	 */
> -
> -	return -ENOSYS;
> -}
> -#endif /* CONFIG_PM */
> -
>   /**
>    * ufshcd_hba_free - free allocated memory for
>    *			host memory space data structures
> @@ -1796,43 +1598,6 @@ void ufshcd_remove(struct ufs_hba *hba)
>   EXPORT_SYMBOL_GPL(ufshcd_remove);
>   
>   /**
> - * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
> - *		data structure memory
> - * @pdev - pointer to PCI handle
> - */
> -static void ufshcd_pci_remove(struct pci_dev *pdev)
> -{
> -	struct ufs_hba *hba = pci_get_drvdata(pdev);
> -
> -	free_irq(pdev->irq, hba);
> -	ufshcd_remove(hba);
> -	pci_release_regions(pdev);
> -	pci_set_drvdata(pdev, NULL);
> -	pci_clear_master(pdev);
> -	pci_disable_device(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_init - Driver initialization routine
>    * @dev: pointer to device handle
>    * @hba_handle: driver private handle
> @@ -1940,92 +1705,8 @@ out_error:
>   }
>   EXPORT_SYMBOL_GPL(ufshcd_init);
>   
> -/**
> - * ufshcd_pci_probe - probe routine of the driver
> - * @pdev: pointer to PCI device handle
> - * @id: PCI device id
> - *
> - * Returns 0 on success, non-zero value on failure
> - */
> -static int __devinit
> -ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> -{
> -	struct ufs_hba *hba;
> -	void __iomem *mmio_base;
> -	int err;
> -
> -	err = pci_enable_device(pdev);
> -	if (err) {
> -		dev_err(&pdev->dev, "pci_enable_device failed\n");
> -		goto out_error;
> -	}
> -
> -	pci_set_master(pdev);
> -
> -	err = pci_request_regions(pdev, UFSHCD);
> -	if (err < 0) {
> -		dev_err(&pdev->dev, "request regions failed\n");
> -		goto out_disable;
> -	}
> -
> -	mmio_base = pci_ioremap_bar(pdev, 0);
> -	if (!mmio_base) {
> -		dev_err(&pdev->dev, "memory map failed\n");
> -		err = -ENOMEM;
> -		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, "%s:%d %sInitialization failed\n",
> -				__FILE__, __LINE__, __func__);
> -		goto out_iounmap;
> -	}
> -
> -	pci_set_drvdata(pdev, hba);
> -
> -	return 0;
> -
> -out_iounmap:
> -	iounmap(mmio_base);
> -out_release_regions:
> -	pci_release_regions(pdev);
> -out_disable:
> -	pci_clear_master(pdev);
> -	pci_disable_device(pdev);
> -out_error:
> -	return err;
> -}
> -
> -static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
> -	{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> -	{ }	/* terminate list */
> -};
> -
> -MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
> -
> -static struct pci_driver ufshcd_pci_driver = {
> -	.name = UFSHCD,
> -	.id_table = ufshcd_pci_tbl,
> -	.probe = ufshcd_pci_probe,
> -	.remove = __devexit_p(ufshcd_pci_remove),
> -	.shutdown = ufshcd_pci_shutdown,
> -#ifdef CONFIG_PM
> -	.suspend = ufshcd_pci_suspend,
> -	.resume = ufshcd_pci_resume,
> -#endif
> -};
> -
> -module_pci_driver(ufshcd_pci_driver);
> -
>   MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
>   MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
> -MODULE_DESCRIPTION("Generic UFS host controller driver");
> +MODULE_DESCRIPTION("Generic Core UFS host controller driver");
>   MODULE_LICENSE("GPL");
>   MODULE_VERSION(UFSHCD_DRIVER_VERSION);
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> new file mode 100644
> index 0000000..1829e93
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -0,0 +1,200 @@
> +/*
> + * Universal Flash Storage Host controller driver
Shouldn't it be Universal Flash Storage Controller Driver Core ??
> + *
> + * This code is based on drivers/scsi/ufs/ufshcd.h
> + * Copyright (C) 2011-2012 Samsung India Software Operations
> + *
> + * Authors:
> + *	Santosh Yaraganavi <santosh.sy@samsung.com>
> + *	Vinayak Holikatti <h.vinayak@samsung.com>
> + *
> + * 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.
> + * See the COPYING file in the top-level directory or visit
> + * <http://www.gnu.org/licenses/gpl-2.0.html>
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
> + * without warranty of any kind. You are solely responsible for
> + * determining the appropriateness of using and distributing
> + * the program and assume all risks associated with your exercise
> + * of rights with respect to the program, including but not limited
> + * to infringement of third party rights, the risks and costs of
> + * program errors, damage to or loss of data, programs or equipment,
> + * and unavailability or interruption of operations. Under no
> + * circumstances will the contributor of this Program be liable for
> + * any damages of any kind arising from your use or distribution of
> + * this program.
> + */
> +
> +#ifndef _UFSHCD_H
> +#define _UFSHCD_H
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/workqueue.h>
> +#include <linux/errno.h>
> +#include <linux/types.h>
> +#include <linux/wait.h>
> +#include <linux/bitops.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/clk.h>
> +
> +#include <asm/irq.h>
> +#include <asm/byteorder.h>
> +#include <scsi/scsi.h>
> +#include <scsi/scsi_cmnd.h>
> +#include <scsi/scsi_host.h>
> +#include <scsi/scsi_tcq.h>
> +#include <scsi/scsi_dbg.h>
> +#include <scsi/scsi_eh.h>
> +
> +#include "ufs.h"
> +#include "ufshci.h"
> +
> +#define UFSHCD "ufshcd"
> +#define UFSHCD_DRIVER_VERSION "0.2"
> +
> +/**
> + * struct uic_command - UIC command structure
> + * @command: UIC command
> + * @argument1: UIC command argument 1
> + * @argument2: UIC command argument 2
> + * @argument3: UIC command argument 3
> + * @cmd_active: Indicate if UIC command is outstanding
> + * @result: UIC command result
> + */
> +struct uic_command {
> +	u32 command;
> +	u32 argument1;
> +	u32 argument2;
> +	u32 argument3;
> +	int cmd_active;
> +	int result;
> +};
> +
> +/**
> + * struct ufshcd_lrb - local reference block
> + * @utr_descriptor_ptr: UTRD address of the command
> + * @ucd_cmd_ptr: UCD address of the command
> + * @ucd_rsp_ptr: Response UPIU address for this command
> + * @ucd_prdt_ptr: PRDT address of the command
> + * @cmd: pointer to SCSI command
> + * @sense_buffer: pointer to sense buffer address of the SCSI command
> + * @sense_bufflen: Length of the sense buffer
> + * @scsi_status: SCSI status of the command
> + * @command_type: SCSI, UFS, Query.
> + * @task_tag: Task tag of the command
> + * @lun: LUN of the command
> + */
> +struct ufshcd_lrb {
> +	struct utp_transfer_req_desc *utr_descriptor_ptr;
> +	struct utp_upiu_cmd *ucd_cmd_ptr;
> +	struct utp_upiu_rsp *ucd_rsp_ptr;
> +	struct ufshcd_sg_entry *ucd_prdt_ptr;
> +
> +	struct scsi_cmnd *cmd;
> +	u8 *sense_buffer;
> +	unsigned int sense_bufflen;
> +	int scsi_status;
> +
> +	int command_type;
> +	int task_tag;
> +	unsigned int lun;
> +};
> +
> +
> +/**
> + * struct ufs_hba - per adapter private structure
> + * @mmio_base: UFSHCI base register address
> + * @ucdl_base_addr: UFS Command Descriptor base address
> + * @utrdl_base_addr: UTP Transfer Request Descriptor base address
> + * @utmrdl_base_addr: UTP Task Management Descriptor base address
> + * @ucdl_dma_addr: UFS Command Descriptor DMA address
> + * @utrdl_dma_addr: UTRDL DMA address
> + * @utmrdl_dma_addr: UTMRDL DMA address
> + * @host: Scsi_Host instance of the driver
> + * @dev: device handle
> + * @lrb: local reference block
> + * @outstanding_tasks: Bits representing outstanding task requests
> + * @outstanding_reqs: Bits representing outstanding transfer requests
> + * @capabilities: UFS Controller Capabilities
> + * @nutrs: Transfer Request Queue depth supported by controller
> + * @nutmrs: Task Management Queue depth supported by controller
> + * @active_uic_cmd: handle of active UIC command
> + * @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
> + * @uic_workq: Work queue for UIC completion handling
> + * @feh_workq: Work queue for fatal controller error handling
> + * @errors: HBA errors
> + */
> +struct ufs_hba {
> +	void __iomem *mmio_base;
> +
> +	/* Virtual memory reference */
> +	struct utp_transfer_cmd_desc *ucdl_base_addr;
> +	struct utp_transfer_req_desc *utrdl_base_addr;
> +	struct utp_task_req_desc *utmrdl_base_addr;
> +
> +	/* DMA memory reference */
> +	dma_addr_t ucdl_dma_addr;
> +	dma_addr_t utrdl_dma_addr;
> +	dma_addr_t utmrdl_dma_addr;
> +
> +	struct Scsi_Host *host;
> +	struct device *dev;
> +
> +	struct ufshcd_lrb *lrb;
> +
> +	unsigned long outstanding_tasks;
> +	unsigned long outstanding_reqs;
> +
> +	u32 capabilities;
> +	int nutrs;
> +	int nutmrs;
> +	unsigned int irq;
> +	u32 ufs_version;
> +
> +	struct uic_command active_uic_cmd;
> +	wait_queue_head_t ufshcd_tm_wait_queue;
> +	unsigned long tm_condition;
> +
> +	u32 ufshcd_state;
> +	u32 int_enable_mask;
> +
> +	/* Work Queues */
> +	struct work_struct uic_workq;
> +	struct work_struct feh_workq;
> +
> +	/* HBA Errors */
> +	u32 errors;
> +};
> +
> +int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
> +			unsigned int);
> +void ufshcd_remove(struct ufs_hba *);
> +
> +/**
> + * ufshcd_hba_stop - Send controller to reset state
> + * @hba: per adapter instance
> + */
> +static inline void ufshcd_hba_stop(struct ufs_hba *hba)
> +{
> +	writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
> +}
> +
> +#endif /* End of Header */


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

* Re: [PATCH V5 1/4] [SCSI] drivers/scsi/ufs: Seggregate PCI Specific Code
  2012-12-27 14:29   ` Subhash Jadavani
@ 2013-01-04  7:00     ` vinayak holikatti
  2013-01-06 17:32       ` Subhash Jadavani
  0 siblings, 1 reply; 16+ messages in thread
From: vinayak holikatti @ 2013-01-04  7:00 UTC (permalink / raw)
  To: Subhash Jadavani; +Cc: james.bottomley, linux-scsi, santoshsy

On Thu, Dec 27, 2012 at 7:59 PM, Subhash Jadavani
<subhashj@codeaurora.org> wrote:
>
> Few comments inline:
>
> On 12/27/2012 1:45 AM, vinholikatti@gmail.com wrote:
>>
>> From: Vinayak Holikatti <vinholikatti@gmail.com>
>>
>> This patch seggregates the PCI specific code in ufshcd.c to make it
>> ready for splitting into core ufs driver and PCI glue driver. Also
>> copyright header modification to remove extra warranty disclaim.
>>
>> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
>> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
>> Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
>> Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
>> ---
>>   drivers/scsi/ufs/Kconfig  |   50 +++----
>>   drivers/scsi/ufs/ufs.h    |   42 ++----
>>   drivers/scsi/ufs/ufshcd.c |  339
>> +++++++++++++++++++++++++++------------------
>>   drivers/scsi/ufs/ufshci.h |   42 ++----
>>   4 files changed, 255 insertions(+), 218 deletions(-)
>>
>> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
>> index 8f27f9d..9c84569 100644
>> --- a/drivers/scsi/ufs/Kconfig
>> +++ b/drivers/scsi/ufs/Kconfig
>> @@ -2,45 +2,35 @@
>>   # Kernel configuration file for the UFS Host Controller
>>   #
>>   # This code is based on drivers/scsi/ufs/Kconfig
>> -# Copyright (C) 2011  Samsung Samsung India Software Operations
>> +# Copyright (C) 2011-2012 Samsung India Software Operations
>> +#
>> +# Authors:
>> +#      Santosh Yaraganavi <santosh.sy@samsung.com>
>> +#      Vinayak Holikatti <h.vinayak@samsung.com>
>>   #
>> -# Santosh Yaraganavi <santosh.sy@samsung.com>
>> -# Vinayak Holikatti <h.vinayak@samsung.com>
>> -
>>   # 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.
>> -
>> +# See the COPYING file in the top-level directory or visit
>> +# <http://www.gnu.org/licenses/gpl-2.0.html>
>> +#
>>   # This program is distributed in the hope that it will be useful,
>>   # but WITHOUT ANY WARRANTY; without even the implied warranty of
>>   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>   # GNU General Public License for more details.
>> -
>> -# NO WARRANTY
>> -# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>> -# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>> -# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>> -# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>> -# solely responsible for determining the appropriateness of using and
>> -# distributing the Program and assumes all risks associated with its
>> -# exercise of rights under this Agreement, including but not limited to
>> -# the risks and costs of program errors, damage to or loss of data,
>> -# programs or equipment, and unavailability or interruption of
>> operations.
>> -
>> -# DISCLAIMER OF LIABILITY
>> -# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
>> -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>> -# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
>> -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> -# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>> -# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
>> GRANTED
>> -# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>> -
>> -# You should have received a copy of the GNU General Public License
>> -# along with this program; if not, write to the Free Software
>> -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>> 02110-1301,
>> -# USA.
>> +#
>> +# This program is provided "AS IS" and "WITH ALL FAULTS" and
>> +# without warranty of any kind. You are solely responsible for
>> +# determining the appropriateness of using and distributing
>> +# the program and assume all risks associated with your exercise
>> +# of rights with respect to the program, including but not limited
>> +# to infringement of third party rights, the risks and costs of
>> +# program errors, damage to or loss of data, programs or equipment,
>> +# and unavailability or interruption of operations. Under no
>> +# circumstances will the contributor of this Program be liable for
>> +# any damages of any kind arising from your use or distribution of
>> +# this program.
>>     config SCSI_UFSHCD
>>         tristate "Universal Flash Storage host controller driver"
>> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
>> index b207529..4b3d611 100644
>> --- a/drivers/scsi/ufs/ufs.h
>> +++ b/drivers/scsi/ufs/ufs.h
>> @@ -4,43 +4,33 @@
>>    * This code is based on drivers/scsi/ufs/ufs.h
>>    * Copyright (C) 2011-2012 Samsung India Software Operations
>>    *
>> - * Santosh Yaraganavi <santosh.sy@samsung.com>
>> - * Vinayak Holikatti <h.vinayak@samsung.com>
>> + * Authors:
>> + *     Santosh Yaraganavi <santosh.sy@samsung.com>
>> + *     Vinayak Holikatti <h.vinayak@samsung.com>
>>    *
>>    * 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.
>> + * See the COPYING file in the top-level directory or visit
>> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>>    *
>>    * This program is distributed in the hope that it will be useful,
>>    * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>    * GNU General Public License for more details.
>>    *
>> - * NO WARRANTY
>> - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>> - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>> - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>> - * solely responsible for determining the appropriateness of using and
>> - * distributing the Program and assumes all risks associated with its
>> - * exercise of rights under this Agreement, including but not limited to
>> - * the risks and costs of program errors, damage to or loss of data,
>> - * programs or equipment, and unavailability or interruption of
>> operations.
>> -
>> - * DISCLAIMER OF LIABILITY
>> - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
>> ANY
>> - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>> - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
>> AND
>> - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>> - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
>> GRANTED
>> - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>> -
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program; if not, write to the Free Software
>> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>> 02110-1301,
>> - * USA.
>> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
>> + * without warranty of any kind. You are solely responsible for
>> + * determining the appropriateness of using and distributing
>> + * the program and assume all risks associated with your exercise
>> + * of rights with respect to the program, including but not limited
>> + * to infringement of third party rights, the risks and costs of
>> + * program errors, damage to or loss of data, programs or equipment,
>> + * and unavailability or interruption of operations. Under no
>> + * circumstances will the contributor of this Program be liable for
>> + * any damages of any kind arising from your use or distribution of
>> + * this program.
>>    */
>>     #ifndef _UFS_H
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index 58f4ba6..86b5b49 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -4,43 +4,33 @@
>>    * This code is based on drivers/scsi/ufs/ufshcd.c
>>    * Copyright (C) 2011-2012 Samsung India Software Operations
>>    *
>> - * Santosh Yaraganavi <santosh.sy@samsung.com>
>> - * Vinayak Holikatti <h.vinayak@samsung.com>
>> + * Authors:
>> + *     Santosh Yaraganavi <santosh.sy@samsung.com>
>> + *     Vinayak Holikatti <h.vinayak@samsung.com>
>>    *
>>    * 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.
>> + * See the COPYING file in the top-level directory or visit
>> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>>    *
>>    * This program is distributed in the hope that it will be useful,
>>    * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>    * GNU General Public License for more details.
>>    *
>> - * NO WARRANTY
>> - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>> - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>> - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>> - * solely responsible for determining the appropriateness of using and
>> - * distributing the Program and assumes all risks associated with its
>> - * exercise of rights under this Agreement, including but not limited to
>> - * the risks and costs of program errors, damage to or loss of data,
>> - * programs or equipment, and unavailability or interruption of
>> operations.
>> -
>> - * DISCLAIMER OF LIABILITY
>> - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
>> ANY
>> - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>> - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
>> AND
>> - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>> - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
>> GRANTED
>> - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>> -
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program; if not, write to the Free Software
>> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>> 02110-1301,
>> - * USA.
>> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
>> + * without warranty of any kind. You are solely responsible for
>> + * determining the appropriateness of using and distributing
>> + * the program and assume all risks associated with your exercise
>> + * of rights with respect to the program, including but not limited
>> + * to infringement of third party rights, the risks and costs of
>> + * program errors, damage to or loss of data, programs or equipment,
>> + * and unavailability or interruption of operations. Under no
>> + * circumstances will the contributor of this Program be liable for
>> + * any damages of any kind arising from your use or distribution of
>> + * this program.
>>    */
>>     #include <linux/module.h>
>> @@ -129,7 +119,7 @@ struct uic_command {
>>    * @utrdl_dma_addr: UTRDL DMA address
>>    * @utmrdl_dma_addr: UTMRDL DMA address
>>    * @host: Scsi_Host instance of the driver
>> - * @pdev: PCI device handle
>> + * @dev: device handle
>>    * @lrb: local reference block
>>    * @outstanding_tasks: Bits representing outstanding task requests
>>    * @outstanding_reqs: Bits representing outstanding transfer requests
>> @@ -159,7 +149,7 @@ struct ufs_hba {
>>         dma_addr_t utmrdl_dma_addr;
>>         struct Scsi_Host *host;
>> -       struct pci_dev *pdev;
>> +       struct device *dev;
>>         struct ufshcd_lrb *lrb;
>>   @@ -335,21 +325,21 @@ static inline void ufshcd_free_hba_memory(struct
>> ufs_hba *hba)
>>         if (hba->utmrdl_base_addr) {
>>                 utmrdl_size = sizeof(struct utp_task_req_desc) *
>> hba->nutmrs;
>> -               dma_free_coherent(&hba->pdev->dev, utmrdl_size,
>> +               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->pdev->dev, utrdl_size,
>> +               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->pdev->dev, ucdl_size,
>> +               dma_free_coherent(hba->dev, ucdl_size,
>>                                   hba->ucdl_base_addr,
>> hba->ucdl_dma_addr);
>>         }
>>   }
>> @@ -724,7 +714,7 @@ 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->pdev->dev,
>> +       hba->ucdl_base_addr = dma_alloc_coherent(hba->dev,
>>                                                  ucdl_size,
>>                                                  &hba->ucdl_dma_addr,
>>                                                  GFP_KERNEL);
>> @@ -737,7 +727,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>>          */
>>         if (!hba->ucdl_base_addr ||
>>             WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) {
>> -               dev_err(&hba->pdev->dev,
>> +               dev_err(hba->dev,
>>                         "Command Descriptor Memory allocation failed\n");
>>                 goto out;
>>         }
>> @@ -747,13 +737,13 @@ 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->pdev->dev,
>> +       hba->utrdl_base_addr = dma_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->pdev->dev,
>> +               dev_err(hba->dev,
>>                         "Transfer Descriptor Memory allocation failed\n");
>>                 goto out;
>>         }
>> @@ -763,13 +753,13 @@ 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->pdev->dev,
>> +       hba->utmrdl_base_addr = dma_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->pdev->dev,
>> +               dev_err(hba->dev,
>>                 "Task Management Descriptor Memory allocation failed\n");
>>                 goto out;
>>         }
>> @@ -777,7 +767,7 @@ 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);
>>         if (!hba->lrb) {
>> -               dev_err(&hba->pdev->dev, "LRB Memory allocation
>> failed\n");
>> +               dev_err(hba->dev, "LRB Memory allocation failed\n");
>>                 goto out;
>>         }
>>         return 0;
>> @@ -867,7 +857,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba
>> *hba)
>>         /* check if controller is ready to accept UIC commands */
>>         if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
>>             UIC_COMMAND_READY) == 0x0) {
>> -               dev_err(&hba->pdev->dev,
>> +               dev_err(hba->dev,
>>                         "Controller not ready"
>>                         " to accept UIC commands\n");
>>                 return -EIO;
>> @@ -912,7 +902,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba
>> *hba)
>>         /* check if device present */
>>         reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
>>         if (!ufshcd_is_device_present(reg)) {
>> -               dev_err(&hba->pdev->dev, "cc: Device not present\n");
>> +               dev_err(hba->dev, "cc: Device not present\n");
>>                 err = -ENXIO;
>>                 goto out;
>>         }
>> @@ -924,7 +914,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba
>> *hba)
>>         if (!(ufshcd_get_lists_status(reg))) {
>>                 ufshcd_enable_run_stop_reg(hba);
>>         } else {
>> -               dev_err(&hba->pdev->dev,
>> +               dev_err(hba->dev,
>>                         "Host controller not ready to process requests");
>>                 err = -EIO;
>>                 goto out;
>> @@ -1005,7 +995,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
>>                 if (retry) {
>>                         retry--;
>>                 } else {
>> -                       dev_err(&hba->pdev->dev,
>> +                       dev_err(hba->dev,
>>                                 "Controller enable failed\n");
>>                         return -EIO;
>>                 }
>> @@ -1084,7 +1074,7 @@ static int ufshcd_do_reset(struct ufs_hba *hba)
>>         /* start the initialization process */
>>         if (ufshcd_initialize_hba(hba)) {
>> -               dev_err(&hba->pdev->dev,
>> +               dev_err(hba->dev,
>>                         "Reset: Controller initialization failed\n");
>>                 return FAILED;
>>         }
>> @@ -1167,7 +1157,7 @@ static int ufshcd_task_req_compl(struct ufs_hba
>> *hba, u32 index)
>>                         task_result = SUCCESS;
>>         } else {
>>                 task_result = FAILED;
>> -               dev_err(&hba->pdev->dev,
>> +               dev_err(hba->dev,
>>                         "trc: Invalid ocs = %x\n", ocs_value);
>>         }
>>         spin_unlock_irqrestore(hba->host->host_lock, flags);
>> @@ -1281,7 +1271,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
>> struct ufshcd_lrb *lrbp)
>>                 /* check if the returned transfer response is valid */
>>                 result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
>>                 if (result) {
>> -                       dev_err(&hba->pdev->dev,
>> +                       dev_err(hba->dev,
>>                                 "Invalid response = %x\n", result);
>>                         break;
>>                 }
>> @@ -1310,7 +1300,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
>> struct ufshcd_lrb *lrbp)
>>         case OCS_FATAL_ERROR:
>>         default:
>>                 result |= DID_ERROR << 16;
>> -               dev_err(&hba->pdev->dev,
>> +               dev_err(hba->dev,
>>                 "OCS error from controller = %x\n", ocs);
>>                 break;
>>         } /* end of switch */
>> @@ -1374,7 +1364,7 @@ static void ufshcd_uic_cc_handler (struct
>> work_struct *work)
>>             !(ufshcd_get_uic_cmd_result(hba))) {
>>                 if (ufshcd_make_hba_operational(hba))
>> -                       dev_err(&hba->pdev->dev,
>> +                       dev_err(hba->dev,
>>                                 "cc: hba not operational state\n");
>>                 return;
>>         }
>> @@ -1509,7 +1499,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
>>         free_slot = ufshcd_get_tm_free_slot(hba);
>>         if (free_slot >= hba->nutmrs) {
>>                 spin_unlock_irqrestore(host->host_lock, flags);
>> -               dev_err(&hba->pdev->dev, "Task management queue full\n");
>> +               dev_err(hba->dev, "Task management queue full\n");
>>                 err = FAILED;
>>                 goto out;
>>         }
>> @@ -1552,7 +1542,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
>>                                          &hba->tm_condition) != 0),
>>                                          60 * HZ);
>>         if (!err) {
>> -               dev_err(&hba->pdev->dev,
>> +               dev_err(hba->dev,
>>                         "Task management command timed-out\n");
>>                 err = FAILED;
>>                 goto out;
>> @@ -1688,23 +1678,22 @@ static struct scsi_host_template
>> ufshcd_driver_template = {
>>   };
>>     /**
>> - * ufshcd_shutdown - main function to put the controller in reset state
>> + * ufshcd_pci_shutdown - main function to put the controller in reset
>> state
>>    * @pdev: pointer to PCI device handle
>>    */
>> -static void ufshcd_shutdown(struct pci_dev *pdev)
>> +static void ufshcd_pci_shutdown(struct pci_dev *pdev)
>>   {
>>         ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
>>   }
>>   -#ifdef CONFIG_PM
>>   /**
>>    * ufshcd_suspend - suspend power management function
>> - * @pdev: pointer to PCI device handle
>> + * @hba: per adapter instance
>>    * @state: power state
>>    *
>>    * Returns -ENOSYS
>>    */
>> -static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
>> +int ufshcd_suspend(struct ufs_hba *hba, pm_message_t state)
>>   {
>>         /*
>>          * TODO:
>> @@ -1717,14 +1706,15 @@ static int ufshcd_suspend(struct pci_dev *pdev,
>> pm_message_t state)
>>         return -ENOSYS;
>>   }
>> +EXPORT_SYMBOL_GPL(ufshcd_suspend);
>>     /**
>>    * ufshcd_resume - resume power management function
>> - * @pdev: pointer to PCI device handle
>> + * @hba: per adapter instance
>>    *
>>    * Returns -ENOSYS
>>    */
>> -static int ufshcd_resume(struct pci_dev *pdev)
>> +int ufshcd_resume(struct ufs_hba *hba)
>>   {
>>         /*
>>          * TODO:
>> @@ -1737,6 +1727,43 @@ static int ufshcd_resume(struct pci_dev *pdev)
>>         return -ENOSYS;
>>   }
>> +EXPORT_SYMBOL_GPL(ufshcd_resume);
>> +
>> +#ifdef CONFIG_PM
>> +/**
>> + * ufshcd_pci_suspend - suspend power management function
>> + * @pdev: pointer to PCI device handle
>> + * @state: power state
>> + *
>> + * Returns -ENOSYS
>> + */
>> +static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
>> +{
>> +       /*
>> +        * TODO:
>> +        * 1. Call ufshcd_suspend
>> +        * 2. Do bus specific power management
>> +        */
>> +
>> +       return -ENOSYS;
>> +}
>> +
>> +/**
>> + * ufshcd_pci_resume - resume power management function
>> + * @pdev: pointer to PCI device handle
>> + *
>> + * Returns -ENOSYS
>> + */
>> +static int ufshcd_pci_resume(struct pci_dev *pdev)
>> +{
>> +       /*
>> +        * TODO:
>> +        * 1. Call ufshcd_resume.
>
> Full stop can be removed to be consistant with other comments in this file.
>>
>> +        * 2. Do bus specific wake up
>> +        */
>> +
>> +       return -ENOSYS;
>> +}
>>   #endif /* CONFIG_PM */
>>     /**
>> @@ -1748,27 +1775,38 @@ static void ufshcd_hba_free(struct ufs_hba *hba)
>>   {
>>         iounmap(hba->mmio_base);
>>         ufshcd_free_hba_memory(hba);
>> -       pci_release_regions(hba->pdev);
>>   }
>>     /**
>> - * ufshcd_remove - de-allocate PCI/SCSI host and host memory space
>> + * ufshcd_remove - de-allocate SCSI host and host memory space
>>    *            data structure memory
>> - * @pdev - pointer to PCI handle
>> + * @hba - per adapter instance
>>    */
>> -static void ufshcd_remove(struct pci_dev *pdev)
>> +void ufshcd_remove(struct ufs_hba *hba)
>>   {
>> -       struct ufs_hba *hba = pci_get_drvdata(pdev);
>> -
>>         /* disable interrupts */
>>         ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
>> -       free_irq(pdev->irq, hba);
>>         ufshcd_hba_stop(hba);
>>         ufshcd_hba_free(hba);
>>         scsi_remove_host(hba->host);
>>         scsi_host_put(hba->host);
>> +}
>> +EXPORT_SYMBOL_GPL(ufshcd_remove);
>> +
>> +/**
>> + * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
>> + *             data structure memory
>> + * @pdev - pointer to PCI handle
>> + */
>> +static void ufshcd_pci_remove(struct pci_dev *pdev)
>> +{
>> +       struct ufs_hba *hba = pci_get_drvdata(pdev);
>> +
>> +       free_irq(pdev->irq, hba);
>> +       ufshcd_remove(hba);
>> +       pci_release_regions(pdev);
>>         pci_set_drvdata(pdev, NULL);
>>         pci_clear_master(pdev);
>>         pci_disable_device(pdev);
>> @@ -1781,75 +1819,52 @@ static void ufshcd_remove(struct pci_dev *pdev)
>>    *
>>    * Returns 0 for success, non-zero for failure
>>    */
>> -static int ufshcd_set_dma_mask(struct ufs_hba *hba)
>> +static int ufshcd_set_dma_mask(struct pci_dev *pdev)
>>   {
>>         int err;
>> -       u64 dma_mask;
>> -
>> -       /*
>> -        * If controller supports 64 bit addressing mode, then set the DMA
>> -        * mask to 64-bit, else set the DMA mask to 32-bit
>> -        */
>> -       if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT)
>> -               dma_mask = DMA_BIT_MASK(64);
>> -       else
>> -               dma_mask = DMA_BIT_MASK(32);
>> -
>> -       err = pci_set_dma_mask(hba->pdev, dma_mask);
>> -       if (err)
>> -               return err;
>> -
>> -       err = pci_set_consistent_dma_mask(hba->pdev, dma_mask);
>>   +     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_probe - probe routine of the driver
>> - * @pdev: pointer to PCI device handle
>> - * @id: PCI device id
>> - *
>> + * ufshcd_init - Driver initialization routine
>> + * @dev: pointer to device handle
>> + * @hba_handle: driver private handle
>> + * @mmio_base: base register address
>> + * @irq_line: Interrupt line of device
>>    * Returns 0 on success, non-zero value on failure
>>    */
>> -static int __devinit
>> -ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> +int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
>> +                void __iomem *mmio_base, unsigned int irq_line)
>
> Just irq should be enough: s/irq_line/irq
>>
>>   {
>>         struct Scsi_Host *host;
>>         struct ufs_hba *hba;
>>         int err;
>>   -     err = pci_enable_device(pdev);
>> -       if (err) {
>> -               dev_err(&pdev->dev, "pci_enable_device failed\n");
>> +       if (!dev && !mmio_base) {
>> +               dev_err(dev,
>> +               "Invalid memory reference for dev or mmio_base NULL\n");
>
> Better to have "!dev" and "!mmio_base" seperate to print out exact error.
>
>> +               err = -ENODEV;
>>                 goto out_error;
>>         }
>>   -     pci_set_master(pdev);
>> -
>>         host = scsi_host_alloc(&ufshcd_driver_template,
>>                                 sizeof(struct ufs_hba));
>>         if (!host) {
>> -               dev_err(&pdev->dev, "scsi_host_alloc failed\n");
>> +               dev_err(dev, "scsi_host_alloc failed\n");
>>                 err = -ENOMEM;
>> -               goto out_disable;
>> +               goto out_error;
>>         }
>>         hba = shost_priv(host);
>> -
>> -       err = pci_request_regions(pdev, UFSHCD);
>> -       if (err < 0) {
>> -               dev_err(&pdev->dev, "request regions failed\n");
>> -               goto out_host_put;
>> -       }
>> -
>> -       hba->mmio_base = pci_ioremap_bar(pdev, 0);
>> -       if (!hba->mmio_base) {
>> -               dev_err(&pdev->dev, "memory map failed\n");
>> -               err = -ENOMEM;
>> -               goto out_release_regions;
>> -       }
>> -
>>         hba->host = host;
>> -       hba->pdev = pdev;
>> +       hba->dev = dev;
>> +       hba->mmio_base = mmio_base;
>>         /* Read capabilities registers */
>>         ufshcd_hba_capabilities(hba);
>> @@ -1857,17 +1872,11 @@ ufshcd_probe(struct pci_dev *pdev, const struct
>> pci_device_id *id)
>>         /* Get UFS version supported by the controller */
>>         hba->ufs_version = ufshcd_get_ufs_version(hba);
>>   -     err = ufshcd_set_dma_mask(hba);
>> -       if (err) {
>> -               dev_err(&pdev->dev, "set dma mask failed\n");
>> -               goto out_iounmap;
>> -       }
>> -
>>         /* Allocate memory for host memory space */
>>         err = ufshcd_memory_alloc(hba);
>>         if (err) {
>> -               dev_err(&pdev->dev, "Memory allocation failed\n");
>> -               goto out_iounmap;
>> +               dev_err(hba->dev, "Memory allocation failed\n");
>> +               goto out_disable;
>>         }
>>         /* Configure LRB */
>> @@ -1889,46 +1898,104 @@ ufshcd_probe(struct pci_dev *pdev, const struct
>> pci_device_id *id)
>>         INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
>>         /* IRQ registration */
>> -       err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD,
>> hba);
>> +       err = request_irq(irq_line, ufshcd_intr, IRQF_SHARED, UFSHCD,
>> hba);
>
> irq flags is set to IRQF_SHARED. Not sure why? Is there any specific reason?
> I don't see any shared interrupt handler for same irq line here?
It is generic to be shared. So works well even if interrupt line in not shared.
>
> Here irq name is "UFSHCD" but say if we more than 1 instances of the UFS
> controllers on same chipset then it would have seperate irq numbers as well
> so to differnentiate them uniquely (when we do "cat /proc/interrupts"), it's
> better to name the irq uniquely for each instances of UFS controllers.
the separate irq numbers differentiate different controllers. Do you have
any better way to accomplish it?
>
>>         if (err) {
>> -               dev_err(&pdev->dev, "request irq failed\n");
>> +               dev_err(hba->dev, "request irq failed\n");
>>                 goto out_lrb_free;
>>         }
>>         /* Enable SCSI tag mapping */
>>         err = scsi_init_shared_tag_map(host, host->can_queue);
>>         if (err) {
>> -               dev_err(&pdev->dev, "init shared queue failed\n");
>> +               dev_err(hba->dev, "init shared queue failed\n");
>>                 goto out_free_irq;
>>         }
>>   -     pci_set_drvdata(pdev, hba);
>> -
>> -       err = scsi_add_host(host, &pdev->dev);
>> +       err = scsi_add_host(host, hba->dev);
>>         if (err) {
>> -               dev_err(&pdev->dev, "scsi_add_host failed\n");
>> +               dev_err(hba->dev, "scsi_add_host failed\n");
>>                 goto out_free_irq;
>>         }
>>         /* Initialization routine */
>>         err = ufshcd_initialize_hba(hba);
>>         if (err) {
>> -               dev_err(&pdev->dev, "Initialization failed\n");
>> -               goto out_free_irq;
>> +               dev_err(hba->dev, "Initialization failed\n");
>> +               goto out_remove_scsi_host;
>>         }
>> +       *hba_handle = hba;
>>         return 0;
>>   +out_remove_scsi_host:
>> +       scsi_remove_host(hba->host);
>>   out_free_irq:
>> -       free_irq(pdev->irq, hba);
>> +       free_irq(irq_line, hba);
>>   out_lrb_free:
>>         ufshcd_free_hba_memory(hba);
>> +out_disable:
>> +       scsi_host_put(host);
>> +out_error:
>> +       return err;
>> +}
>> +EXPORT_SYMBOL_GPL(ufshcd_init);
>> +
>> +/**
>> + * ufshcd_pci_probe - probe routine of the driver
>> + * @pdev: pointer to PCI device handle
>> + * @id: PCI device id
>> + *
>> + * Returns 0 on success, non-zero value on failure
>> + */
>> +static int __devinit
>> +ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> +{
>> +       struct ufs_hba *hba;
>> +       void __iomem *mmio_base;
>> +       int err;
>> +
>> +       err = pci_enable_device(pdev);
>> +       if (err) {
>> +               dev_err(&pdev->dev, "pci_enable_device failed\n");
>> +               goto out_error;
>> +       }
>> +
>> +       pci_set_master(pdev);
>> +
>> +       err = pci_request_regions(pdev, UFSHCD);
>> +       if (err < 0) {
>> +               dev_err(&pdev->dev, "request regions failed\n");
>> +               goto out_disable;
>> +       }
>> +
>> +       mmio_base = pci_ioremap_bar(pdev, 0);
>> +       if (!mmio_base) {
>> +               dev_err(&pdev->dev, "memory map failed\n");
>> +               err = -ENOMEM;
>> +               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, "%s:%d %sInitialization failed\n",
>> +                               __FILE__, __LINE__, __func__);
>> +               goto out_iounmap;
>> +       }
>> +
>> +       pci_set_drvdata(pdev, hba);
>> +
>> +       return 0;
>> +
>>   out_iounmap:
>> -       iounmap(hba->mmio_base);
>> +       iounmap(mmio_base);
>>   out_release_regions:
>>         pci_release_regions(pdev);
>> -out_host_put:
>> -       scsi_host_put(host);
>>   out_disable:
>>         pci_clear_master(pdev);
>>         pci_disable_device(pdev);
>> @@ -1946,19 +2013,19 @@ MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
>>   static struct pci_driver ufshcd_pci_driver = {
>>         .name = UFSHCD,
>>         .id_table = ufshcd_pci_tbl,
>> -       .probe = ufshcd_probe,
>> -       .remove = __devexit_p(ufshcd_remove),
>> -       .shutdown = ufshcd_shutdown,
>> +       .probe = ufshcd_pci_probe,
>> +       .remove = __devexit_p(ufshcd_pci_remove),
>> +       .shutdown = ufshcd_pci_shutdown,
>>   #ifdef CONFIG_PM
>> -       .suspend = ufshcd_suspend,
>> -       .resume = ufshcd_resume,
>> +       .suspend = ufshcd_pci_suspend,
>> +       .resume = ufshcd_pci_resume,
>>   #endif
>>   };
>>     module_pci_driver(ufshcd_pci_driver);
>>   -MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, "
>> -             "Vinayak Holikatti <h.vinayak@samsung.com>");
>> +MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
>> +MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
>>   MODULE_DESCRIPTION("Generic UFS host controller driver");
>>   MODULE_LICENSE("GPL");
>>   MODULE_VERSION(UFSHCD_DRIVER_VERSION);
>> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
>> index 6e3510f..1cc1e00 100644
>> --- a/drivers/scsi/ufs/ufshci.h
>> +++ b/drivers/scsi/ufs/ufshci.h
>> @@ -4,43 +4,33 @@
>>    * This code is based on drivers/scsi/ufs/ufshci.h
>>    * Copyright (C) 2011-2012 Samsung India Software Operations
>>    *
>> - * Santosh Yaraganavi <santosh.sy@samsung.com>
>> - * Vinayak Holikatti <h.vinayak@samsung.com>
>> + * Authors:
>> + *     Santosh Yaraganavi <santosh.sy@samsung.com>
>> + *     Vinayak Holikatti <h.vinayak@samsung.com>
>>    *
>>    * 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.
>> + * See the COPYING file in the top-level directory or visit
>> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>>    *
>>    * This program is distributed in the hope that it will be useful,
>>    * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>    * GNU General Public License for more details.
>>    *
>> - * NO WARRANTY
>> - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>> - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>> - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>> - * solely responsible for determining the appropriateness of using and
>> - * distributing the Program and assumes all risks associated with its
>> - * exercise of rights under this Agreement, including but not limited to
>> - * the risks and costs of program errors, damage to or loss of data,
>> - * programs or equipment, and unavailability or interruption of
>> operations.
>> -
>> - * DISCLAIMER OF LIABILITY
>> - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
>> ANY
>> - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>> - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
>> AND
>> - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>> - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
>> GRANTED
>> - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>> -
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program; if not, write to the Free Software
>> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>> 02110-1301,
>> - * USA.
>> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
>> + * without warranty of any kind. You are solely responsible for
>> + * determining the appropriateness of using and distributing
>> + * the program and assume all risks associated with your exercise
>> + * of rights with respect to the program, including but not limited
>> + * to infringement of third party rights, the risks and costs of
>> + * program errors, damage to or loss of data, programs or equipment,
>> + * and unavailability or interruption of operations. Under no
>> + * circumstances will the contributor of this Program be liable for
>> + * any damages of any kind arising from your use or distribution of
>> + * this program.
>>    */
>>     #ifndef _UFSHCI_H
>
>



-- 
Regards,
Vinayak Holikatti

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

* Re: [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd
  2012-12-27 14:58   ` Subhash Jadavani
@ 2013-01-04  7:37     ` vinayak holikatti
  2013-01-06 17:36       ` Subhash Jadavani
  0 siblings, 1 reply; 16+ messages in thread
From: vinayak holikatti @ 2013-01-04  7:37 UTC (permalink / raw)
  To: Subhash Jadavani; +Cc: james.bottomley, linux-scsi, santoshsy

On Thu, Dec 27, 2012 at 8:28 PM, Subhash Jadavani
<subhashj@codeaurora.org> wrote:
> On 12/27/2012 1:45 AM, vinholikatti@gmail.com wrote:
>>
>> From: Vinayak Holikatti <vinholikatti@gmail.com>
>>
>> This patch adds Platform glue driver for ufshcd.
>>
>> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
>> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
>> Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
>> Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
>> ---
>>   drivers/scsi/ufs/Kconfig         |   11 ++
>>   drivers/scsi/ufs/Makefile        |    1 +
>>   drivers/scsi/ufs/ufshcd-pltfrm.c |  205
>> ++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 217 insertions(+), 0 deletions(-)
>>   create mode 100644 drivers/scsi/ufs/ufshcd-pltfrm.c
>>
>> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
>> index d77ae97..96e1721 100644
>> --- a/drivers/scsi/ufs/Kconfig
>> +++ b/drivers/scsi/ufs/Kconfig
>> @@ -57,3 +57,14 @@ config SCSI_UFSHCD_PCI
>>           If you have a controller with this interface, say Y or M here.
>>           If unsure, say N.
>> +
>> +config SCSI_UFSHCD_PLATFORM
>> +       tristate "Platform based UFS Controller support"
>
> This may sound more explicit: s/"Platform based"/"Platform bus based"
>>
>> +       depends on SCSI_UFSHCD
>> +       ---help---
>> +       This selects the UFS host controller support. If you have a
>> +          platform with UFS controller, say Y or M here.
>
> s/"If you have a platform with UFS controller,"/"If you have UFS controller
> on platform bus,"
>>
>> +
>> +          If you have a controller with this interface, say Y or M here.
>
> Why do we need this line? we already one comment above.
>>
>> +
>> +         If unsure, say N.
>> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
>> index 9eda0df..1e5bd48 100644
>> --- a/drivers/scsi/ufs/Makefile
>> +++ b/drivers/scsi/ufs/Makefile
>> @@ -1,3 +1,4 @@
>>   # UFSHCD makefile
>>   obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
>>   obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
>> +obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
>> diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c
>> b/drivers/scsi/ufs/ufshcd-pltfrm.c
>> new file mode 100644
>> index 0000000..94acfdc
>> --- /dev/null
>> +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
>> @@ -0,0 +1,205 @@
>> +/*
>> + * Universal Flash Storage Host controller driver
>
> Please add some comment to indicate that this is platform bus UFS host
> controller driver.
The File name itself would identify the nature of driver. can add for more info.
>>
>> + *
>> + * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
>> + * Copyright (C) 2011-2012 Samsung India Software Operations
>> + *
>> + * Authors:
>> + *     Santosh Yaraganavi <santosh.sy@samsung.com>
>> + *     Vinayak Holikatti <h.vinayak@samsung.com>
>> + *
>> + * 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.
>> + * See the COPYING file in the top-level directory or visit
>> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
>> + * without warranty of any kind. You are solely responsible for
>> + * determining the appropriateness of using and distributing
>> + * the program and assume all risks associated with your exercise
>> + * of rights with respect to the program, including but not limited
>> + * to infringement of third party rights, the risks and costs of
>> + * program errors, damage to or loss of data, programs or equipment,
>> + * and unavailability or interruption of operations. Under no
>> + * circumstances will the contributor of this Program be liable for
>> + * any damages of any kind arising from your use or distribution of
>> + * this program.
>> + */
>> +
>> +#include "ufshcd.h"
>> +#include <linux/platform_device.h>
>> +
>> +#ifdef CONFIG_PM
>> +/**
>> + * ufshcd_pltfrm_suspend - suspend power management function
>> + * @pdev: pointer to Platform device handle
>> + * @mesg: power state
>> + *
>> + * Returns -ENOSYS
>> + */
>> +static int ufshcd_pltfrm_suspend(struct platform_device *pdev,
>> +                                pm_message_t mesg)
>> +{
>> +       /*
>> +        * TODO:
>> +        * 1. Call ufshcd_suspend
>> +        * 2. Do bus specific power management
>> +        */
>> +
>> +       return -ENOSYS;
>> +}
>> +
>> +/**
>> + * ufshcd_pltfrm_resume - resume power management function
>> + * @pdev: pointer to Platform device handle
>> + *
>> + * Returns -ENOSYS
>> + */
>> +static int ufshcd_pltfrm_resume(struct platform_device *pdev)
>> +{
>> +       /*
>> +        * TODO:
>> +        * 1. Call ufshcd_resume.
>> +        * 2. Do bus specific wake up
>> +        */
>> +
>> +       return -ENOSYS;
>> +}
>> +#endif
>> +
>> +/**
>> + * ufshcd_pltfrm_probe - probe routine of the driver
>> + * @pdev: pointer to Platform device handle
>> + *
>> + * Returns 0 on success, non-zero value on failure
>> + */
>> +static int __devinit
>> +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;
>> +       struct device *dev = &pdev->dev;
>> +
>> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       if (!mem_res) {
>> +               dev_err(&pdev->dev,
>> +                       "%s: Memory resource not available\n", __FILE__);
>
> Why would we print the file name? Won't the device name prefix enough in
> debug message?
File name would be necessary for faster debugging
>>
>> +               err = -ENODEV;
>> +               goto out_error;
>> +       }
>> +
>> +       mem_size = resource_size(mem_res);
>> +       if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
>
> you may want to use the UFSHCD macro:   s/"ufshcd"/UFSHCD
>
>> +               dev_err(&pdev->dev,
>> +                       "ufshcd: Cannot reserve the memory resource\n");
>
>
> "ufshcd:" prefix may not be required here as the device name prefix should
> be enough to know the context of the error.
"ufshcd:" Can be removed.
>>
>> +               err = -EBUSY;
>> +               goto out_error;
>> +       }
>> +
>> +       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, "ufshcd: IRQ resource not
>> available\n");
>
>
> Same as above. "ufshcd:" prefix may not be required here as the device name
> prefix should be enough to know the context of the error.
can be removed.
>
>> +               err = -ENODEV;
>> +               goto out_iounmap;
>> +       }
>> +
>> +       err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
>> +       if (err) {
>> +               dev_err(&pdev->dev, "set dma mask failed\n");
>> +               goto out_iounmap;
>> +       }
>> +
>> +       err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
>> +       if (err) {
>> +               dev_err(&pdev->dev, "%s: Intialization failed\n",
>> +                       __FILE__);
>
>
> Again, not sure why we would need to prefix the file name here.
__FILE__ is necessary for faster debugging
>
>> +               goto out_iounmap;
>> +       }
>> +
>> +       platform_set_drvdata(pdev, hba);
>> +
>> +       return 0;
>> +
>> +out_iounmap:
>> +       iounmap(mmio_base);
>> +out_release_regions:
>> +       release_mem_region(mem_res->start, mem_size);
>> +out_error:
>> +       return err;
>> +}
>> +
>> +/**
>> + * ufshcd_pltfrm_remove - remove platform driver routine
>> + * @pdev: pointer to platform device handle
>> + *
>> + * Returns 0 on success, non-zero value on failure
>> + */
>> +static int __devexit ufshcd_pltfrm_remove(struct platform_device *pdev)
>> +{
>> +       struct resource *mem_res;
>> +       struct resource *irq_res;
>> +       resource_size_t mem_size;
>> +       struct ufs_hba *hba =  platform_get_drvdata(pdev);
>> +
>> +       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>
> It would be better to save the irq number under "struct ufs_hba" during
> probe. So here during remove you just need simply need to call the
> "free_irq(irq_res->start, hba)"
Will modify the code accordingly in the next patchset.
>>
>> +
>> +       if (!irq_res)
>> +               dev_err(&pdev->dev, "ufshcd: IRQ resource not
>> available\n");
>> +       else
>> +               free_irq(irq_res->start, hba);
>> +
>> +       ufshcd_remove(hba);
>
> Remove should be exactly opposite of probe(). So shouldn't you call the
> ufshcd_remove() first and then free_irq() after that.
Some bugging controllers might raise the interrupt after resources are removed.
this sequence will prevent it.
>>
>> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>
> You might want to save the pointer to mem_res in "struct ufs_hba" during
> probe and may use the same here.
>>
>> +       if (!mem_res)
>> +               dev_err(&pdev->dev, "ufshcd: Memory resource not
>> available\n");
>> +       else {
>> +               mem_size = resource_size(mem_res);
>> +               release_mem_region(mem_res->start, mem_size);
>> +       }
>> +       platform_set_drvdata(pdev, NULL);
>> +       return 0;
>> +}
>> +
>> +static const struct of_device_id ufs_of_match[] = {
>> +       { .compatible = "jedec,ufs-1.1"},
>> +};
>> +
>> +static struct platform_driver ufshcd_pltfrm_driver = {
>> +       .probe  = ufshcd_pltfrm_probe,
>> +       .remove = __devexit_p(ufshcd_pltfrm_remove),
>> +#ifdef CONFIG_PM
>> +       .suspend = ufshcd_pltfrm_suspend,
>> +       .resume = ufshcd_pltfrm_resume,
>> +#endif
>> +       .driver = {
>> +               .name   = "ufshcd",
>> +               .owner  = THIS_MODULE,
>> +               .of_match_table = ufs_of_match,
>> +       },
>> +};
>> +
>> +module_platform_driver(ufshcd_pltfrm_driver);
>> +
>> +MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
>> +MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
>> +MODULE_DESCRIPTION("Platform based UFS host controller driver");
>
>
> s/"Platform based"/"Platform Bus based"
>
>> +MODULE_LICENSE("GPL");
>> +MODULE_VERSION(UFSHCD_DRIVER_VERSION);
>
> You want to keep the same driver version as the UFS core driver?
>

-- 
Regards,
Vinayak Holikatti

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

* Re: [PATCH V5 1/4] [SCSI] drivers/scsi/ufs: Seggregate PCI Specific Code
  2013-01-04  7:00     ` vinayak holikatti
@ 2013-01-06 17:32       ` Subhash Jadavani
  0 siblings, 0 replies; 16+ messages in thread
From: Subhash Jadavani @ 2013-01-06 17:32 UTC (permalink / raw)
  To: vinayak holikatti; +Cc: james.bottomley, linux-scsi, santoshsy

On 1/4/2013 12:30 PM, vinayak holikatti wrote:
> On Thu, Dec 27, 2012 at 7:59 PM, Subhash Jadavani
> <subhashj@codeaurora.org> wrote:
>> Few comments inline:
>>
>> On 12/27/2012 1:45 AM, vinholikatti@gmail.com wrote:
>>> From: Vinayak Holikatti <vinholikatti@gmail.com>
>>>
>>> This patch seggregates the PCI specific code in ufshcd.c to make it
>>> ready for splitting into core ufs driver and PCI glue driver. Also
>>> copyright header modification to remove extra warranty disclaim.
>>>
>>> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
>>> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
>>> Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
>>> Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
>>> ---
>>>    drivers/scsi/ufs/Kconfig  |   50 +++----
>>>    drivers/scsi/ufs/ufs.h    |   42 ++----
>>>    drivers/scsi/ufs/ufshcd.c |  339
>>> +++++++++++++++++++++++++++------------------
>>>    drivers/scsi/ufs/ufshci.h |   42 ++----
>>>    4 files changed, 255 insertions(+), 218 deletions(-)
>>>
>>> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
>>> index 8f27f9d..9c84569 100644
>>> --- a/drivers/scsi/ufs/Kconfig
>>> +++ b/drivers/scsi/ufs/Kconfig
>>> @@ -2,45 +2,35 @@
>>>    # Kernel configuration file for the UFS Host Controller
>>>    #
>>>    # This code is based on drivers/scsi/ufs/Kconfig
>>> -# Copyright (C) 2011  Samsung Samsung India Software Operations
>>> +# Copyright (C) 2011-2012 Samsung India Software Operations
>>> +#
>>> +# Authors:
>>> +#      Santosh Yaraganavi <santosh.sy@samsung.com>
>>> +#      Vinayak Holikatti <h.vinayak@samsung.com>
>>>    #
>>> -# Santosh Yaraganavi <santosh.sy@samsung.com>
>>> -# Vinayak Holikatti <h.vinayak@samsung.com>
>>> -
>>>    # 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.
>>> -
>>> +# See the COPYING file in the top-level directory or visit
>>> +# <http://www.gnu.org/licenses/gpl-2.0.html>
>>> +#
>>>    # This program is distributed in the hope that it will be useful,
>>>    # but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>    # GNU General Public License for more details.
>>> -
>>> -# NO WARRANTY
>>> -# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>>> -# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>>> -# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>>> -# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>>> -# solely responsible for determining the appropriateness of using and
>>> -# distributing the Program and assumes all risks associated with its
>>> -# exercise of rights under this Agreement, including but not limited to
>>> -# the risks and costs of program errors, damage to or loss of data,
>>> -# programs or equipment, and unavailability or interruption of
>>> operations.
>>> -
>>> -# DISCLAIMER OF LIABILITY
>>> -# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
>>> -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>>> -# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
>>> -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>>> -# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>>> -# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
>>> GRANTED
>>> -# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>>> -
>>> -# You should have received a copy of the GNU General Public License
>>> -# along with this program; if not, write to the Free Software
>>> -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>> 02110-1301,
>>> -# USA.
>>> +#
>>> +# This program is provided "AS IS" and "WITH ALL FAULTS" and
>>> +# without warranty of any kind. You are solely responsible for
>>> +# determining the appropriateness of using and distributing
>>> +# the program and assume all risks associated with your exercise
>>> +# of rights with respect to the program, including but not limited
>>> +# to infringement of third party rights, the risks and costs of
>>> +# program errors, damage to or loss of data, programs or equipment,
>>> +# and unavailability or interruption of operations. Under no
>>> +# circumstances will the contributor of this Program be liable for
>>> +# any damages of any kind arising from your use or distribution of
>>> +# this program.
>>>      config SCSI_UFSHCD
>>>          tristate "Universal Flash Storage host controller driver"
>>> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
>>> index b207529..4b3d611 100644
>>> --- a/drivers/scsi/ufs/ufs.h
>>> +++ b/drivers/scsi/ufs/ufs.h
>>> @@ -4,43 +4,33 @@
>>>     * This code is based on drivers/scsi/ufs/ufs.h
>>>     * Copyright (C) 2011-2012 Samsung India Software Operations
>>>     *
>>> - * Santosh Yaraganavi <santosh.sy@samsung.com>
>>> - * Vinayak Holikatti <h.vinayak@samsung.com>
>>> + * Authors:
>>> + *     Santosh Yaraganavi <santosh.sy@samsung.com>
>>> + *     Vinayak Holikatti <h.vinayak@samsung.com>
>>>     *
>>>     * 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.
>>> + * See the COPYING file in the top-level directory or visit
>>> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>>>     *
>>>     * This program is distributed in the hope that it will be useful,
>>>     * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>     * GNU General Public License for more details.
>>>     *
>>> - * NO WARRANTY
>>> - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>>> - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>>> - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>>> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>>> - * solely responsible for determining the appropriateness of using and
>>> - * distributing the Program and assumes all risks associated with its
>>> - * exercise of rights under this Agreement, including but not limited to
>>> - * the risks and costs of program errors, damage to or loss of data,
>>> - * programs or equipment, and unavailability or interruption of
>>> operations.
>>> -
>>> - * DISCLAIMER OF LIABILITY
>>> - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
>>> ANY
>>> - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>>> - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
>>> AND
>>> - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>>> - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>>> - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
>>> GRANTED
>>> - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>>> -
>>> - * You should have received a copy of the GNU General Public License
>>> - * along with this program; if not, write to the Free Software
>>> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>> 02110-1301,
>>> - * USA.
>>> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
>>> + * without warranty of any kind. You are solely responsible for
>>> + * determining the appropriateness of using and distributing
>>> + * the program and assume all risks associated with your exercise
>>> + * of rights with respect to the program, including but not limited
>>> + * to infringement of third party rights, the risks and costs of
>>> + * program errors, damage to or loss of data, programs or equipment,
>>> + * and unavailability or interruption of operations. Under no
>>> + * circumstances will the contributor of this Program be liable for
>>> + * any damages of any kind arising from your use or distribution of
>>> + * this program.
>>>     */
>>>      #ifndef _UFS_H
>>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>>> index 58f4ba6..86b5b49 100644
>>> --- a/drivers/scsi/ufs/ufshcd.c
>>> +++ b/drivers/scsi/ufs/ufshcd.c
>>> @@ -4,43 +4,33 @@
>>>     * This code is based on drivers/scsi/ufs/ufshcd.c
>>>     * Copyright (C) 2011-2012 Samsung India Software Operations
>>>     *
>>> - * Santosh Yaraganavi <santosh.sy@samsung.com>
>>> - * Vinayak Holikatti <h.vinayak@samsung.com>
>>> + * Authors:
>>> + *     Santosh Yaraganavi <santosh.sy@samsung.com>
>>> + *     Vinayak Holikatti <h.vinayak@samsung.com>
>>>     *
>>>     * 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.
>>> + * See the COPYING file in the top-level directory or visit
>>> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>>>     *
>>>     * This program is distributed in the hope that it will be useful,
>>>     * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>     * GNU General Public License for more details.
>>>     *
>>> - * NO WARRANTY
>>> - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>>> - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>>> - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>>> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>>> - * solely responsible for determining the appropriateness of using and
>>> - * distributing the Program and assumes all risks associated with its
>>> - * exercise of rights under this Agreement, including but not limited to
>>> - * the risks and costs of program errors, damage to or loss of data,
>>> - * programs or equipment, and unavailability or interruption of
>>> operations.
>>> -
>>> - * DISCLAIMER OF LIABILITY
>>> - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
>>> ANY
>>> - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>>> - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
>>> AND
>>> - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>>> - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>>> - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
>>> GRANTED
>>> - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>>> -
>>> - * You should have received a copy of the GNU General Public License
>>> - * along with this program; if not, write to the Free Software
>>> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>> 02110-1301,
>>> - * USA.
>>> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
>>> + * without warranty of any kind. You are solely responsible for
>>> + * determining the appropriateness of using and distributing
>>> + * the program and assume all risks associated with your exercise
>>> + * of rights with respect to the program, including but not limited
>>> + * to infringement of third party rights, the risks and costs of
>>> + * program errors, damage to or loss of data, programs or equipment,
>>> + * and unavailability or interruption of operations. Under no
>>> + * circumstances will the contributor of this Program be liable for
>>> + * any damages of any kind arising from your use or distribution of
>>> + * this program.
>>>     */
>>>      #include <linux/module.h>
>>> @@ -129,7 +119,7 @@ struct uic_command {
>>>     * @utrdl_dma_addr: UTRDL DMA address
>>>     * @utmrdl_dma_addr: UTMRDL DMA address
>>>     * @host: Scsi_Host instance of the driver
>>> - * @pdev: PCI device handle
>>> + * @dev: device handle
>>>     * @lrb: local reference block
>>>     * @outstanding_tasks: Bits representing outstanding task requests
>>>     * @outstanding_reqs: Bits representing outstanding transfer requests
>>> @@ -159,7 +149,7 @@ struct ufs_hba {
>>>          dma_addr_t utmrdl_dma_addr;
>>>          struct Scsi_Host *host;
>>> -       struct pci_dev *pdev;
>>> +       struct device *dev;
>>>          struct ufshcd_lrb *lrb;
>>>    @@ -335,21 +325,21 @@ static inline void ufshcd_free_hba_memory(struct
>>> ufs_hba *hba)
>>>          if (hba->utmrdl_base_addr) {
>>>                  utmrdl_size = sizeof(struct utp_task_req_desc) *
>>> hba->nutmrs;
>>> -               dma_free_coherent(&hba->pdev->dev, utmrdl_size,
>>> +               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->pdev->dev, utrdl_size,
>>> +               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->pdev->dev, ucdl_size,
>>> +               dma_free_coherent(hba->dev, ucdl_size,
>>>                                    hba->ucdl_base_addr,
>>> hba->ucdl_dma_addr);
>>>          }
>>>    }
>>> @@ -724,7 +714,7 @@ 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->pdev->dev,
>>> +       hba->ucdl_base_addr = dma_alloc_coherent(hba->dev,
>>>                                                   ucdl_size,
>>>                                                   &hba->ucdl_dma_addr,
>>>                                                   GFP_KERNEL);
>>> @@ -737,7 +727,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>>>           */
>>>          if (!hba->ucdl_base_addr ||
>>>              WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) {
>>> -               dev_err(&hba->pdev->dev,
>>> +               dev_err(hba->dev,
>>>                          "Command Descriptor Memory allocation failed\n");
>>>                  goto out;
>>>          }
>>> @@ -747,13 +737,13 @@ 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->pdev->dev,
>>> +       hba->utrdl_base_addr = dma_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->pdev->dev,
>>> +               dev_err(hba->dev,
>>>                          "Transfer Descriptor Memory allocation failed\n");
>>>                  goto out;
>>>          }
>>> @@ -763,13 +753,13 @@ 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->pdev->dev,
>>> +       hba->utmrdl_base_addr = dma_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->pdev->dev,
>>> +               dev_err(hba->dev,
>>>                  "Task Management Descriptor Memory allocation failed\n");
>>>                  goto out;
>>>          }
>>> @@ -777,7 +767,7 @@ 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);
>>>          if (!hba->lrb) {
>>> -               dev_err(&hba->pdev->dev, "LRB Memory allocation
>>> failed\n");
>>> +               dev_err(hba->dev, "LRB Memory allocation failed\n");
>>>                  goto out;
>>>          }
>>>          return 0;
>>> @@ -867,7 +857,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba
>>> *hba)
>>>          /* check if controller is ready to accept UIC commands */
>>>          if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
>>>              UIC_COMMAND_READY) == 0x0) {
>>> -               dev_err(&hba->pdev->dev,
>>> +               dev_err(hba->dev,
>>>                          "Controller not ready"
>>>                          " to accept UIC commands\n");
>>>                  return -EIO;
>>> @@ -912,7 +902,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba
>>> *hba)
>>>          /* check if device present */
>>>          reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
>>>          if (!ufshcd_is_device_present(reg)) {
>>> -               dev_err(&hba->pdev->dev, "cc: Device not present\n");
>>> +               dev_err(hba->dev, "cc: Device not present\n");
>>>                  err = -ENXIO;
>>>                  goto out;
>>>          }
>>> @@ -924,7 +914,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba
>>> *hba)
>>>          if (!(ufshcd_get_lists_status(reg))) {
>>>                  ufshcd_enable_run_stop_reg(hba);
>>>          } else {
>>> -               dev_err(&hba->pdev->dev,
>>> +               dev_err(hba->dev,
>>>                          "Host controller not ready to process requests");
>>>                  err = -EIO;
>>>                  goto out;
>>> @@ -1005,7 +995,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
>>>                  if (retry) {
>>>                          retry--;
>>>                  } else {
>>> -                       dev_err(&hba->pdev->dev,
>>> +                       dev_err(hba->dev,
>>>                                  "Controller enable failed\n");
>>>                          return -EIO;
>>>                  }
>>> @@ -1084,7 +1074,7 @@ static int ufshcd_do_reset(struct ufs_hba *hba)
>>>          /* start the initialization process */
>>>          if (ufshcd_initialize_hba(hba)) {
>>> -               dev_err(&hba->pdev->dev,
>>> +               dev_err(hba->dev,
>>>                          "Reset: Controller initialization failed\n");
>>>                  return FAILED;
>>>          }
>>> @@ -1167,7 +1157,7 @@ static int ufshcd_task_req_compl(struct ufs_hba
>>> *hba, u32 index)
>>>                          task_result = SUCCESS;
>>>          } else {
>>>                  task_result = FAILED;
>>> -               dev_err(&hba->pdev->dev,
>>> +               dev_err(hba->dev,
>>>                          "trc: Invalid ocs = %x\n", ocs_value);
>>>          }
>>>          spin_unlock_irqrestore(hba->host->host_lock, flags);
>>> @@ -1281,7 +1271,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
>>> struct ufshcd_lrb *lrbp)
>>>                  /* check if the returned transfer response is valid */
>>>                  result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
>>>                  if (result) {
>>> -                       dev_err(&hba->pdev->dev,
>>> +                       dev_err(hba->dev,
>>>                                  "Invalid response = %x\n", result);
>>>                          break;
>>>                  }
>>> @@ -1310,7 +1300,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
>>> struct ufshcd_lrb *lrbp)
>>>          case OCS_FATAL_ERROR:
>>>          default:
>>>                  result |= DID_ERROR << 16;
>>> -               dev_err(&hba->pdev->dev,
>>> +               dev_err(hba->dev,
>>>                  "OCS error from controller = %x\n", ocs);
>>>                  break;
>>>          } /* end of switch */
>>> @@ -1374,7 +1364,7 @@ static void ufshcd_uic_cc_handler (struct
>>> work_struct *work)
>>>              !(ufshcd_get_uic_cmd_result(hba))) {
>>>                  if (ufshcd_make_hba_operational(hba))
>>> -                       dev_err(&hba->pdev->dev,
>>> +                       dev_err(hba->dev,
>>>                                  "cc: hba not operational state\n");
>>>                  return;
>>>          }
>>> @@ -1509,7 +1499,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
>>>          free_slot = ufshcd_get_tm_free_slot(hba);
>>>          if (free_slot >= hba->nutmrs) {
>>>                  spin_unlock_irqrestore(host->host_lock, flags);
>>> -               dev_err(&hba->pdev->dev, "Task management queue full\n");
>>> +               dev_err(hba->dev, "Task management queue full\n");
>>>                  err = FAILED;
>>>                  goto out;
>>>          }
>>> @@ -1552,7 +1542,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
>>>                                           &hba->tm_condition) != 0),
>>>                                           60 * HZ);
>>>          if (!err) {
>>> -               dev_err(&hba->pdev->dev,
>>> +               dev_err(hba->dev,
>>>                          "Task management command timed-out\n");
>>>                  err = FAILED;
>>>                  goto out;
>>> @@ -1688,23 +1678,22 @@ static struct scsi_host_template
>>> ufshcd_driver_template = {
>>>    };
>>>      /**
>>> - * ufshcd_shutdown - main function to put the controller in reset state
>>> + * ufshcd_pci_shutdown - main function to put the controller in reset
>>> state
>>>     * @pdev: pointer to PCI device handle
>>>     */
>>> -static void ufshcd_shutdown(struct pci_dev *pdev)
>>> +static void ufshcd_pci_shutdown(struct pci_dev *pdev)
>>>    {
>>>          ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
>>>    }
>>>    -#ifdef CONFIG_PM
>>>    /**
>>>     * ufshcd_suspend - suspend power management function
>>> - * @pdev: pointer to PCI device handle
>>> + * @hba: per adapter instance
>>>     * @state: power state
>>>     *
>>>     * Returns -ENOSYS
>>>     */
>>> -static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
>>> +int ufshcd_suspend(struct ufs_hba *hba, pm_message_t state)
>>>    {
>>>          /*
>>>           * TODO:
>>> @@ -1717,14 +1706,15 @@ static int ufshcd_suspend(struct pci_dev *pdev,
>>> pm_message_t state)
>>>          return -ENOSYS;
>>>    }
>>> +EXPORT_SYMBOL_GPL(ufshcd_suspend);
>>>      /**
>>>     * ufshcd_resume - resume power management function
>>> - * @pdev: pointer to PCI device handle
>>> + * @hba: per adapter instance
>>>     *
>>>     * Returns -ENOSYS
>>>     */
>>> -static int ufshcd_resume(struct pci_dev *pdev)
>>> +int ufshcd_resume(struct ufs_hba *hba)
>>>    {
>>>          /*
>>>           * TODO:
>>> @@ -1737,6 +1727,43 @@ static int ufshcd_resume(struct pci_dev *pdev)
>>>          return -ENOSYS;
>>>    }
>>> +EXPORT_SYMBOL_GPL(ufshcd_resume);
>>> +
>>> +#ifdef CONFIG_PM
>>> +/**
>>> + * ufshcd_pci_suspend - suspend power management function
>>> + * @pdev: pointer to PCI device handle
>>> + * @state: power state
>>> + *
>>> + * Returns -ENOSYS
>>> + */
>>> +static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
>>> +{
>>> +       /*
>>> +        * TODO:
>>> +        * 1. Call ufshcd_suspend
>>> +        * 2. Do bus specific power management
>>> +        */
>>> +
>>> +       return -ENOSYS;
>>> +}
>>> +
>>> +/**
>>> + * ufshcd_pci_resume - resume power management function
>>> + * @pdev: pointer to PCI device handle
>>> + *
>>> + * Returns -ENOSYS
>>> + */
>>> +static int ufshcd_pci_resume(struct pci_dev *pdev)
>>> +{
>>> +       /*
>>> +        * TODO:
>>> +        * 1. Call ufshcd_resume.
>> Full stop can be removed to be consistant with other comments in this file.
>>> +        * 2. Do bus specific wake up
>>> +        */
>>> +
>>> +       return -ENOSYS;
>>> +}
>>>    #endif /* CONFIG_PM */
>>>      /**
>>> @@ -1748,27 +1775,38 @@ static void ufshcd_hba_free(struct ufs_hba *hba)
>>>    {
>>>          iounmap(hba->mmio_base);
>>>          ufshcd_free_hba_memory(hba);
>>> -       pci_release_regions(hba->pdev);
>>>    }
>>>      /**
>>> - * ufshcd_remove - de-allocate PCI/SCSI host and host memory space
>>> + * ufshcd_remove - de-allocate SCSI host and host memory space
>>>     *            data structure memory
>>> - * @pdev - pointer to PCI handle
>>> + * @hba - per adapter instance
>>>     */
>>> -static void ufshcd_remove(struct pci_dev *pdev)
>>> +void ufshcd_remove(struct ufs_hba *hba)
>>>    {
>>> -       struct ufs_hba *hba = pci_get_drvdata(pdev);
>>> -
>>>          /* disable interrupts */
>>>          ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
>>> -       free_irq(pdev->irq, hba);
>>>          ufshcd_hba_stop(hba);
>>>          ufshcd_hba_free(hba);
>>>          scsi_remove_host(hba->host);
>>>          scsi_host_put(hba->host);
>>> +}
>>> +EXPORT_SYMBOL_GPL(ufshcd_remove);
>>> +
>>> +/**
>>> + * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
>>> + *             data structure memory
>>> + * @pdev - pointer to PCI handle
>>> + */
>>> +static void ufshcd_pci_remove(struct pci_dev *pdev)
>>> +{
>>> +       struct ufs_hba *hba = pci_get_drvdata(pdev);
>>> +
>>> +       free_irq(pdev->irq, hba);
>>> +       ufshcd_remove(hba);
>>> +       pci_release_regions(pdev);
>>>          pci_set_drvdata(pdev, NULL);
>>>          pci_clear_master(pdev);
>>>          pci_disable_device(pdev);
>>> @@ -1781,75 +1819,52 @@ static void ufshcd_remove(struct pci_dev *pdev)
>>>     *
>>>     * Returns 0 for success, non-zero for failure
>>>     */
>>> -static int ufshcd_set_dma_mask(struct ufs_hba *hba)
>>> +static int ufshcd_set_dma_mask(struct pci_dev *pdev)
>>>    {
>>>          int err;
>>> -       u64 dma_mask;
>>> -
>>> -       /*
>>> -        * If controller supports 64 bit addressing mode, then set the DMA
>>> -        * mask to 64-bit, else set the DMA mask to 32-bit
>>> -        */
>>> -       if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT)
>>> -               dma_mask = DMA_BIT_MASK(64);
>>> -       else
>>> -               dma_mask = DMA_BIT_MASK(32);
>>> -
>>> -       err = pci_set_dma_mask(hba->pdev, dma_mask);
>>> -       if (err)
>>> -               return err;
>>> -
>>> -       err = pci_set_consistent_dma_mask(hba->pdev, dma_mask);
>>>    +     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_probe - probe routine of the driver
>>> - * @pdev: pointer to PCI device handle
>>> - * @id: PCI device id
>>> - *
>>> + * ufshcd_init - Driver initialization routine
>>> + * @dev: pointer to device handle
>>> + * @hba_handle: driver private handle
>>> + * @mmio_base: base register address
>>> + * @irq_line: Interrupt line of device
>>>     * Returns 0 on success, non-zero value on failure
>>>     */
>>> -static int __devinit
>>> -ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>> +int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
>>> +                void __iomem *mmio_base, unsigned int irq_line)
>> Just irq should be enough: s/irq_line/irq
>>>    {
>>>          struct Scsi_Host *host;
>>>          struct ufs_hba *hba;
>>>          int err;
>>>    -     err = pci_enable_device(pdev);
>>> -       if (err) {
>>> -               dev_err(&pdev->dev, "pci_enable_device failed\n");
>>> +       if (!dev && !mmio_base) {
>>> +               dev_err(dev,
>>> +               "Invalid memory reference for dev or mmio_base NULL\n");
>> Better to have "!dev" and "!mmio_base" seperate to print out exact error.
>>
>>> +               err = -ENODEV;
>>>                  goto out_error;
>>>          }
>>>    -     pci_set_master(pdev);
>>> -
>>>          host = scsi_host_alloc(&ufshcd_driver_template,
>>>                                  sizeof(struct ufs_hba));
>>>          if (!host) {
>>> -               dev_err(&pdev->dev, "scsi_host_alloc failed\n");
>>> +               dev_err(dev, "scsi_host_alloc failed\n");
>>>                  err = -ENOMEM;
>>> -               goto out_disable;
>>> +               goto out_error;
>>>          }
>>>          hba = shost_priv(host);
>>> -
>>> -       err = pci_request_regions(pdev, UFSHCD);
>>> -       if (err < 0) {
>>> -               dev_err(&pdev->dev, "request regions failed\n");
>>> -               goto out_host_put;
>>> -       }
>>> -
>>> -       hba->mmio_base = pci_ioremap_bar(pdev, 0);
>>> -       if (!hba->mmio_base) {
>>> -               dev_err(&pdev->dev, "memory map failed\n");
>>> -               err = -ENOMEM;
>>> -               goto out_release_regions;
>>> -       }
>>> -
>>>          hba->host = host;
>>> -       hba->pdev = pdev;
>>> +       hba->dev = dev;
>>> +       hba->mmio_base = mmio_base;
>>>          /* Read capabilities registers */
>>>          ufshcd_hba_capabilities(hba);
>>> @@ -1857,17 +1872,11 @@ ufshcd_probe(struct pci_dev *pdev, const struct
>>> pci_device_id *id)
>>>          /* Get UFS version supported by the controller */
>>>          hba->ufs_version = ufshcd_get_ufs_version(hba);
>>>    -     err = ufshcd_set_dma_mask(hba);
>>> -       if (err) {
>>> -               dev_err(&pdev->dev, "set dma mask failed\n");
>>> -               goto out_iounmap;
>>> -       }
>>> -
>>>          /* Allocate memory for host memory space */
>>>          err = ufshcd_memory_alloc(hba);
>>>          if (err) {
>>> -               dev_err(&pdev->dev, "Memory allocation failed\n");
>>> -               goto out_iounmap;
>>> +               dev_err(hba->dev, "Memory allocation failed\n");
>>> +               goto out_disable;
>>>          }
>>>          /* Configure LRB */
>>> @@ -1889,46 +1898,104 @@ ufshcd_probe(struct pci_dev *pdev, const struct
>>> pci_device_id *id)
>>>          INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
>>>          /* IRQ registration */
>>> -       err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD,
>>> hba);
>>> +       err = request_irq(irq_line, ufshcd_intr, IRQF_SHARED, UFSHCD,
>>> hba);
>> irq flags is set to IRQF_SHARED. Not sure why? Is there any specific reason?
>> I don't see any shared interrupt handler for same irq line here?
> It is generic to be shared. So works well even if interrupt line in not shared.
Ok. That's fine. Thanks.
>> Here irq name is "UFSHCD" but say if we more than 1 instances of the UFS
>> controllers on same chipset then it would have seperate irq numbers as well
>> so to differnentiate them uniquely (when we do "cat /proc/interrupts"), it's
>> better to name the irq uniquely for each instances of UFS controllers.
> the separate irq numbers differentiate different controllers. Do you have
> any better way to accomplish it?
Ok. i was thinking if we can have name line "ufshcd.1" for first 
controller, "ufshcd.2" for 2nd and so on. But then we also need this 
controller index (1, 2 ...) passed as the platform data from device 
tree. I guess we can leave this as it is for now because even if 
required during debugging, irq line number should be enough to 
differentiate interrupts from each instances of controller.

With above points clarified, i am fine current version of this patch.
Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org>

Thanks,
Subhash
>>>          if (err) {
>>> -               dev_err(&pdev->dev, "request irq failed\n");
>>> +               dev_err(hba->dev, "request irq failed\n");
>>>                  goto out_lrb_free;
>>>          }
>>>          /* Enable SCSI tag mapping */
>>>          err = scsi_init_shared_tag_map(host, host->can_queue);
>>>          if (err) {
>>> -               dev_err(&pdev->dev, "init shared queue failed\n");
>>> +               dev_err(hba->dev, "init shared queue failed\n");
>>>                  goto out_free_irq;
>>>          }
>>>    -     pci_set_drvdata(pdev, hba);
>>> -
>>> -       err = scsi_add_host(host, &pdev->dev);
>>> +       err = scsi_add_host(host, hba->dev);
>>>          if (err) {
>>> -               dev_err(&pdev->dev, "scsi_add_host failed\n");
>>> +               dev_err(hba->dev, "scsi_add_host failed\n");
>>>                  goto out_free_irq;
>>>          }
>>>          /* Initialization routine */
>>>          err = ufshcd_initialize_hba(hba);
>>>          if (err) {
>>> -               dev_err(&pdev->dev, "Initialization failed\n");
>>> -               goto out_free_irq;
>>> +               dev_err(hba->dev, "Initialization failed\n");
>>> +               goto out_remove_scsi_host;
>>>          }
>>> +       *hba_handle = hba;
>>>          return 0;
>>>    +out_remove_scsi_host:
>>> +       scsi_remove_host(hba->host);
>>>    out_free_irq:
>>> -       free_irq(pdev->irq, hba);
>>> +       free_irq(irq_line, hba);
>>>    out_lrb_free:
>>>          ufshcd_free_hba_memory(hba);
>>> +out_disable:
>>> +       scsi_host_put(host);
>>> +out_error:
>>> +       return err;
>>> +}
>>> +EXPORT_SYMBOL_GPL(ufshcd_init);
>>> +
>>> +/**
>>> + * ufshcd_pci_probe - probe routine of the driver
>>> + * @pdev: pointer to PCI device handle
>>> + * @id: PCI device id
>>> + *
>>> + * Returns 0 on success, non-zero value on failure
>>> + */
>>> +static int __devinit
>>> +ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>> +{
>>> +       struct ufs_hba *hba;
>>> +       void __iomem *mmio_base;
>>> +       int err;
>>> +
>>> +       err = pci_enable_device(pdev);
>>> +       if (err) {
>>> +               dev_err(&pdev->dev, "pci_enable_device failed\n");
>>> +               goto out_error;
>>> +       }
>>> +
>>> +       pci_set_master(pdev);
>>> +
>>> +       err = pci_request_regions(pdev, UFSHCD);
>>> +       if (err < 0) {
>>> +               dev_err(&pdev->dev, "request regions failed\n");
>>> +               goto out_disable;
>>> +       }
>>> +
>>> +       mmio_base = pci_ioremap_bar(pdev, 0);
>>> +       if (!mmio_base) {
>>> +               dev_err(&pdev->dev, "memory map failed\n");
>>> +               err = -ENOMEM;
>>> +               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, "%s:%d %sInitialization failed\n",
>>> +                               __FILE__, __LINE__, __func__);
>>> +               goto out_iounmap;
>>> +       }
>>> +
>>> +       pci_set_drvdata(pdev, hba);
>>> +
>>> +       return 0;
>>> +
>>>    out_iounmap:
>>> -       iounmap(hba->mmio_base);
>>> +       iounmap(mmio_base);
>>>    out_release_regions:
>>>          pci_release_regions(pdev);
>>> -out_host_put:
>>> -       scsi_host_put(host);
>>>    out_disable:
>>>          pci_clear_master(pdev);
>>>          pci_disable_device(pdev);
>>> @@ -1946,19 +2013,19 @@ MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
>>>    static struct pci_driver ufshcd_pci_driver = {
>>>          .name = UFSHCD,
>>>          .id_table = ufshcd_pci_tbl,
>>> -       .probe = ufshcd_probe,
>>> -       .remove = __devexit_p(ufshcd_remove),
>>> -       .shutdown = ufshcd_shutdown,
>>> +       .probe = ufshcd_pci_probe,
>>> +       .remove = __devexit_p(ufshcd_pci_remove),
>>> +       .shutdown = ufshcd_pci_shutdown,
>>>    #ifdef CONFIG_PM
>>> -       .suspend = ufshcd_suspend,
>>> -       .resume = ufshcd_resume,
>>> +       .suspend = ufshcd_pci_suspend,
>>> +       .resume = ufshcd_pci_resume,
>>>    #endif
>>>    };
>>>      module_pci_driver(ufshcd_pci_driver);
>>>    -MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, "
>>> -             "Vinayak Holikatti <h.vinayak@samsung.com>");
>>> +MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
>>> +MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
>>>    MODULE_DESCRIPTION("Generic UFS host controller driver");
>>>    MODULE_LICENSE("GPL");
>>>    MODULE_VERSION(UFSHCD_DRIVER_VERSION);
>>> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
>>> index 6e3510f..1cc1e00 100644
>>> --- a/drivers/scsi/ufs/ufshci.h
>>> +++ b/drivers/scsi/ufs/ufshci.h
>>> @@ -4,43 +4,33 @@
>>>     * This code is based on drivers/scsi/ufs/ufshci.h
>>>     * Copyright (C) 2011-2012 Samsung India Software Operations
>>>     *
>>> - * Santosh Yaraganavi <santosh.sy@samsung.com>
>>> - * Vinayak Holikatti <h.vinayak@samsung.com>
>>> + * Authors:
>>> + *     Santosh Yaraganavi <santosh.sy@samsung.com>
>>> + *     Vinayak Holikatti <h.vinayak@samsung.com>
>>>     *
>>>     * 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.
>>> + * See the COPYING file in the top-level directory or visit
>>> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>>>     *
>>>     * This program is distributed in the hope that it will be useful,
>>>     * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>     * GNU General Public License for more details.
>>>     *
>>> - * NO WARRANTY
>>> - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>>> - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>>> - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>>> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>>> - * solely responsible for determining the appropriateness of using and
>>> - * distributing the Program and assumes all risks associated with its
>>> - * exercise of rights under this Agreement, including but not limited to
>>> - * the risks and costs of program errors, damage to or loss of data,
>>> - * programs or equipment, and unavailability or interruption of
>>> operations.
>>> -
>>> - * DISCLAIMER OF LIABILITY
>>> - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
>>> ANY
>>> - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>>> - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
>>> AND
>>> - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>>> - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>>> - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
>>> GRANTED
>>> - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>>> -
>>> - * You should have received a copy of the GNU General Public License
>>> - * along with this program; if not, write to the Free Software
>>> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>> 02110-1301,
>>> - * USA.
>>> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
>>> + * without warranty of any kind. You are solely responsible for
>>> + * determining the appropriateness of using and distributing
>>> + * the program and assume all risks associated with your exercise
>>> + * of rights with respect to the program, including but not limited
>>> + * to infringement of third party rights, the risks and costs of
>>> + * program errors, damage to or loss of data, programs or equipment,
>>> + * and unavailability or interruption of operations. Under no
>>> + * circumstances will the contributor of this Program be liable for
>>> + * any damages of any kind arising from your use or distribution of
>>> + * this program.
>>>     */
>>>      #ifndef _UFSHCI_H
>>
>
>


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

* Re: [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd
  2013-01-04  7:37     ` vinayak holikatti
@ 2013-01-06 17:36       ` Subhash Jadavani
  2013-01-07  7:41         ` Sujit Reddy Thumma
  0 siblings, 1 reply; 16+ messages in thread
From: Subhash Jadavani @ 2013-01-06 17:36 UTC (permalink / raw)
  To: vinayak holikatti; +Cc: james.bottomley, linux-scsi, santoshsy

On 1/4/2013 1:07 PM, vinayak holikatti wrote:
> On Thu, Dec 27, 2012 at 8:28 PM, Subhash Jadavani
> <subhashj@codeaurora.org> wrote:
>> On 12/27/2012 1:45 AM, vinholikatti@gmail.com wrote:
>>> From: Vinayak Holikatti <vinholikatti@gmail.com>
>>>
>>> This patch adds Platform glue driver for ufshcd.
>>>
>>> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
>>> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
>>> Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
>>> Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
>>> ---
>>>    drivers/scsi/ufs/Kconfig         |   11 ++
>>>    drivers/scsi/ufs/Makefile        |    1 +
>>>    drivers/scsi/ufs/ufshcd-pltfrm.c |  205
>>> ++++++++++++++++++++++++++++++++++++++
>>>    3 files changed, 217 insertions(+), 0 deletions(-)
>>>    create mode 100644 drivers/scsi/ufs/ufshcd-pltfrm.c
>>>
>>> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
>>> index d77ae97..96e1721 100644
>>> --- a/drivers/scsi/ufs/Kconfig
>>> +++ b/drivers/scsi/ufs/Kconfig
>>> @@ -57,3 +57,14 @@ config SCSI_UFSHCD_PCI
>>>            If you have a controller with this interface, say Y or M here.
>>>            If unsure, say N.
>>> +
>>> +config SCSI_UFSHCD_PLATFORM
>>> +       tristate "Platform based UFS Controller support"
>> This may sound more explicit: s/"Platform based"/"Platform bus based"
>>> +       depends on SCSI_UFSHCD
>>> +       ---help---
>>> +       This selects the UFS host controller support. If you have a
>>> +          platform with UFS controller, say Y or M here.
>> s/"If you have a platform with UFS controller,"/"If you have UFS controller
>> on platform bus,"
>>> +
>>> +          If you have a controller with this interface, say Y or M here.
>> Why do we need this line? we already one comment above.
>>> +
>>> +         If unsure, say N.
>>> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
>>> index 9eda0df..1e5bd48 100644
>>> --- a/drivers/scsi/ufs/Makefile
>>> +++ b/drivers/scsi/ufs/Makefile
>>> @@ -1,3 +1,4 @@
>>>    # UFSHCD makefile
>>>    obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
>>>    obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
>>> +obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
>>> diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c
>>> b/drivers/scsi/ufs/ufshcd-pltfrm.c
>>> new file mode 100644
>>> index 0000000..94acfdc
>>> --- /dev/null
>>> +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
>>> @@ -0,0 +1,205 @@
>>> +/*
>>> + * Universal Flash Storage Host controller driver
>> Please add some comment to indicate that this is platform bus UFS host
>> controller driver.
> The File name itself would identify the nature of driver. can add for more info.
>>> + *
>>> + * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
>>> + * Copyright (C) 2011-2012 Samsung India Software Operations
>>> + *
>>> + * Authors:
>>> + *     Santosh Yaraganavi <santosh.sy@samsung.com>
>>> + *     Vinayak Holikatti <h.vinayak@samsung.com>
>>> + *
>>> + * 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.
>>> + * See the COPYING file in the top-level directory or visit
>>> + * <http://www.gnu.org/licenses/gpl-2.0.html>
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * This program is provided "AS IS" and "WITH ALL FAULTS" and
>>> + * without warranty of any kind. You are solely responsible for
>>> + * determining the appropriateness of using and distributing
>>> + * the program and assume all risks associated with your exercise
>>> + * of rights with respect to the program, including but not limited
>>> + * to infringement of third party rights, the risks and costs of
>>> + * program errors, damage to or loss of data, programs or equipment,
>>> + * and unavailability or interruption of operations. Under no
>>> + * circumstances will the contributor of this Program be liable for
>>> + * any damages of any kind arising from your use or distribution of
>>> + * this program.
>>> + */
>>> +
>>> +#include "ufshcd.h"
>>> +#include <linux/platform_device.h>
>>> +
>>> +#ifdef CONFIG_PM
>>> +/**
>>> + * ufshcd_pltfrm_suspend - suspend power management function
>>> + * @pdev: pointer to Platform device handle
>>> + * @mesg: power state
>>> + *
>>> + * Returns -ENOSYS
>>> + */
>>> +static int ufshcd_pltfrm_suspend(struct platform_device *pdev,
>>> +                                pm_message_t mesg)
>>> +{
>>> +       /*
>>> +        * TODO:
>>> +        * 1. Call ufshcd_suspend
>>> +        * 2. Do bus specific power management
>>> +        */
>>> +
>>> +       return -ENOSYS;
>>> +}
>>> +
>>> +/**
>>> + * ufshcd_pltfrm_resume - resume power management function
>>> + * @pdev: pointer to Platform device handle
>>> + *
>>> + * Returns -ENOSYS
>>> + */
>>> +static int ufshcd_pltfrm_resume(struct platform_device *pdev)
>>> +{
>>> +       /*
>>> +        * TODO:
>>> +        * 1. Call ufshcd_resume.
>>> +        * 2. Do bus specific wake up
>>> +        */
>>> +
>>> +       return -ENOSYS;
>>> +}
>>> +#endif
>>> +
>>> +/**
>>> + * ufshcd_pltfrm_probe - probe routine of the driver
>>> + * @pdev: pointer to Platform device handle
>>> + *
>>> + * Returns 0 on success, non-zero value on failure
>>> + */
>>> +static int __devinit
>>> +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;
>>> +       struct device *dev = &pdev->dev;
>>> +
>>> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +       if (!mem_res) {
>>> +               dev_err(&pdev->dev,
>>> +                       "%s: Memory resource not available\n", __FILE__);
>> Why would we print the file name? Won't the device name prefix enough in
>> debug message?
> File name would be necessary for faster debugging
>>> +               err = -ENODEV;
>>> +               goto out_error;
>>> +       }
>>> +
>>> +       mem_size = resource_size(mem_res);
>>> +       if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
>> you may want to use the UFSHCD macro:   s/"ufshcd"/UFSHCD
>>
>>> +               dev_err(&pdev->dev,
>>> +                       "ufshcd: Cannot reserve the memory resource\n");
>>
>> "ufshcd:" prefix may not be required here as the device name prefix should
>> be enough to know the context of the error.
> "ufshcd:" Can be removed.
>>> +               err = -EBUSY;
>>> +               goto out_error;
>>> +       }
>>> +
>>> +       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, "ufshcd: IRQ resource not
>>> available\n");
>>
>> Same as above. "ufshcd:" prefix may not be required here as the device name
>> prefix should be enough to know the context of the error.
> can be removed.
>>> +               err = -ENODEV;
>>> +               goto out_iounmap;
>>> +       }
>>> +
>>> +       err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
>>> +       if (err) {
>>> +               dev_err(&pdev->dev, "set dma mask failed\n");
>>> +               goto out_iounmap;
>>> +       }
>>> +
>>> +       err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
>>> +       if (err) {
>>> +               dev_err(&pdev->dev, "%s: Intialization failed\n",
>>> +                       __FILE__);
>>
>> Again, not sure why we would need to prefix the file name here.
> __FILE__ is necessary for faster debugging
>>> +               goto out_iounmap;
>>> +       }
>>> +
>>> +       platform_set_drvdata(pdev, hba);
>>> +
>>> +       return 0;
>>> +
>>> +out_iounmap:
>>> +       iounmap(mmio_base);
>>> +out_release_regions:
>>> +       release_mem_region(mem_res->start, mem_size);
>>> +out_error:
>>> +       return err;
>>> +}
>>> +
>>> +/**
>>> + * ufshcd_pltfrm_remove - remove platform driver routine
>>> + * @pdev: pointer to platform device handle
>>> + *
>>> + * Returns 0 on success, non-zero value on failure
>>> + */
>>> +static int __devexit ufshcd_pltfrm_remove(struct platform_device *pdev)
>>> +{
>>> +       struct resource *mem_res;
>>> +       struct resource *irq_res;
>>> +       resource_size_t mem_size;
>>> +       struct ufs_hba *hba =  platform_get_drvdata(pdev);
>>> +
>>> +       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>> It would be better to save the irq number under "struct ufs_hba" during
>> probe. So here during remove you just need simply need to call the
>> "free_irq(irq_res->start, hba)"
> Will modify the code accordingly in the next patchset.
>>> +
>>> +       if (!irq_res)
>>> +               dev_err(&pdev->dev, "ufshcd: IRQ resource not
>>> available\n");
>>> +       else
>>> +               free_irq(irq_res->start, hba);
>>> +
>>> +       ufshcd_remove(hba);
>> Remove should be exactly opposite of probe(). So shouldn't you call the
>> ufshcd_remove() first and then free_irq() after that.
> Some bugging controllers might raise the interrupt after resources are removed.
> this sequence will prevent it.

Could you please add the same as comment in above code sequence?

>>> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> You might want to save the pointer to mem_res in "struct ufs_hba" during
>> probe and may use the same here.
>>> +       if (!mem_res)
>>> +               dev_err(&pdev->dev, "ufshcd: Memory resource not
>>> available\n");
>>> +       else {
>>> +               mem_size = resource_size(mem_res);
>>> +               release_mem_region(mem_res->start, mem_size);
>>> +       }
>>> +       platform_set_drvdata(pdev, NULL);
>>> +       return 0;
>>> +}
>>> +
>>> +static const struct of_device_id ufs_of_match[] = {
>>> +       { .compatible = "jedec,ufs-1.1"},
>>> +};
>>> +
>>> +static struct platform_driver ufshcd_pltfrm_driver = {
>>> +       .probe  = ufshcd_pltfrm_probe,
>>> +       .remove = __devexit_p(ufshcd_pltfrm_remove),
>>> +#ifdef CONFIG_PM
>>> +       .suspend = ufshcd_pltfrm_suspend,
>>> +       .resume = ufshcd_pltfrm_resume,
>>> +#endif
>>> +       .driver = {
>>> +               .name   = "ufshcd",
>>> +               .owner  = THIS_MODULE,
>>> +               .of_match_table = ufs_of_match,
>>> +       },
>>> +};
>>> +
>>> +module_platform_driver(ufshcd_pltfrm_driver);
>>> +
>>> +MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
>>> +MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
>>> +MODULE_DESCRIPTION("Platform based UFS host controller driver");
>>
>> s/"Platform based"/"Platform Bus based"
>>
>>> +MODULE_LICENSE("GPL");
>>> +MODULE_VERSION(UFSHCD_DRIVER_VERSION);
>> You want to keep the same driver version as the UFS core driver?
>>


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

* Re: [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd
  2013-01-06 17:36       ` Subhash Jadavani
@ 2013-01-07  7:41         ` Sujit Reddy Thumma
  2013-01-09 12:11           ` vinayak holikatti
  0 siblings, 1 reply; 16+ messages in thread
From: Sujit Reddy Thumma @ 2013-01-07  7:41 UTC (permalink / raw)
  To: Subhash Jadavani, vinayak holikatti
  Cc: james.bottomley, linux-scsi, santoshsy

Hi Vinayak,

I have few comments below:


 >>>> +#ifdef CONFIG_PM
 >>>> +/**
 >>>> + * ufshcd_pltfrm_suspend - suspend power management function
 >>>> + * @pdev: pointer to Platform device handle
 >>>> + * @mesg: power state
 >>>> + *
 >>>> + * Returns -ENOSYS

What breaks if you return 0 instead of return -ENOSYS? Returning error 
seems to break platform suspend/resume until all the TODO's are 
addressed. If the current s/w cannot make h/w suspend, it should be okay 
to let the rest of the system be suspended.

 >>>> + */
 >>>> +static int ufshcd_pltfrm_suspend(struct platform_device *pdev,
 >>>> +                                pm_message_t mesg)
 >>>> +{
 >>>> +       /*
 >>>> +        * TODO:
 >>>> +        * 1. Call ufshcd_suspend
 >>>> +        * 2. Do bus specific power management
 >>>> +        */
 >>>> +
 >>>> +       return -ENOSYS;

Returning error doesn't allow entire system to be suspended. Perhaps, 
you can do disable_irq() and return 0?

 >>>> +}
 >>>> +
 >>>> +/**
 >>>> + * ufshcd_pltfrm_resume - resume power management function
 >>>> + * @pdev: pointer to Platform device handle
 >>>> + *
 >>>> + * Returns -ENOSYS
 >>>> + */
 >>>> +static int ufshcd_pltfrm_resume(struct platform_device *pdev)
 >>>> +{
 >>>> +       /*
 >>>> +        * TODO:
 >>>> +        * 1. Call ufshcd_resume.
 >>>> +        * 2. Do bus specific wake up
 >>>> +        */
 >>>> +
 >>>> +       return -ENOSYS;

enable_irq() and return 0?

 >>>> +}
 >>>> +#endif
 >>>> +

>>>> +static int __devexit ufshcd_pltfrm_remove(struct platform_device
>>>> *pdev)
>>>> +{
>>>> +       struct resource *mem_res;
>>>> +       struct resource *irq_res;
>>>> +       resource_size_t mem_size;
>>>> +       struct ufs_hba *hba =  platform_get_drvdata(pdev);
>>>> +
>>>> +       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>>> It would be better to save the irq number under "struct ufs_hba" during
>>> probe. So here during remove you just need simply need to call the
>>> "free_irq(irq_res->start, hba)"
>> Will modify the code accordingly in the next patchset.
>>>> +
>>>> +       if (!irq_res)
>>>> +               dev_err(&pdev->dev, "ufshcd: IRQ resource not
>>>> available\n");
>>>> +       else
>>>> +               free_irq(irq_res->start, hba);

The documentation of free_irq says:
"... On a shared IRQ the caller must ensure the interrupt is disabled on 
the card it drives before calling this function. .." I don't see 
disable_irq() getting called either here or ufshcd_remove().


>>>> +
>>>> +       ufshcd_remove(hba);
>>> Remove should be exactly opposite of probe(). So shouldn't you call the
>>> ufshcd_remove() first and then free_irq() after that.
>> Some bugging controllers might raise the interrupt after resources are
>> removed.
>> this sequence will prevent it.
>
> Could you please add the same as comment in above code sequence?
>
>>>> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> You might want to save the pointer to mem_res in "struct ufs_hba" during
>>> probe and may use the same here.
>>>> +       if (!mem_res)
>>>> +               dev_err(&pdev->dev, "ufshcd: Memory resource not
>>>> available\n");
>>>> +       else {
>>>> +               mem_size = resource_size(mem_res);
>>>> +               release_mem_region(mem_res->start, mem_size);
>>>> +       }
>>>> +       platform_set_drvdata(pdev, NULL);
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static const struct of_device_id ufs_of_match[] = {
>>>> +       { .compatible = "jedec,ufs-1.1"},
>>>> +};
>>>> +
>>>> +static struct platform_driver ufshcd_pltfrm_driver = {
>>>> +       .probe  = ufshcd_pltfrm_probe,
>>>> +       .remove = __devexit_p(ufshcd_pltfrm_remove),
>>>> +#ifdef CONFIG_PM

CONFIG_PM_SLEEP would be better? Also, can you move legacy 
suspend/resume callbacks below to dev_pm_ops?

>>>> +       .suspend = ufshcd_pltfrm_suspend,
>>>> +       .resume = ufshcd_pltfrm_resume,
>>>> +#endif
>>>> +       .driver = {
>>>> +               .name   = "ufshcd",
>>>> +               .owner  = THIS_MODULE,
>>>> +               .of_match_table = ufs_of_match,
>>>> +       },
>>>> +};

-- 
Regards,
Sujit Reddy Thumma

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

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

* Re: [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd
  2013-01-07  7:41         ` Sujit Reddy Thumma
@ 2013-01-09 12:11           ` vinayak holikatti
  2013-01-11 10:41             ` Sujit Reddy Thumma
  0 siblings, 1 reply; 16+ messages in thread
From: vinayak holikatti @ 2013-01-09 12:11 UTC (permalink / raw)
  To: Sujit Reddy Thumma
  Cc: Subhash Jadavani, james.bottomley, linux-scsi, santoshsy

On Mon, Jan 7, 2013 at 1:11 PM, Sujit Reddy Thumma
<sthumma@codeaurora.org> wrote:
> Hi Vinayak,
>
> I have few comments below:
>
>
>>>>> +#ifdef CONFIG_PM
>>>>> +/**
>>>>> + * ufshcd_pltfrm_suspend - suspend power management function
>>>>> + * @pdev: pointer to Platform device handle
>>>>> + * @mesg: power state
>>>>> + *
>>>>> + * Returns -ENOSYS
>
> What breaks if you return 0 instead of return -ENOSYS? Returning error seems
> to break platform suspend/resume until all the TODO's are addressed. If the
> current s/w cannot make h/w suspend, it should be okay to let the rest of
> the system be suspended.
>

In that case how will the controller be in a working state once it resumes.
It does not make sense to return zero and to notify the OS that
everything is fine.

>>>>> + */
>>>>> +static int ufshcd_pltfrm_suspend(struct platform_device *pdev,
>>>>> +                                pm_message_t mesg)
>>>>> +{
>>>>> +       /*
>>>>> +        * TODO:
>>>>> +        * 1. Call ufshcd_suspend
>>>>> +        * 2. Do bus specific power management
>>>>> +        */
>>>>> +
>>>>> +       return -ENOSYS;
>
> Returning error doesn't allow entire system to be suspended. Perhaps, you
> can do disable_irq() and return 0?
>
>>>>> +}
>>>>> +
>>>>> +/**
>>>>> + * ufshcd_pltfrm_resume - resume power management function
>>>>> + * @pdev: pointer to Platform device handle
>>>>> + *
>>>>> + * Returns -ENOSYS
>>>>> + */
>>>>> +static int ufshcd_pltfrm_resume(struct platform_device *pdev)
>>>>> +{
>>>>> +       /*
>>>>> +        * TODO:
>>>>> +        * 1. Call ufshcd_resume.
>>>>> +        * 2. Do bus specific wake up
>>>>> +        */
>>>>> +
>>>>> +       return -ENOSYS;
>
> enable_irq() and return 0?
>
>>>>> +}
>>>>> +#endif
>>>>> +
>
>>>>> +static int __devexit ufshcd_pltfrm_remove(struct platform_device
>>>>> *pdev)
>>>>> +{
>>>>> +       struct resource *mem_res;
>>>>> +       struct resource *irq_res;
>>>>> +       resource_size_t mem_size;
>>>>> +       struct ufs_hba *hba =  platform_get_drvdata(pdev);
>>>>> +
>>>>> +       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>>>>
>>>> It would be better to save the irq number under "struct ufs_hba" during
>>>> probe. So here during remove you just need simply need to call the
>>>> "free_irq(irq_res->start, hba)"
>>>
>>> Will modify the code accordingly in the next patchset.
>>>>>
>>>>> +
>>>>> +       if (!irq_res)
>>>>> +               dev_err(&pdev->dev, "ufshcd: IRQ resource not
>>>>> available\n");
>>>>> +       else
>>>>> +               free_irq(irq_res->start, hba);
>
>
> The documentation of free_irq says:
> "... On a shared IRQ the caller must ensure the interrupt is disabled on the
> card it drives before calling this function. .." I don't see disable_irq()
> getting called either here or ufshcd_remove().

Why would you want to disable the entire IRQ line when it is shared?
Logical thing is to disable the interrupt on the controller.

>
>
>>>>> +
>>>>> +       ufshcd_remove(hba);
>>>>
>>>> Remove should be exactly opposite of probe(). So shouldn't you call the
>>>> ufshcd_remove() first and then free_irq() after that.
>>>
>>> Some bugging controllers might raise the interrupt after resources are
>>> removed.
>>> this sequence will prevent it.
>>
>>
>> Could you please add the same as comment in above code sequence?
>>
>>>>> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>
>>>> You might want to save the pointer to mem_res in "struct ufs_hba" during
>>>> probe and may use the same here.
>>>>>
>>>>> +       if (!mem_res)
>>>>> +               dev_err(&pdev->dev, "ufshcd: Memory resource not
>>>>> available\n");
>>>>> +       else {
>>>>> +               mem_size = resource_size(mem_res);
>>>>> +               release_mem_region(mem_res->start, mem_size);
>>>>> +       }
>>>>> +       platform_set_drvdata(pdev, NULL);
>>>>> +       return 0;
>>>>> +}
>>>>> +
>>>>> +static const struct of_device_id ufs_of_match[] = {
>>>>> +       { .compatible = "jedec,ufs-1.1"},
>>>>> +};
>>>>> +
>>>>> +static struct platform_driver ufshcd_pltfrm_driver = {
>>>>> +       .probe  = ufshcd_pltfrm_probe,
>>>>> +       .remove = __devexit_p(ufshcd_pltfrm_remove),
>>>>> +#ifdef CONFIG_PM
>
>
> CONFIG_PM_SLEEP would be better?

the current implementation looks fine.

>Also, can you move legacy suspend/resume

Ok,

> callbacks below to dev_pm_ops?
>
>>>>> +       .suspend = ufshcd_pltfrm_suspend,
>>>>> +       .resume = ufshcd_pltfrm_resume,
>>>>> +#endif
>>>>> +       .driver = {
>>>>> +               .name   = "ufshcd",
>>>>> +               .owner  = THIS_MODULE,
>>>>> +               .of_match_table = ufs_of_match,
>>>>> +       },
>>>>> +};
>
>
> --
> Regards,
> Sujit Reddy Thumma
>
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation.



-- 
Regards,
Vinayak Holikatti

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

* Re: [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd
  2013-01-09 12:11           ` vinayak holikatti
@ 2013-01-11 10:41             ` Sujit Reddy Thumma
  2013-01-11 12:30               ` Subhash Jadavani
  0 siblings, 1 reply; 16+ messages in thread
From: Sujit Reddy Thumma @ 2013-01-11 10:41 UTC (permalink / raw)
  To: vinayak holikatti
  Cc: Subhash Jadavani, james.bottomley, linux-scsi, santoshsy

On 1/9/2013 5:41 PM, vinayak holikatti wrote:
> On Mon, Jan 7, 2013 at 1:11 PM, Sujit Reddy Thumma
> <sthumma@codeaurora.org> wrote:
>> Hi Vinayak,
>>
>> I have few comments below:
>>
>>
>>>>>> +#ifdef CONFIG_PM
>>>>>> +/**
>>>>>> + * ufshcd_pltfrm_suspend - suspend power management function
>>>>>> + * @pdev: pointer to Platform device handle
>>>>>> + * @mesg: power state
>>>>>> + *
>>>>>> + * Returns -ENOSYS
>>
>> What breaks if you return 0 instead of return -ENOSYS? Returning error seems
>> to break platform suspend/resume until all the TODO's are addressed. If the
>> current s/w cannot make h/w suspend, it should be okay to let the rest of
>> the system be suspended.
>>
>
> In that case how will the controller be in a working state once it resumes.
> It does not make sense to return zero and to notify the OS that
> everything is fine.

Since the suspend routine doesn't do anything except returning zero, no 
power/clocks would be removed and the controller should be in the same 
state after resume. Do you see any system that removes power/clocks to 
controllers during suspend without knowledge of corresponding drivers? 
If so, then such systems must be fixed. In any case, blocking entire 
system suspend just because s/w isn't taking care of powering down one 
controller is not a good idea.

I would like to hear from others on this as well.

>
>>>>>> + */
>>>>>> +static int ufshcd_pltfrm_suspend(struct platform_device *pdev,
>>>>>> +                                pm_message_t mesg)
>>>>>> +{
>>>>>> +       /*
>>>>>> +        * TODO:
>>>>>> +        * 1. Call ufshcd_suspend
>>>>>> +        * 2. Do bus specific power management
>>>>>> +        */
>>>>>> +
>>>>>> +       return -ENOSYS;
>>
>> Returning error doesn't allow entire system to be suspended. Perhaps, you
>> can do disable_irq() and return 0?
>>
>>>>>> +}
>>>>>> +
>>>>>> +/**
>>>>>> + * ufshcd_pltfrm_resume - resume power management function
>>>>>> + * @pdev: pointer to Platform device handle
>>>>>> + *
>>>>>> + * Returns -ENOSYS
>>>>>> + */
>>>>>> +static int ufshcd_pltfrm_resume(struct platform_device *pdev)
>>>>>> +{
>>>>>> +       /*
>>>>>> +        * TODO:
>>>>>> +        * 1. Call ufshcd_resume.
>>>>>> +        * 2. Do bus specific wake up
>>>>>> +        */
>>>>>> +
>>>>>> +       return -ENOSYS;
>>
>> enable_irq() and return 0?
>>
>>>>>> +}
>>>>>> +#endif
>>>>>> +
>>
>>>>>> +static int __devexit ufshcd_pltfrm_remove(struct platform_device
>>>>>> *pdev)
>>>>>> +{
>>>>>> +       struct resource *mem_res;
>>>>>> +       struct resource *irq_res;
>>>>>> +       resource_size_t mem_size;
>>>>>> +       struct ufs_hba *hba =  platform_get_drvdata(pdev);
>>>>>> +
>>>>>> +       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>>>>>
>>>>> It would be better to save the irq number under "struct ufs_hba" during
>>>>> probe. So here during remove you just need simply need to call the
>>>>> "free_irq(irq_res->start, hba)"
>>>>
>>>> Will modify the code accordingly in the next patchset.
>>>>>>
>>>>>> +
>>>>>> +       if (!irq_res)
>>>>>> +               dev_err(&pdev->dev, "ufshcd: IRQ resource not
>>>>>> available\n");
>>>>>> +       else
>>>>>> +               free_irq(irq_res->start, hba);
>>
>>
>> The documentation of free_irq says:
>> "... On a shared IRQ the caller must ensure the interrupt is disabled on the
>> card it drives before calling this function. .." I don't see disable_irq()
>> getting called either here or ufshcd_remove().
>
> Why would you want to disable the entire IRQ line when it is shared?
> Logical thing is to disable the interrupt on the controller.

Since you have enabled the irq in ufshcd_init() and decremented the 
desc->depth you need to need to do disable_irq(). disable_irq() doesn't 
disable the irq line until all the shared irq drivers disables it.

Also, on some systems not calling disable_irq() could be a problem - the 
power to wakeup irq monitor block couldn't be turned off if there are 
active irqs.

>
>>
>>
>>>>>> +
>>>>>> +       ufshcd_remove(hba);
>>>>>
>>>>> Remove should be exactly opposite of probe(). So shouldn't you call the
>>>>> ufshcd_remove() first and then free_irq() after that.
>>>>
>>>> Some bugging controllers might raise the interrupt after resources are
>>>> removed.
>>>> this sequence will prevent it.
>>>
>>>
>>> Could you please add the same as comment in above code sequence?
>>>
>>>>>> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>
>>>>> You might want to save the pointer to mem_res in "struct ufs_hba" during
>>>>> probe and may use the same here.
>>>>>>
>>>>>> +       if (!mem_res)
>>>>>> +               dev_err(&pdev->dev, "ufshcd: Memory resource not
>>>>>> available\n");
>>>>>> +       else {
>>>>>> +               mem_size = resource_size(mem_res);
>>>>>> +               release_mem_region(mem_res->start, mem_size);
>>>>>> +       }
>>>>>> +       platform_set_drvdata(pdev, NULL);
>>>>>> +       return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static const struct of_device_id ufs_of_match[] = {
>>>>>> +       { .compatible = "jedec,ufs-1.1"},
>>>>>> +};
>>>>>> +
>>>>>> +static struct platform_driver ufshcd_pltfrm_driver = {
>>>>>> +       .probe  = ufshcd_pltfrm_probe,
>>>>>> +       .remove = __devexit_p(ufshcd_pltfrm_remove),
>>>>>> +#ifdef CONFIG_PM
>>
>>
>> CONFIG_PM_SLEEP would be better?
>
> the current implementation looks fine.
>
>> Also, can you move legacy suspend/resume
>
> Ok,
>
>> callbacks below to dev_pm_ops?
>>
>>>>>> +       .suspend = ufshcd_pltfrm_suspend,
>>>>>> +       .resume = ufshcd_pltfrm_resume,
>>>>>> +#endif
>>>>>> +       .driver = {
>>>>>> +               .name   = "ufshcd",
>>>>>> +               .owner  = THIS_MODULE,
>>>>>> +               .of_match_table = ufs_of_match,
>>>>>> +       },
>>>>>> +};
>>
>>
>> --
>> Regards,
>> Sujit Reddy Thumma
>>
>> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
>> of Code Aurora Forum, hosted by The Linux Foundation.
>
>
>



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

* Re: [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd
  2013-01-11 10:41             ` Sujit Reddy Thumma
@ 2013-01-11 12:30               ` Subhash Jadavani
  2013-01-16 15:54                 ` vinayak holikatti
  0 siblings, 1 reply; 16+ messages in thread
From: Subhash Jadavani @ 2013-01-11 12:30 UTC (permalink / raw)
  To: Sujit Reddy Thumma
  Cc: vinayak holikatti, james.bottomley, linux-scsi, santoshsy

On 1/11/2013 4:11 PM, Sujit Reddy Thumma wrote:
> On 1/9/2013 5:41 PM, vinayak holikatti wrote:
>> On Mon, Jan 7, 2013 at 1:11 PM, Sujit Reddy Thumma
>> <sthumma@codeaurora.org> wrote:
>>> Hi Vinayak,
>>>
>>> I have few comments below:
>>>
>>>
>>>>>>> +#ifdef CONFIG_PM
>>>>>>> +/**
>>>>>>> + * ufshcd_pltfrm_suspend - suspend power management function
>>>>>>> + * @pdev: pointer to Platform device handle
>>>>>>> + * @mesg: power state
>>>>>>> + *
>>>>>>> + * Returns -ENOSYS
>>>
>>> What breaks if you return 0 instead of return -ENOSYS? Returning 
>>> error seems
>>> to break platform suspend/resume until all the TODO's are addressed. 
>>> If the
>>> current s/w cannot make h/w suspend, it should be okay to let the 
>>> rest of
>>> the system be suspended.
>>>
>>
>> In that case how will the controller be in a working state once it 
>> resumes.
>> It does not make sense to return zero and to notify the OS that
>> everything is fine.
>
> Since the suspend routine doesn't do anything except returning zero, 
> no power/clocks would be removed and the controller should be in the 
> same state after resume. Do you see any system that removes 
> power/clocks to controllers during suspend without knowledge of 
> corresponding drivers? If so, then such systems must be fixed. In any 
> case, blocking entire system suspend just because s/w isn't taking 
> care of powering down one controller is not a good idea.
>
> I would like to hear from others on this as well.

Yes, i agree with Sujit that there is no point in blocking the entire 
system suspend just because ufshcd haven't implemented their suspend 
functionality. returning 0 from this function should be fine. And as 
Sujit already mentioned, if during resume you don't find the UFS 
(controller / phy) state as it was left in suspend then it's a 
particular system's issue and which needs to be fixed.

>
>>
>>>>>>> + */
>>>>>>> +static int ufshcd_pltfrm_suspend(struct platform_device *pdev,
>>>>>>> +                                pm_message_t mesg)
>>>>>>> +{
>>>>>>> +       /*
>>>>>>> +        * TODO:
>>>>>>> +        * 1. Call ufshcd_suspend
>>>>>>> +        * 2. Do bus specific power management
>>>>>>> +        */
>>>>>>> +
>>>>>>> +       return -ENOSYS;
>>>
>>> Returning error doesn't allow entire system to be suspended. 
>>> Perhaps, you
>>> can do disable_irq() and return 0?
>>>
>>>>>>> +}
>>>>>>> +
>>>>>>> +/**
>>>>>>> + * ufshcd_pltfrm_resume - resume power management function
>>>>>>> + * @pdev: pointer to Platform device handle
>>>>>>> + *
>>>>>>> + * Returns -ENOSYS
>>>>>>> + */
>>>>>>> +static int ufshcd_pltfrm_resume(struct platform_device *pdev)
>>>>>>> +{
>>>>>>> +       /*
>>>>>>> +        * TODO:
>>>>>>> +        * 1. Call ufshcd_resume.
>>>>>>> +        * 2. Do bus specific wake up
>>>>>>> +        */
>>>>>>> +
>>>>>>> +       return -ENOSYS;
>>>
>>> enable_irq() and return 0?
>>>
>>>>>>> +}
>>>>>>> +#endif
>>>>>>> +
>>>
>>>>>>> +static int __devexit ufshcd_pltfrm_remove(struct platform_device
>>>>>>> *pdev)
>>>>>>> +{
>>>>>>> +       struct resource *mem_res;
>>>>>>> +       struct resource *irq_res;
>>>>>>> +       resource_size_t mem_size;
>>>>>>> +       struct ufs_hba *hba = platform_get_drvdata(pdev);
>>>>>>> +
>>>>>>> +       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>>>>>>
>>>>>> It would be better to save the irq number under "struct ufs_hba" 
>>>>>> during
>>>>>> probe. So here during remove you just need simply need to call the
>>>>>> "free_irq(irq_res->start, hba)"
>>>>>
>>>>> Will modify the code accordingly in the next patchset.
>>>>>>>
>>>>>>> +
>>>>>>> +       if (!irq_res)
>>>>>>> +               dev_err(&pdev->dev, "ufshcd: IRQ resource not
>>>>>>> available\n");
>>>>>>> +       else
>>>>>>> +               free_irq(irq_res->start, hba);
>>>
>>>
>>> The documentation of free_irq says:
>>> "... On a shared IRQ the caller must ensure the interrupt is 
>>> disabled on the
>>> card it drives before calling this function. .." I don't see 
>>> disable_irq()
>>> getting called either here or ufshcd_remove().
>>
>> Why would you want to disable the entire IRQ line when it is shared?
>> Logical thing is to disable the interrupt on the controller.
>
> Since you have enabled the irq in ufshcd_init() and decremented the 
> desc->depth you need to need to do disable_irq(). disable_irq() 
> doesn't disable the irq line until all the shared irq drivers disables 
> it.
>
> Also, on some systems not calling disable_irq() could be a problem - 
> the power to wakeup irq monitor block couldn't be turned off if there 
> are active irqs.
>
>>
>>>
>>>
>>>>>>> +
>>>>>>> +       ufshcd_remove(hba);
>>>>>>
>>>>>> Remove should be exactly opposite of probe(). So shouldn't you 
>>>>>> call the
>>>>>> ufshcd_remove() first and then free_irq() after that.
>>>>>
>>>>> Some bugging controllers might raise the interrupt after resources 
>>>>> are
>>>>> removed.
>>>>> this sequence will prevent it.
>>>>
>>>>
>>>> Could you please add the same as comment in above code sequence?
>>>>
>>>>>>> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>>
>>>>>> You might want to save the pointer to mem_res in "struct ufs_hba" 
>>>>>> during
>>>>>> probe and may use the same here.
>>>>>>>
>>>>>>> +       if (!mem_res)
>>>>>>> +               dev_err(&pdev->dev, "ufshcd: Memory resource not
>>>>>>> available\n");
>>>>>>> +       else {
>>>>>>> +               mem_size = resource_size(mem_res);
>>>>>>> +               release_mem_region(mem_res->start, mem_size);
>>>>>>> +       }
>>>>>>> +       platform_set_drvdata(pdev, NULL);
>>>>>>> +       return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static const struct of_device_id ufs_of_match[] = {
>>>>>>> +       { .compatible = "jedec,ufs-1.1"},
>>>>>>> +};
>>>>>>> +
>>>>>>> +static struct platform_driver ufshcd_pltfrm_driver = {
>>>>>>> +       .probe  = ufshcd_pltfrm_probe,
>>>>>>> +       .remove = __devexit_p(ufshcd_pltfrm_remove),
>>>>>>> +#ifdef CONFIG_PM
>>>
>>>
>>> CONFIG_PM_SLEEP would be better?
>>
>> the current implementation looks fine.
>>
>>> Also, can you move legacy suspend/resume
>>
>> Ok,
>>
>>> callbacks below to dev_pm_ops?
>>>
>>>>>>> +       .suspend = ufshcd_pltfrm_suspend,
>>>>>>> +       .resume = ufshcd_pltfrm_resume,
>>>>>>> +#endif
>>>>>>> +       .driver = {
>>>>>>> +               .name   = "ufshcd",
>>>>>>> +               .owner  = THIS_MODULE,
>>>>>>> +               .of_match_table = ufs_of_match,
>>>>>>> +       },
>>>>>>> +};
>>>
>>>
>>> -- 
>>> Regards,
>>> Sujit Reddy Thumma
>>>
>>> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a 
>>> member
>>> of Code Aurora Forum, hosted by The Linux Foundation.
>>
>>
>>
>
>
> -- 
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* Re: [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd
  2013-01-11 12:30               ` Subhash Jadavani
@ 2013-01-16 15:54                 ` vinayak holikatti
  0 siblings, 0 replies; 16+ messages in thread
From: vinayak holikatti @ 2013-01-16 15:54 UTC (permalink / raw)
  To: Subhash Jadavani
  Cc: Sujit Reddy Thumma, james.bottomley, linux-scsi, santoshsy

On Fri, Jan 11, 2013 at 6:00 PM, Subhash Jadavani
<subhashj@codeaurora.org> wrote:
> On 1/11/2013 4:11 PM, Sujit Reddy Thumma wrote:
>>
>> On 1/9/2013 5:41 PM, vinayak holikatti wrote:
>>>
>>> On Mon, Jan 7, 2013 at 1:11 PM, Sujit Reddy Thumma
>>> <sthumma@codeaurora.org> wrote:
>>>>
>>>> Hi Vinayak,
>>>>
>>>> I have few comments below:
>>>>
>>>>
>>>>>>>> +#ifdef CONFIG_PM
>>>>>>>> +/**
>>>>>>>> + * ufshcd_pltfrm_suspend - suspend power management function
>>>>>>>> + * @pdev: pointer to Platform device handle
>>>>>>>> + * @mesg: power state
>>>>>>>> + *
>>>>>>>> + * Returns -ENOSYS
>>>>
>>>>
>>>> What breaks if you return 0 instead of return -ENOSYS? Returning error
>>>> seems
>>>> to break platform suspend/resume until all the TODO's are addressed. If
>>>> the
>>>> current s/w cannot make h/w suspend, it should be okay to let the rest
>>>> of
>>>> the system be suspended.
>>>>
>>>
>>> In that case how will the controller be in a working state once it
>>> resumes.
>>> It does not make sense to return zero and to notify the OS that
>>> everything is fine.
>>
>>
>> Since the suspend routine doesn't do anything except returning zero, no
>> power/clocks would be removed and the controller should be in the same state
>> after resume. Do you see any system that removes power/clocks to controllers
>> during suspend without knowledge of corresponding drivers? If so, then such
>> systems must be fixed. In any case, blocking entire system suspend just
>> because s/w isn't taking care of powering down one controller is not a good
>> idea.
>>
>> I would like to hear from others on this as well.
>
>
> Yes, i agree with Sujit that there is no point in blocking the entire system
> suspend just because ufshcd haven't implemented their suspend functionality.
> returning 0 from this function should be fine. And as Sujit already
> mentioned, if during resume you don't find the UFS (controller / phy) state
> as it was left in suspend then it's a particular system's issue and which
> needs to be fixed.
We Implemented Suspend/Resume place holders seeing the kernel documentation
in submitting device drivers
I would like to know if the suggested code change works with any
existing system.
Does any one have similar point of view as Sujit and Subhash have?

>
>>
>>>
>>>>>>>> + */
>>>>>>>> +static int ufshcd_pltfrm_suspend(struct platform_device *pdev,
>>>>>>>> +                                pm_message_t mesg)
>>>>>>>> +{
>>>>>>>> +       /*
>>>>>>>> +        * TODO:
>>>>>>>> +        * 1. Call ufshcd_suspend
>>>>>>>> +        * 2. Do bus specific power management
>>>>>>>> +        */
>>>>>>>> +
>>>>>>>> +       return -ENOSYS;
>>>>
>>>>
>>>> Returning error doesn't allow entire system to be suspended. Perhaps,
>>>> you
>>>> can do disable_irq() and return 0?
>>>>
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + * ufshcd_pltfrm_resume - resume power management function
>>>>>>>> + * @pdev: pointer to Platform device handle
>>>>>>>> + *
>>>>>>>> + * Returns -ENOSYS
>>>>>>>> + */
>>>>>>>> +static int ufshcd_pltfrm_resume(struct platform_device *pdev)
>>>>>>>> +{
>>>>>>>> +       /*
>>>>>>>> +        * TODO:
>>>>>>>> +        * 1. Call ufshcd_resume.
>>>>>>>> +        * 2. Do bus specific wake up
>>>>>>>> +        */
>>>>>>>> +
>>>>>>>> +       return -ENOSYS;
>>>>
>>>>
>>>> enable_irq() and return 0?
>>>>
>>>>>>>> +}
>>>>>>>> +#endif
>>>>>>>> +
>>>>
>>>>
>>>>>>>> +static int __devexit ufshcd_pltfrm_remove(struct platform_device
>>>>>>>> *pdev)
>>>>>>>> +{
>>>>>>>> +       struct resource *mem_res;
>>>>>>>> +       struct resource *irq_res;
>>>>>>>> +       resource_size_t mem_size;
>>>>>>>> +       struct ufs_hba *hba = platform_get_drvdata(pdev);
>>>>>>>> +
>>>>>>>> +       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>>>>>>>
>>>>>>>
>>>>>>> It would be better to save the irq number under "struct ufs_hba"
>>>>>>> during
>>>>>>> probe. So here during remove you just need simply need to call the
>>>>>>> "free_irq(irq_res->start, hba)"
>>>>>>
>>>>>>
>>>>>> Will modify the code accordingly in the next patchset.
>>>>>>>>
>>>>>>>>
>>>>>>>> +
>>>>>>>> +       if (!irq_res)
>>>>>>>> +               dev_err(&pdev->dev, "ufshcd: IRQ resource not
>>>>>>>> available\n");
>>>>>>>> +       else
>>>>>>>> +               free_irq(irq_res->start, hba);
>>>>
>>>>
>>>>
>>>> The documentation of free_irq says:
>>>> "... On a shared IRQ the caller must ensure the interrupt is disabled on
>>>> the
>>>> card it drives before calling this function. .." I don't see
>>>> disable_irq()
>>>> getting called either here or ufshcd_remove().
>>>
>>>
>>> Why would you want to disable the entire IRQ line when it is shared?
>>> Logical thing is to disable the interrupt on the controller.
>>
>>
>> Since you have enabled the irq in ufshcd_init() and decremented the
>> desc->depth you need to need to do disable_irq(). disable_irq() doesn't
>> disable the irq line until all the shared irq drivers disables it.
>>
>> Also, on some systems not calling disable_irq() could be a problem - the
>> power to wakeup irq monitor block couldn't be turned off if there are active
>> irqs.
>>
>>>
>>>>
>>>>
>>>>>>>> +
>>>>>>>> +       ufshcd_remove(hba);
>>>>>>>
>>>>>>>
>>>>>>> Remove should be exactly opposite of probe(). So shouldn't you call
>>>>>>> the
>>>>>>> ufshcd_remove() first and then free_irq() after that.
>>>>>>
>>>>>>
>>>>>> Some bugging controllers might raise the interrupt after resources are
>>>>>> removed.
>>>>>> this sequence will prevent it.
>>>>>
>>>>>
>>>>>
>>>>> Could you please add the same as comment in above code sequence?
>>>>>
>>>>>>>> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>>>
>>>>>>>
>>>>>>> You might want to save the pointer to mem_res in "struct ufs_hba"
>>>>>>> during
>>>>>>> probe and may use the same here.
>>>>>>>>
>>>>>>>>
>>>>>>>> +       if (!mem_res)
>>>>>>>> +               dev_err(&pdev->dev, "ufshcd: Memory resource not
>>>>>>>> available\n");
>>>>>>>> +       else {
>>>>>>>> +               mem_size = resource_size(mem_res);
>>>>>>>> +               release_mem_region(mem_res->start, mem_size);
>>>>>>>> +       }
>>>>>>>> +       platform_set_drvdata(pdev, NULL);
>>>>>>>> +       return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static const struct of_device_id ufs_of_match[] = {
>>>>>>>> +       { .compatible = "jedec,ufs-1.1"},
>>>>>>>> +};
>>>>>>>> +
>>>>>>>> +static struct platform_driver ufshcd_pltfrm_driver = {
>>>>>>>> +       .probe  = ufshcd_pltfrm_probe,
>>>>>>>> +       .remove = __devexit_p(ufshcd_pltfrm_remove),
>>>>>>>> +#ifdef CONFIG_PM
>>>>
>>>>
>>>>
>>>> CONFIG_PM_SLEEP would be better?
>>>
>>>
>>> the current implementation looks fine.
>>>
>>>> Also, can you move legacy suspend/resume
>>>
>>>
>>> Ok,
>>>
>>>> callbacks below to dev_pm_ops?
>>>>
>>>>>>>> +       .suspend = ufshcd_pltfrm_suspend,
>>>>>>>> +       .resume = ufshcd_pltfrm_resume,
>>>>>>>> +#endif
>>>>>>>> +       .driver = {
>>>>>>>> +               .name   = "ufshcd",
>>>>>>>> +               .owner  = THIS_MODULE,
>>>>>>>> +               .of_match_table = ufs_of_match,
>>>>>>>> +       },
>>>>>>>> +};
>>>>
>>>>
>>>>
>>>> --
>>>> Regards,
>>>> Sujit Reddy Thumma
>>>>
>>>> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a
>>>> member
>>>> of Code Aurora Forum, hosted by The Linux Foundation.
>>>
>>>
>>>
>>>
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>



-- 
Regards,
Vinayak Holikatti

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

end of thread, other threads:[~2013-01-16 15:54 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1356552955-18027-1-git-send-email-y>
2012-12-26 20:15 ` [PATCH V5 1/4] [SCSI] drivers/scsi/ufs: Seggregate PCI Specific Code vinholikatti
2012-12-27 14:29   ` Subhash Jadavani
2013-01-04  7:00     ` vinayak holikatti
2013-01-06 17:32       ` Subhash Jadavani
2012-12-26 20:15 ` [PATCH V5 2/4] [SCSI] drivers/scsi/ufs: Separate PCI code into glue driver vinholikatti
2012-12-27 15:05   ` Subhash Jadavani
2012-12-26 20:15 ` [PATCH V5 3/4] [SCSI] ufs: Add Platform glue driver for ufshcd vinholikatti
2012-12-27 14:58   ` Subhash Jadavani
2013-01-04  7:37     ` vinayak holikatti
2013-01-06 17:36       ` Subhash Jadavani
2013-01-07  7:41         ` Sujit Reddy Thumma
2013-01-09 12:11           ` vinayak holikatti
2013-01-11 10:41             ` Sujit Reddy Thumma
2013-01-11 12:30               ` Subhash Jadavani
2013-01-16 15:54                 ` vinayak holikatti
2012-12-26 20:15 ` [PATCH V5 4/4] [SCSI] ufs: Correct the expected data transfer size vinholikatti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).