Re: [RFC V2 1/2] SCSI: UFS: Create separate UFS core and pci modules

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

 



On Thu, May 17, 2012 at 4:52 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 |  217 ++++++++++++++++++++++++
>  drivers/scsi/ufs/ufshcd.c     |  374 +++++++++++------------------------------
>  5 files changed, 436 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..029a3f3 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_probe(struct ufs_hba **hostdat, struct device *dev,
> +                       int irq_no, void __iomem *mmio_base);
> +extern void ufshcd_remove(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..eabdaa6
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufshcd-pci.c
> @@ -0,0 +1,217 @@
> +/*
> + * 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_probe(&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_remove(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_remove(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_SLEEP

Is there a reason to use CONFIG_PM for ufshcd_suspend and
CONFIG_PM_SLEEP for ufshcd_pci_suspend ?

> +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_SLEEP */
> +
> +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         = ufshcd_pci_remove,
Please use the __devexit_p annotation

> +       .driver         =       {
> +               .pm =   &ufshcd_pci_pmops
> +       },
> +};
> +
> +static int __init ufshcd_init(void)
> +{
> +       return pci_register_driver(&ufshcd_pci_driver);
> +}
> +
> +static void __exit ufshcd_exit(void)
> +{
> +       pci_unregister_driver(&ufshcd_pci_driver);
> +}
> +
> +module_init(ufshcd_init);
> +module_exit(ufshcd_exit);
> +
Please use the module_pci_driver() macro

> +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..7c49074 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;
It'd be better to propogate the error returned by ufshcd_hba_enable ?

> +
> +       /* 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_remove - 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_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);
> +       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);
> -}
> -
> -/**
> - * 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;
>  }
> +EXPORT_SYMBOL(ufshcd_remove);
>
>  /**
> - * ufshcd_probe - probe routine of the driver
> - * @pdev: pointer to PCI device handle
> - * @id: PCI device id
> + * ufshcd_probe - generic probe 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_probe(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;
>        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,59 @@ 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_probe);
>
> -static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
> -       { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> -       { }     /* terminate list */
> -};
> +/*****************************************************************************\
> + *                                                                           *
> + * Driver init/exit                                                          *
> + *                                                                           *
> +\*****************************************************************************/
>
> -MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
> +static int __init ufshcd_drv_init(void)
> +{
> +       pr_info(UFSHCD
> +               ": Generic UFS host controller driver\n");
> +       pr_info(UFSHCD ": Copyright(c) Samsung India Software Operations\n");
>
> -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
> -};
> +       return 0;
> +}
> +
> +static void __exit ufshcd_drv_exit(void)
> +{
> +}
>
> -module_pci_driver(ufshcd_pci_driver);
> +module_init(ufshcd_drv_init);
> +module_exit(ufshcd_drv_exit);
There doesn't allow the core ufshcd to be inserted and removed as a
module, the actual probe and remove functions aren't annotated
properly like a true driver.

You can see the example of dwc3 driver in USB which does a thorough split..
(drivers/usb/dwc3/core.c and drivers/usb/dwc3/dwc3-pci.c)

>
>  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
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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