On 22 May 2012 10:59, S, Venkatraman <svenkatr@xxxxxx> wrote: > On Mon, May 21, 2012 at 12:01 PM, Girish K S > <girish.shivananjappa@xxxxxxxxxx> wrote: >> The existing driver was pci specific. This patch removes the >> pci specific code from the core driver. Irrespective of the >> pci or non-pci probe, the same core driver can be re-used. >> >> It also creates 2 separate modules of core and pci driver >> >> Signed-off-by: Girish K S <girish.shivananjappa@xxxxxxxxxx> >> --- >> drivers/scsi/ufs/Kconfig | 19 ++- >> drivers/scsi/ufs/Makefile | 1 + >> drivers/scsi/ufs/ufs.h | 103 ++++++++++++ >> drivers/scsi/ufs/ufshcd-pci.c | 206 +++++++++++++++++++++++ >> drivers/scsi/ufs/ufshcd.c | 370 +++++++++++------------------------------ >> 5 files changed, 421 insertions(+), 278 deletions(-) >> create mode 100644 drivers/scsi/ufs/ufshcd-pci.c >> >> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig >> index 8f27f9d..2a70972 100644 >> --- a/drivers/scsi/ufs/Kconfig >> +++ b/drivers/scsi/ufs/Kconfig >> @@ -44,6 +44,19 @@ >> >> config SCSI_UFSHCD >> tristate "Universal Flash Storage host controller driver" >> - depends on PCI && SCSI >> - ---help--- >> - This is a generic driver which supports PCIe UFS Host controllers. >> + depends on SCSI >> + help >> + This is a generic driver which supports UFS Host controllers. >> + This option is selected automatically if the SCSI option is >> + selected. This is a core ufs driver. >> + >> +config SCSI_UFSHCD_PCI >> + tristate "Universal Flash Storage host support on PCI bus" >> + depends on SCSI_UFSHCD && PCI >> + help >> + This selects the PCI bus for the Universal Flash Storage IP. >> + Select this option if the IP is present on PCI platform. >> + >> + 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/ufs.h b/drivers/scsi/ufs/ufs.h >> index b207529..dc36793 100644 >> --- a/drivers/scsi/ufs/ufs.h >> +++ b/drivers/scsi/ufs/ufs.h >> @@ -46,6 +46,8 @@ >> #ifndef _UFS_H >> #define _UFS_H >> >> +#define ufs_hostname(x) (dev_name(&(x)->dev)) >> + >> #define MAX_CDB_SIZE 16 >> >> #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\ >> @@ -204,4 +206,105 @@ struct utp_upiu_task_rsp { >> u32 reserved[3]; >> }; >> >> +/** >> + * 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_pdata { >> + /* TODO */ >> + u32 quirks; /* Quirk flags */ >> +}; >> + >> +/** >> + * 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; >> + >> + unsigned int irq; >> +}; >> + >> +extern int ufshcd_initialize_hba(struct ufs_hba *hba); >> +extern int ufshcd_drv_init(struct ufs_hba **hostdat, struct device *dev, >> + int irq_no, void __iomem *mmio_base); >> +extern void ufshcd_drv_exit(struct ufs_hba *hba); >> +#ifdef CONFIG_PM >> +extern int ufshcd_suspend(struct ufs_hba *hba); >> +extern int ufshcd_resume(struct ufs_hba *hba); >> +#endif /* CONFIG_PM */ >> + >> #endif /* End of Header */ >> diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c >> new file mode 100644 >> index 0000000..e306573 >> --- /dev/null >> +++ b/drivers/scsi/ufs/ufshcd-pci.c >> @@ -0,0 +1,206 @@ >> +/* >> + * Universal Flash Storage Host controller driver >> + * >> + * This code is based on drivers/scsi/ufs/ufshcd.c >> + * Copyright (C) 2011-2012 Samsung India Software Operations >> + * >> + * 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. >> + * >> + * 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. >> + */ >> + >> +#include <linux/interrupt.h> >> +#include <linux/module.h> >> +#include <linux/io.h> >> +#include <linux/pci.h> >> +#include <scsi/scsi_host.h> >> + >> +#include "ufs.h" >> +#include "ufshci.h" >> + >> +/** >> + * ufshcd_pci_set_dma_mask - Set dma mask based on the controller >> + * addressing capability >> + * @ihba: pointer to host platform data >> + * >> + * Returns 0 for success, non-zero for failure >> + */ >> +static int ufshcd_pci_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 >> + */ >> + dma_mask = DMA_BIT_MASK(64); >> + err = pci_set_dma_mask(pdev, dma_mask); >> + if (err) { >> + dma_mask = DMA_BIT_MASK(32); >> + err = pci_set_dma_mask(pdev, dma_mask); >> + } >> + >> + if (err) >> + return err; >> + >> + err = pci_set_consistent_dma_mask(pdev, dma_mask); >> + >> + return err; >> +} >> + >> +static int __devinit ufshcd_pci_probe(struct pci_dev *pdev, >> + const struct pci_device_id *entries) >> +{ >> + struct ufs_hba *uninitialized_var(hba); >> + int err; >> + void __iomem *mmio_base; >> + >> + err = pci_enable_device(pdev); >> + if (err) { >> + dev_err(&pdev->dev, "pci_enable_device failed\n"); >> + goto err_return; >> + } >> + >> + pci_set_master(pdev); >> + >> + err = pci_request_regions(pdev, "ufshcd-pci"); >> + if (err < 0) { >> + dev_err(&pdev->dev, "request regions failed\n"); >> + goto err_disable; >> + } >> + >> + mmio_base = pci_ioremap_bar(pdev, 0); >> + if (!mmio_base) { >> + dev_err(&pdev->dev, "memory map failed\n"); >> + err = -ENOMEM; >> + goto err_release; >> + } >> + >> + err = ufshcd_pci_set_dma_mask(pdev); >> + if (err) { >> + dev_err(&pdev->dev, "set dma mask failed\n"); >> + goto err_iounmap; >> + } >> + >> + err = ufshcd_drv_init(&hba, &pdev->dev, pdev->irq, mmio_base); >> + if (err) >> + goto err_iounmap; >> + >> + pci_set_drvdata(pdev, hba); >> + >> + /* Initialization routine */ >> + err = ufshcd_initialize_hba(hba); >> + if (err) { >> + dev_err(&hba->dev, "Initialization failed\n"); >> + goto err_remove; >> + } >> + >> + return err; >> + >> +err_remove: >> + ufshcd_drv_exit(hba); >> +err_iounmap: >> + iounmap(hba->mmio_base); >> +err_release: >> + pci_release_regions(pdev); >> +err_disable: >> + pci_clear_master(pdev); >> + pci_disable_device(pdev); >> +err_return: >> + return err; >> +} >> + >> +static void __devexit ufshcd_pci_remove(struct pci_dev *pdev) >> +{ >> + struct ufs_hba *hba = pci_get_drvdata(pdev); >> + >> + ufshcd_drv_exit(hba); >> + iounmap(hba->mmio_base); >> + pci_set_drvdata(pdev, NULL); >> + pci_clear_master(pdev); >> + pci_release_regions(pdev); >> + pci_disable_device(pdev); >> +} >> + >> +#ifdef CONFIG_PM >> +static int ufshcd_pci_suspend(struct device *dev) >> +{ >> + int ret; >> + struct pci_dev *pdev = to_pci_dev(dev); >> + struct ufs_hba *hba = pci_get_drvdata(pdev); >> + >> + ret = ufshcd_suspend(hba); >> + return ret; >> +} >> + >> +static int ufshcd_pci_resume(struct device *dev) >> +{ >> + int ret; >> + struct pci_dev *pdev = to_pci_dev(dev); >> + struct ufs_hba *hba = pci_get_drvdata(pdev); >> + >> + ret = ufshcd_resume(hba); >> + return ret; >> +} >> +#else >> +#define ufshcd_pci_suspend NULL >> +#define ufshcd_pci_resume NULL >> +#endif /* CONFIG_PM */ >> + >> +static SIMPLE_DEV_PM_OPS(ufshcd_pci_pmops, >> + ufshcd_pci_suspend, >> + ufshcd_pci_resume); >> + >> +static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_id) = { >> + { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, >> + {} >> +}; >> +MODULE_DEVICE_TABLE(pci, ufshcd_pci_id); >> + >> +static struct pci_driver ufshcd_pci_driver = { >> + .name = "ufshcd-pci", >> + .id_table = ufshcd_pci_id, >> + .probe = ufshcd_pci_probe, >> + .remove = __devexit_p(ufshcd_pci_remove), >> + .driver = { >> + .pm = &ufshcd_pci_pmops >> + }, >> +}; >> + >> +module_pci_driver(ufshcd_pci_driver); >> + >> +MODULE_DESCRIPTION("UFS Host Controller PCI Interface driver"); >> +MODULE_AUTHOR("Girish K S <ks.giri@xxxxxxxxxxx>"); >> +MODULE_LICENSE("GPL"); >> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c >> index e47a0da..4cfbfc5 100644 >> --- a/drivers/scsi/ufs/ufshcd.c >> +++ b/drivers/scsi/ufs/ufshcd.c >> @@ -46,7 +46,6 @@ >> #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> >> @@ -102,91 +101,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 >> - * @pdev: PCI 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 pci_dev *pdev; >> - >> - 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 >> @@ -335,21 +249,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 +638,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 +651,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 +661,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 +677,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 +691,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 +781,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 +826,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 +838,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 +919,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; >> } >> @@ -1015,37 +929,6 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) >> } >> >> /** >> - * ufshcd_initialize_hba - start the initialization process >> - * @hba: per adapter instance >> - * >> - * 1. Enable the controller via ufshcd_hba_enable. >> - * 2. Program the Transfer Request List Address with the starting address of >> - * UTRDL. >> - * 3. Program the Task Management Request List Address with starting address >> - * of UTMRDL. >> - * >> - * Returns 0 on success, non-zero value on failure. >> - */ >> -static int ufshcd_initialize_hba(struct ufs_hba *hba) >> -{ >> - if (ufshcd_hba_enable(hba)) >> - return -EIO; >> - >> - /* Configure UTRL and UTMRL base address registers */ >> - writel(lower_32_bits(hba->utrdl_dma_addr), >> - (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L)); >> - writel(upper_32_bits(hba->utrdl_dma_addr), >> - (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H)); >> - writel(lower_32_bits(hba->utmrdl_dma_addr), >> - (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L)); >> - writel(upper_32_bits(hba->utmrdl_dma_addr), >> - (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H)); >> - >> - /* Initialize unipro link startup procedure */ >> - return ufshcd_dme_link_startup(hba); >> -} >> - >> -/** >> * ufshcd_do_reset - reset the host controller >> * @hba: per adapter instance >> * >> @@ -1084,7 +967,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 +1050,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 +1164,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 +1193,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 +1257,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 +1392,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 +1435,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 +1571,46 @@ static struct scsi_host_template ufshcd_driver_template = { >> }; >> >> /** >> - * ufshcd_shutdown - main function to put the controller in reset state >> - * @pdev: pointer to PCI device handle >> + * ufshcd_initialize_hba - start the initialization process >> + * @hba: per adapter instance >> + * >> + * 1. Enable the controller via ufshcd_hba_enable. >> + * 2. Program the Transfer Request List Address with the starting address of >> + * UTRDL. >> + * 3. Program the Task Management Request List Address with starting address >> + * of UTMRDL. >> + * >> + * Returns 0 on success, non-zero value on failure. >> */ >> -static void ufshcd_shutdown(struct pci_dev *pdev) >> +int ufshcd_initialize_hba(struct ufs_hba *hba) >> { >> - ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev)); >> + if (ufshcd_hba_enable(hba)) >> + return -EIO; >> + >> + /* Configure UTRL and UTMRL base address registers */ >> + writel(hba->utrdl_dma_addr, >> + (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L)); >> + writel(lower_32_bits(hba->utrdl_dma_addr), >> + (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H)); >> + writel(hba->utmrdl_dma_addr, >> + (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L)); >> + writel(upper_32_bits(hba->utmrdl_dma_addr), >> + (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H)); >> + >> + /* Initialize unipro link startup procedure */ >> + return ufshcd_dme_link_startup(hba); >> } >> +EXPORT_SYMBOL(ufshcd_initialize_hba); >> >> #ifdef CONFIG_PM >> /** >> * ufshcd_suspend - suspend power management function >> - * @pdev: pointer to PCI device handle >> + * @hba: pointer to host controller platform data >> * @state: power state >> * >> * Returns -ENOSYS >> */ >> -static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state) >> +int ufshcd_suspend(struct ufs_hba *hba) >> { >> /* >> * TODO: >> @@ -1717,14 +1623,15 @@ static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state) >> >> return -ENOSYS; >> } >> +EXPORT_SYMBOL(ufshcd_suspend); >> >> /** >> * ufshcd_resume - resume power management function >> - * @pdev: pointer to PCI device handle >> + * @hba: pointer to host controller platform data >> * >> * Returns -ENOSYS >> */ >> -static int ufshcd_resume(struct pci_dev *pdev) >> +int ufshcd_resume(struct ufs_hba *hba) >> { >> /* >> * TODO: >> @@ -1737,119 +1644,55 @@ static int ufshcd_resume(struct pci_dev *pdev) >> >> return -ENOSYS; >> } >> -#endif /* CONFIG_PM */ >> +EXPORT_SYMBOL(ufshcd_resume); >> >> -/** >> - * ufshcd_hba_free - free allocated memory for >> - * host memory space data structures >> - * @hba: per adapter instance >> - */ >> -static void ufshcd_hba_free(struct ufs_hba *hba) >> -{ >> - iounmap(hba->mmio_base); >> - ufshcd_free_hba_memory(hba); >> - pci_release_regions(hba->pdev); >> -} >> +#endif /* CONFIG_PM */ >> >> /** >> - * ufshcd_remove - de-allocate PCI/SCSI host and host memory space >> + * ufshcd_drv_exit - de-allocate SCSI host and host memory space >> * data structure memory >> - * @pdev - pointer to PCI handle >> + * @dev - pointer to host platform data >> */ >> -static void ufshcd_remove(struct pci_dev *pdev) >> +void ufshcd_drv_exit(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); >> + free_irq(hba->irq, hba); >> >> ufshcd_hba_stop(hba); >> - ufshcd_hba_free(hba); >> + ufshcd_free_hba_memory(hba); >> >> scsi_remove_host(hba->host); >> scsi_host_put(hba->host); >> - pci_set_drvdata(pdev, NULL); >> - pci_clear_master(pdev); >> - pci_disable_device(pdev); >> } >> +EXPORT_SYMBOL(ufshcd_drv_exit); >> >> /** >> - * 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 ufs_hba *hba) >> -{ >> - 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); >> - >> - return err; >> -} >> - >> -/** >> - * ufshcd_probe - probe routine of the driver >> - * @pdev: pointer to PCI device handle >> - * @id: PCI device id >> + * ufshcd_drv_init - generic init routine of the driver >> + * @hba: pointer to platform data >> * >> * 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_drv_init(struct ufs_hba **hostdata, struct device *dev, >> + int irq_no, void __iomem *mmio_base) >> { >> 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"); >> - goto out_error; >> - } >> - >> - pci_set_master(pdev); >> + struct ufs_hba *hba; >> >> host = scsi_host_alloc(&ufshcd_driver_template, >> sizeof(struct ufs_hba)); >> if (!host) { >> - dev_err(&pdev->dev, "scsi_host_alloc failed\n"); >> + dev_err(&hba->dev, "scsi_host_alloc failed\n"); >> err = -ENOMEM; >> goto out_disable; >> } >> hba = shost_priv(host); >> - >> - err = pci_request_regions(pdev, UFSHCD); >> - if (err < 0) { >> - dev_err(&pdev->dev, "request regions failed\n"); >> - goto out_disable; >> - } >> - >> - 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->dev = *dev; > It doesn't look like you need to copy the entire device data into hba. Will change it to only have the address. > Why isn't a reference not sufficient ? > > >> hba->host = host; >> - hba->pdev = pdev; >> + hba->irq = irq_no; >> + hba->mmio_base = mmio_base; >> + *hostdata = hba; >> >> /* Read capabilities registers */ >> ufshcd_hba_capabilities(hba); >> @@ -1857,17 +1700,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,72 +1726,55 @@ 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(hba->irq, ufshcd_intr, IRQF_SHARED, >> + ufs_hostname(hba), 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"); >> - goto out_free_irq; >> - } >> - >> - pci_set_drvdata(pdev, hba); >> - >> - err = scsi_add_host(host, &pdev->dev); >> - if (err) { >> - dev_err(&pdev->dev, "scsi_add_host failed\n"); >> + dev_err(&hba->dev, "init shared queue failed\n"); >> goto out_free_irq; >> } >> >> - /* Initialization routine */ >> - err = ufshcd_initialize_hba(hba); >> + err = scsi_add_host(host, &hba->dev); >> if (err) { >> - dev_err(&pdev->dev, "Initialization failed\n"); >> + dev_err(&hba->dev, "scsi_add_host failed\n"); >> goto out_free_irq; >> } >> >> return 0; >> >> out_free_irq: >> - free_irq(pdev->irq, hba); >> + free_irq(hba->irq, hba); >> out_lrb_free: >> ufshcd_free_hba_memory(hba); >> -out_iounmap: >> - iounmap(hba->mmio_base); >> -out_release_regions: >> - pci_release_regions(pdev); >> out_disable: >> scsi_host_put(host); >> - pci_clear_master(pdev); >> - pci_disable_device(pdev); >> -out_error: >> return err; >> } >> +EXPORT_SYMBOL(ufshcd_drv_init); >> >> -static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = { >> - { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, >> - { } /* terminate list */ >> -}; >> +static int __init ufshcd_probe(void) >> +{ >> + pr_info(UFSHCD >> + ": Generic UFS host controller driver\n"); >> + pr_info(UFSHCD ": Copyright(c) Samsung India Software Operations\n"); >> > Is it really necessary to assert the copyright on probe ? I haven't > seen this practice anywhere.. You can find one in driver/mmc/host/sdhci.c > >> -MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl); >> + return 0; >> +} >> >> -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, >> -#ifdef CONFIG_PM >> - .suspend = ufshcd_suspend, >> - .resume = ufshcd_resume, >> -#endif >> -}; >> +static void __exit ufshcd_remove(void) >> +{ >> + pr_info(UFSHCD >> + ": Generic UFS host controller driver removed\n"); >> +} >> >> -module_pci_driver(ufshcd_pci_driver); >> +module_init(ufshcd_probe); >> +module_exit(ufshcd_remove); >> >> MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@xxxxxxxxxxx>, " >> "Vinayak Holikatti <h.vinayak@xxxxxxxxxxx>"); >> -- >> 1.7.4.1 >> -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html