diff options
| -rw-r--r-- | drivers/scsi/ufs/Kconfig | 50 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufs.h | 44 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 348 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufshci.h | 44 |
4 files changed, 267 insertions, 219 deletions
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index 8f27f9d6f91d..8ee40dff3dfb 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig | |||
| @@ -2,45 +2,35 @@ | |||
| 2 | # Kernel configuration file for the UFS Host Controller | 2 | # Kernel configuration file for the UFS Host Controller |
| 3 | # | 3 | # |
| 4 | # This code is based on drivers/scsi/ufs/Kconfig | 4 | # This code is based on drivers/scsi/ufs/Kconfig |
| 5 | # Copyright (C) 2011 Samsung Samsung India Software Operations | 5 | # Copyright (C) 2011-2013 Samsung India Software Operations |
| 6 | # | ||
| 7 | # Authors: | ||
| 8 | # Santosh Yaraganavi <santosh.sy@samsung.com> | ||
| 9 | # Vinayak Holikatti <h.vinayak@samsung.com> | ||
| 6 | # | 10 | # |
| 7 | # Santosh Yaraganavi <santosh.sy@samsung.com> | ||
| 8 | # Vinayak Holikatti <h.vinayak@samsung.com> | ||
| 9 | |||
| 10 | # This program is free software; you can redistribute it and/or | 11 | # This program is free software; you can redistribute it and/or |
| 11 | # modify it under the terms of the GNU General Public License | 12 | # modify it under the terms of the GNU General Public License |
| 12 | # as published by the Free Software Foundation; either version 2 | 13 | # as published by the Free Software Foundation; either version 2 |
| 13 | # of the License, or (at your option) any later version. | 14 | # of the License, or (at your option) any later version. |
| 14 | 15 | # See the COPYING file in the top-level directory or visit | |
| 16 | # <http://www.gnu.org/licenses/gpl-2.0.html> | ||
| 17 | # | ||
| 15 | # This program is distributed in the hope that it will be useful, | 18 | # This program is distributed in the hope that it will be useful, |
| 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | # GNU General Public License for more details. | 21 | # GNU General Public License for more details. |
| 19 | 22 | # | |
| 20 | # NO WARRANTY | 23 | # This program is provided "AS IS" and "WITH ALL FAULTS" and |
| 21 | # THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | 24 | # without warranty of any kind. You are solely responsible for |
| 22 | # CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | 25 | # determining the appropriateness of using and distributing |
| 23 | # LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | 26 | # the program and assume all risks associated with your exercise |
| 24 | # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | 27 | # of rights with respect to the program, including but not limited |
| 25 | # solely responsible for determining the appropriateness of using and | 28 | # to infringement of third party rights, the risks and costs of |
| 26 | # distributing the Program and assumes all risks associated with its | 29 | # program errors, damage to or loss of data, programs or equipment, |
| 27 | # exercise of rights under this Agreement, including but not limited to | 30 | # and unavailability or interruption of operations. Under no |
| 28 | # the risks and costs of program errors, damage to or loss of data, | 31 | # circumstances will the contributor of this Program be liable for |
| 29 | # programs or equipment, and unavailability or interruption of operations. | 32 | # any damages of any kind arising from your use or distribution of |
| 30 | 33 | # this program. | |
| 31 | # DISCLAIMER OF LIABILITY | ||
| 32 | # NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 33 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 34 | # DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 35 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 36 | # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 37 | # USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 38 | # HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 39 | |||
| 40 | # You should have received a copy of the GNU General Public License | ||
| 41 | # along with this program; if not, write to the Free Software | ||
| 42 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 43 | # USA. | ||
| 44 | 34 | ||
| 45 | config SCSI_UFSHCD | 35 | config SCSI_UFSHCD |
| 46 | tristate "Universal Flash Storage host controller driver" | 36 | tristate "Universal Flash Storage host controller driver" |
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index b207529f8d54..139bc0647b41 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h | |||
| @@ -2,45 +2,35 @@ | |||
| 2 | * Universal Flash Storage Host controller driver | 2 | * Universal Flash Storage Host controller driver |
| 3 | * | 3 | * |
| 4 | * This code is based on drivers/scsi/ufs/ufs.h | 4 | * This code is based on drivers/scsi/ufs/ufs.h |
| 5 | * Copyright (C) 2011-2012 Samsung India Software Operations | 5 | * Copyright (C) 2011-2013 Samsung India Software Operations |
| 6 | * | 6 | * |
| 7 | * Santosh Yaraganavi <santosh.sy@samsung.com> | 7 | * Authors: |
| 8 | * Vinayak Holikatti <h.vinayak@samsung.com> | 8 | * Santosh Yaraganavi <santosh.sy@samsung.com> |
| 9 | * Vinayak Holikatti <h.vinayak@samsung.com> | ||
| 9 | * | 10 | * |
| 10 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
| 11 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
| 12 | * as published by the Free Software Foundation; either version 2 | 13 | * as published by the Free Software Foundation; either version 2 |
| 13 | * of the License, or (at your option) any later version. | 14 | * of the License, or (at your option) any later version. |
| 15 | * See the COPYING file in the top-level directory or visit | ||
| 16 | * <http://www.gnu.org/licenses/gpl-2.0.html> | ||
| 14 | * | 17 | * |
| 15 | * This program is distributed in the hope that it will be useful, | 18 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | * GNU General Public License for more details. | 21 | * GNU General Public License for more details. |
| 19 | * | 22 | * |
| 20 | * NO WARRANTY | 23 | * This program is provided "AS IS" and "WITH ALL FAULTS" and |
| 21 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | 24 | * without warranty of any kind. You are solely responsible for |
| 22 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | 25 | * determining the appropriateness of using and distributing |
| 23 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | 26 | * the program and assume all risks associated with your exercise |
| 24 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | 27 | * of rights with respect to the program, including but not limited |
| 25 | * solely responsible for determining the appropriateness of using and | 28 | * to infringement of third party rights, the risks and costs of |
| 26 | * distributing the Program and assumes all risks associated with its | 29 | * program errors, damage to or loss of data, programs or equipment, |
| 27 | * exercise of rights under this Agreement, including but not limited to | 30 | * and unavailability or interruption of operations. Under no |
| 28 | * the risks and costs of program errors, damage to or loss of data, | 31 | * circumstances will the contributor of this Program be liable for |
| 29 | * programs or equipment, and unavailability or interruption of operations. | 32 | * any damages of any kind arising from your use or distribution of |
| 30 | 33 | * this program. | |
| 31 | * DISCLAIMER OF LIABILITY | ||
| 32 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 33 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 34 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 35 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 36 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 37 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 38 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 39 | |||
| 40 | * You should have received a copy of the GNU General Public License | ||
| 41 | * along with this program; if not, write to the Free Software | ||
| 42 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 43 | * USA. | ||
| 44 | */ | 34 | */ |
| 45 | 35 | ||
| 46 | #ifndef _UFS_H | 36 | #ifndef _UFS_H |
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 91a4046ca9ba..5f7c0173d8a0 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
| @@ -2,45 +2,35 @@ | |||
| 2 | * Universal Flash Storage Host controller driver | 2 | * Universal Flash Storage Host controller driver |
| 3 | * | 3 | * |
| 4 | * This code is based on drivers/scsi/ufs/ufshcd.c | 4 | * This code is based on drivers/scsi/ufs/ufshcd.c |
| 5 | * Copyright (C) 2011-2012 Samsung India Software Operations | 5 | * Copyright (C) 2011-2013 Samsung India Software Operations |
| 6 | * | 6 | * |
| 7 | * Santosh Yaraganavi <santosh.sy@samsung.com> | 7 | * Authors: |
| 8 | * Vinayak Holikatti <h.vinayak@samsung.com> | 8 | * Santosh Yaraganavi <santosh.sy@samsung.com> |
| 9 | * Vinayak Holikatti <h.vinayak@samsung.com> | ||
| 9 | * | 10 | * |
| 10 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
| 11 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
| 12 | * as published by the Free Software Foundation; either version 2 | 13 | * as published by the Free Software Foundation; either version 2 |
| 13 | * of the License, or (at your option) any later version. | 14 | * of the License, or (at your option) any later version. |
| 15 | * See the COPYING file in the top-level directory or visit | ||
| 16 | * <http://www.gnu.org/licenses/gpl-2.0.html> | ||
| 14 | * | 17 | * |
| 15 | * This program is distributed in the hope that it will be useful, | 18 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | * GNU General Public License for more details. | 21 | * GNU General Public License for more details. |
| 19 | * | 22 | * |
| 20 | * NO WARRANTY | 23 | * This program is provided "AS IS" and "WITH ALL FAULTS" and |
| 21 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | 24 | * without warranty of any kind. You are solely responsible for |
| 22 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | 25 | * determining the appropriateness of using and distributing |
| 23 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | 26 | * the program and assume all risks associated with your exercise |
| 24 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | 27 | * of rights with respect to the program, including but not limited |
| 25 | * solely responsible for determining the appropriateness of using and | 28 | * to infringement of third party rights, the risks and costs of |
| 26 | * distributing the Program and assumes all risks associated with its | 29 | * program errors, damage to or loss of data, programs or equipment, |
| 27 | * exercise of rights under this Agreement, including but not limited to | 30 | * and unavailability or interruption of operations. Under no |
| 28 | * the risks and costs of program errors, damage to or loss of data, | 31 | * circumstances will the contributor of this Program be liable for |
| 29 | * programs or equipment, and unavailability or interruption of operations. | 32 | * any damages of any kind arising from your use or distribution of |
| 30 | 33 | * this program. | |
| 31 | * DISCLAIMER OF LIABILITY | ||
| 32 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 33 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 34 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 35 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 36 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 37 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 38 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 39 | |||
| 40 | * You should have received a copy of the GNU General Public License | ||
| 41 | * along with this program; if not, write to the Free Software | ||
| 42 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 43 | * USA. | ||
| 44 | */ | 34 | */ |
| 45 | 35 | ||
| 46 | #include <linux/module.h> | 36 | #include <linux/module.h> |
| @@ -129,13 +119,15 @@ struct uic_command { | |||
| 129 | * @utrdl_dma_addr: UTRDL DMA address | 119 | * @utrdl_dma_addr: UTRDL DMA address |
| 130 | * @utmrdl_dma_addr: UTMRDL DMA address | 120 | * @utmrdl_dma_addr: UTMRDL DMA address |
| 131 | * @host: Scsi_Host instance of the driver | 121 | * @host: Scsi_Host instance of the driver |
| 132 | * @pdev: PCI device handle | 122 | * @dev: device handle |
| 133 | * @lrb: local reference block | 123 | * @lrb: local reference block |
| 134 | * @outstanding_tasks: Bits representing outstanding task requests | 124 | * @outstanding_tasks: Bits representing outstanding task requests |
| 135 | * @outstanding_reqs: Bits representing outstanding transfer requests | 125 | * @outstanding_reqs: Bits representing outstanding transfer requests |
| 136 | * @capabilities: UFS Controller Capabilities | 126 | * @capabilities: UFS Controller Capabilities |
| 137 | * @nutrs: Transfer Request Queue depth supported by controller | 127 | * @nutrs: Transfer Request Queue depth supported by controller |
| 138 | * @nutmrs: Task Management Queue depth supported by controller | 128 | * @nutmrs: Task Management Queue depth supported by controller |
| 129 | * @ufs_version: UFS Version to which controller complies | ||
| 130 | * @irq: Irq number of the controller | ||
| 139 | * @active_uic_cmd: handle of active UIC command | 131 | * @active_uic_cmd: handle of active UIC command |
| 140 | * @ufshcd_tm_wait_queue: wait queue for task management | 132 | * @ufshcd_tm_wait_queue: wait queue for task management |
| 141 | * @tm_condition: condition variable for task management | 133 | * @tm_condition: condition variable for task management |
| @@ -159,7 +151,7 @@ struct ufs_hba { | |||
| 159 | dma_addr_t utmrdl_dma_addr; | 151 | dma_addr_t utmrdl_dma_addr; |
| 160 | 152 | ||
| 161 | struct Scsi_Host *host; | 153 | struct Scsi_Host *host; |
| 162 | struct pci_dev *pdev; | 154 | struct device *dev; |
| 163 | 155 | ||
| 164 | struct ufshcd_lrb *lrb; | 156 | struct ufshcd_lrb *lrb; |
| 165 | 157 | ||
| @@ -170,6 +162,7 @@ struct ufs_hba { | |||
| 170 | int nutrs; | 162 | int nutrs; |
| 171 | int nutmrs; | 163 | int nutmrs; |
| 172 | u32 ufs_version; | 164 | u32 ufs_version; |
| 165 | unsigned int irq; | ||
| 173 | 166 | ||
| 174 | struct uic_command active_uic_cmd; | 167 | struct uic_command active_uic_cmd; |
| 175 | wait_queue_head_t ufshcd_tm_wait_queue; | 168 | wait_queue_head_t ufshcd_tm_wait_queue; |
| @@ -335,21 +328,21 @@ static inline void ufshcd_free_hba_memory(struct ufs_hba *hba) | |||
| 335 | 328 | ||
| 336 | if (hba->utmrdl_base_addr) { | 329 | if (hba->utmrdl_base_addr) { |
| 337 | utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs; | 330 | utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs; |
| 338 | dma_free_coherent(&hba->pdev->dev, utmrdl_size, | 331 | dma_free_coherent(hba->dev, utmrdl_size, |
| 339 | hba->utmrdl_base_addr, hba->utmrdl_dma_addr); | 332 | hba->utmrdl_base_addr, hba->utmrdl_dma_addr); |
| 340 | } | 333 | } |
| 341 | 334 | ||
| 342 | if (hba->utrdl_base_addr) { | 335 | if (hba->utrdl_base_addr) { |
| 343 | utrdl_size = | 336 | utrdl_size = |
| 344 | (sizeof(struct utp_transfer_req_desc) * hba->nutrs); | 337 | (sizeof(struct utp_transfer_req_desc) * hba->nutrs); |
| 345 | dma_free_coherent(&hba->pdev->dev, utrdl_size, | 338 | dma_free_coherent(hba->dev, utrdl_size, |
| 346 | hba->utrdl_base_addr, hba->utrdl_dma_addr); | 339 | hba->utrdl_base_addr, hba->utrdl_dma_addr); |
| 347 | } | 340 | } |
| 348 | 341 | ||
| 349 | if (hba->ucdl_base_addr) { | 342 | if (hba->ucdl_base_addr) { |
| 350 | ucdl_size = | 343 | ucdl_size = |
| 351 | (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs); | 344 | (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs); |
| 352 | dma_free_coherent(&hba->pdev->dev, ucdl_size, | 345 | dma_free_coherent(hba->dev, ucdl_size, |
| 353 | hba->ucdl_base_addr, hba->ucdl_dma_addr); | 346 | hba->ucdl_base_addr, hba->ucdl_dma_addr); |
| 354 | } | 347 | } |
| 355 | } | 348 | } |
| @@ -724,7 +717,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) | |||
| 724 | 717 | ||
| 725 | /* Allocate memory for UTP command descriptors */ | 718 | /* Allocate memory for UTP command descriptors */ |
| 726 | ucdl_size = (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs); | 719 | ucdl_size = (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs); |
| 727 | hba->ucdl_base_addr = dma_alloc_coherent(&hba->pdev->dev, | 720 | hba->ucdl_base_addr = dma_alloc_coherent(hba->dev, |
| 728 | ucdl_size, | 721 | ucdl_size, |
| 729 | &hba->ucdl_dma_addr, | 722 | &hba->ucdl_dma_addr, |
| 730 | GFP_KERNEL); | 723 | GFP_KERNEL); |
| @@ -737,7 +730,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) | |||
| 737 | */ | 730 | */ |
| 738 | if (!hba->ucdl_base_addr || | 731 | if (!hba->ucdl_base_addr || |
| 739 | WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) { | 732 | WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) { |
| 740 | dev_err(&hba->pdev->dev, | 733 | dev_err(hba->dev, |
| 741 | "Command Descriptor Memory allocation failed\n"); | 734 | "Command Descriptor Memory allocation failed\n"); |
| 742 | goto out; | 735 | goto out; |
| 743 | } | 736 | } |
| @@ -747,13 +740,13 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) | |||
| 747 | * UFSHCI requires 1024 byte alignment of UTRD | 740 | * UFSHCI requires 1024 byte alignment of UTRD |
| 748 | */ | 741 | */ |
| 749 | utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs); | 742 | utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs); |
| 750 | hba->utrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev, | 743 | hba->utrdl_base_addr = dma_alloc_coherent(hba->dev, |
| 751 | utrdl_size, | 744 | utrdl_size, |
| 752 | &hba->utrdl_dma_addr, | 745 | &hba->utrdl_dma_addr, |
| 753 | GFP_KERNEL); | 746 | GFP_KERNEL); |
| 754 | if (!hba->utrdl_base_addr || | 747 | if (!hba->utrdl_base_addr || |
| 755 | WARN_ON(hba->utrdl_dma_addr & (PAGE_SIZE - 1))) { | 748 | WARN_ON(hba->utrdl_dma_addr & (PAGE_SIZE - 1))) { |
| 756 | dev_err(&hba->pdev->dev, | 749 | dev_err(hba->dev, |
| 757 | "Transfer Descriptor Memory allocation failed\n"); | 750 | "Transfer Descriptor Memory allocation failed\n"); |
| 758 | goto out; | 751 | goto out; |
| 759 | } | 752 | } |
| @@ -763,13 +756,13 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) | |||
| 763 | * UFSHCI requires 1024 byte alignment of UTMRD | 756 | * UFSHCI requires 1024 byte alignment of UTMRD |
| 764 | */ | 757 | */ |
| 765 | utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs; | 758 | utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs; |
| 766 | hba->utmrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev, | 759 | hba->utmrdl_base_addr = dma_alloc_coherent(hba->dev, |
| 767 | utmrdl_size, | 760 | utmrdl_size, |
| 768 | &hba->utmrdl_dma_addr, | 761 | &hba->utmrdl_dma_addr, |
| 769 | GFP_KERNEL); | 762 | GFP_KERNEL); |
| 770 | if (!hba->utmrdl_base_addr || | 763 | if (!hba->utmrdl_base_addr || |
| 771 | WARN_ON(hba->utmrdl_dma_addr & (PAGE_SIZE - 1))) { | 764 | WARN_ON(hba->utmrdl_dma_addr & (PAGE_SIZE - 1))) { |
| 772 | dev_err(&hba->pdev->dev, | 765 | dev_err(hba->dev, |
| 773 | "Task Management Descriptor Memory allocation failed\n"); | 766 | "Task Management Descriptor Memory allocation failed\n"); |
| 774 | goto out; | 767 | goto out; |
| 775 | } | 768 | } |
| @@ -777,7 +770,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) | |||
| 777 | /* Allocate memory for local reference block */ | 770 | /* Allocate memory for local reference block */ |
| 778 | hba->lrb = kcalloc(hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL); | 771 | hba->lrb = kcalloc(hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL); |
| 779 | if (!hba->lrb) { | 772 | if (!hba->lrb) { |
| 780 | dev_err(&hba->pdev->dev, "LRB Memory allocation failed\n"); | 773 | dev_err(hba->dev, "LRB Memory allocation failed\n"); |
| 781 | goto out; | 774 | goto out; |
| 782 | } | 775 | } |
| 783 | return 0; | 776 | return 0; |
| @@ -867,7 +860,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) | |||
| 867 | /* check if controller is ready to accept UIC commands */ | 860 | /* check if controller is ready to accept UIC commands */ |
| 868 | if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) & | 861 | if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) & |
| 869 | UIC_COMMAND_READY) == 0x0) { | 862 | UIC_COMMAND_READY) == 0x0) { |
| 870 | dev_err(&hba->pdev->dev, | 863 | dev_err(hba->dev, |
| 871 | "Controller not ready" | 864 | "Controller not ready" |
| 872 | " to accept UIC commands\n"); | 865 | " to accept UIC commands\n"); |
| 873 | return -EIO; | 866 | return -EIO; |
| @@ -912,7 +905,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) | |||
| 912 | /* check if device present */ | 905 | /* check if device present */ |
| 913 | reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS)); | 906 | reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS)); |
| 914 | if (!ufshcd_is_device_present(reg)) { | 907 | if (!ufshcd_is_device_present(reg)) { |
| 915 | dev_err(&hba->pdev->dev, "cc: Device not present\n"); | 908 | dev_err(hba->dev, "cc: Device not present\n"); |
| 916 | err = -ENXIO; | 909 | err = -ENXIO; |
| 917 | goto out; | 910 | goto out; |
| 918 | } | 911 | } |
| @@ -924,7 +917,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) | |||
| 924 | if (!(ufshcd_get_lists_status(reg))) { | 917 | if (!(ufshcd_get_lists_status(reg))) { |
| 925 | ufshcd_enable_run_stop_reg(hba); | 918 | ufshcd_enable_run_stop_reg(hba); |
| 926 | } else { | 919 | } else { |
| 927 | dev_err(&hba->pdev->dev, | 920 | dev_err(hba->dev, |
| 928 | "Host controller not ready to process requests"); | 921 | "Host controller not ready to process requests"); |
| 929 | err = -EIO; | 922 | err = -EIO; |
| 930 | goto out; | 923 | goto out; |
| @@ -1005,7 +998,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) | |||
| 1005 | if (retry) { | 998 | if (retry) { |
| 1006 | retry--; | 999 | retry--; |
| 1007 | } else { | 1000 | } else { |
| 1008 | dev_err(&hba->pdev->dev, | 1001 | dev_err(hba->dev, |
| 1009 | "Controller enable failed\n"); | 1002 | "Controller enable failed\n"); |
| 1010 | return -EIO; | 1003 | return -EIO; |
| 1011 | } | 1004 | } |
| @@ -1084,7 +1077,7 @@ static int ufshcd_do_reset(struct ufs_hba *hba) | |||
| 1084 | 1077 | ||
| 1085 | /* start the initialization process */ | 1078 | /* start the initialization process */ |
| 1086 | if (ufshcd_initialize_hba(hba)) { | 1079 | if (ufshcd_initialize_hba(hba)) { |
| 1087 | dev_err(&hba->pdev->dev, | 1080 | dev_err(hba->dev, |
| 1088 | "Reset: Controller initialization failed\n"); | 1081 | "Reset: Controller initialization failed\n"); |
| 1089 | return FAILED; | 1082 | return FAILED; |
| 1090 | } | 1083 | } |
| @@ -1167,7 +1160,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index) | |||
| 1167 | task_result = SUCCESS; | 1160 | task_result = SUCCESS; |
| 1168 | } else { | 1161 | } else { |
| 1169 | task_result = FAILED; | 1162 | task_result = FAILED; |
| 1170 | dev_err(&hba->pdev->dev, | 1163 | dev_err(hba->dev, |
| 1171 | "trc: Invalid ocs = %x\n", ocs_value); | 1164 | "trc: Invalid ocs = %x\n", ocs_value); |
| 1172 | } | 1165 | } |
| 1173 | spin_unlock_irqrestore(hba->host->host_lock, flags); | 1166 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
| @@ -1281,7 +1274,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) | |||
| 1281 | /* check if the returned transfer response is valid */ | 1274 | /* check if the returned transfer response is valid */ |
| 1282 | result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr); | 1275 | result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr); |
| 1283 | if (result) { | 1276 | if (result) { |
| 1284 | dev_err(&hba->pdev->dev, | 1277 | dev_err(hba->dev, |
| 1285 | "Invalid response = %x\n", result); | 1278 | "Invalid response = %x\n", result); |
| 1286 | break; | 1279 | break; |
| 1287 | } | 1280 | } |
| @@ -1310,7 +1303,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) | |||
| 1310 | case OCS_FATAL_ERROR: | 1303 | case OCS_FATAL_ERROR: |
| 1311 | default: | 1304 | default: |
| 1312 | result |= DID_ERROR << 16; | 1305 | result |= DID_ERROR << 16; |
| 1313 | dev_err(&hba->pdev->dev, | 1306 | dev_err(hba->dev, |
| 1314 | "OCS error from controller = %x\n", ocs); | 1307 | "OCS error from controller = %x\n", ocs); |
| 1315 | break; | 1308 | break; |
| 1316 | } /* end of switch */ | 1309 | } /* end of switch */ |
| @@ -1374,7 +1367,7 @@ static void ufshcd_uic_cc_handler (struct work_struct *work) | |||
| 1374 | !(ufshcd_get_uic_cmd_result(hba))) { | 1367 | !(ufshcd_get_uic_cmd_result(hba))) { |
| 1375 | 1368 | ||
| 1376 | if (ufshcd_make_hba_operational(hba)) | 1369 | if (ufshcd_make_hba_operational(hba)) |
| 1377 | dev_err(&hba->pdev->dev, | 1370 | dev_err(hba->dev, |
| 1378 | "cc: hba not operational state\n"); | 1371 | "cc: hba not operational state\n"); |
| 1379 | return; | 1372 | return; |
| 1380 | } | 1373 | } |
| @@ -1509,7 +1502,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba, | |||
| 1509 | free_slot = ufshcd_get_tm_free_slot(hba); | 1502 | free_slot = ufshcd_get_tm_free_slot(hba); |
| 1510 | if (free_slot >= hba->nutmrs) { | 1503 | if (free_slot >= hba->nutmrs) { |
| 1511 | spin_unlock_irqrestore(host->host_lock, flags); | 1504 | spin_unlock_irqrestore(host->host_lock, flags); |
| 1512 | dev_err(&hba->pdev->dev, "Task management queue full\n"); | 1505 | dev_err(hba->dev, "Task management queue full\n"); |
| 1513 | err = FAILED; | 1506 | err = FAILED; |
| 1514 | goto out; | 1507 | goto out; |
| 1515 | } | 1508 | } |
| @@ -1552,7 +1545,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba, | |||
| 1552 | &hba->tm_condition) != 0), | 1545 | &hba->tm_condition) != 0), |
| 1553 | 60 * HZ); | 1546 | 60 * HZ); |
| 1554 | if (!err) { | 1547 | if (!err) { |
| 1555 | dev_err(&hba->pdev->dev, | 1548 | dev_err(hba->dev, |
| 1556 | "Task management command timed-out\n"); | 1549 | "Task management command timed-out\n"); |
| 1557 | err = FAILED; | 1550 | err = FAILED; |
| 1558 | goto out; | 1551 | goto out; |
| @@ -1688,23 +1681,22 @@ static struct scsi_host_template ufshcd_driver_template = { | |||
| 1688 | }; | 1681 | }; |
| 1689 | 1682 | ||
| 1690 | /** | 1683 | /** |
| 1691 | * ufshcd_shutdown - main function to put the controller in reset state | 1684 | * ufshcd_pci_shutdown - main function to put the controller in reset state |
| 1692 | * @pdev: pointer to PCI device handle | 1685 | * @pdev: pointer to PCI device handle |
| 1693 | */ | 1686 | */ |
| 1694 | static void ufshcd_shutdown(struct pci_dev *pdev) | 1687 | static void ufshcd_pci_shutdown(struct pci_dev *pdev) |
| 1695 | { | 1688 | { |
| 1696 | ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev)); | 1689 | ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev)); |
| 1697 | } | 1690 | } |
| 1698 | 1691 | ||
| 1699 | #ifdef CONFIG_PM | ||
| 1700 | /** | 1692 | /** |
| 1701 | * ufshcd_suspend - suspend power management function | 1693 | * ufshcd_suspend - suspend power management function |
| 1702 | * @pdev: pointer to PCI device handle | 1694 | * @hba: per adapter instance |
| 1703 | * @state: power state | 1695 | * @state: power state |
| 1704 | * | 1696 | * |
| 1705 | * Returns -ENOSYS | 1697 | * Returns -ENOSYS |
| 1706 | */ | 1698 | */ |
| 1707 | static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state) | 1699 | int ufshcd_suspend(struct ufs_hba *hba, pm_message_t state) |
| 1708 | { | 1700 | { |
| 1709 | /* | 1701 | /* |
| 1710 | * TODO: | 1702 | * TODO: |
| @@ -1717,14 +1709,15 @@ static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 1717 | 1709 | ||
| 1718 | return -ENOSYS; | 1710 | return -ENOSYS; |
| 1719 | } | 1711 | } |
| 1712 | EXPORT_SYMBOL_GPL(ufshcd_suspend); | ||
| 1720 | 1713 | ||
| 1721 | /** | 1714 | /** |
| 1722 | * ufshcd_resume - resume power management function | 1715 | * ufshcd_resume - resume power management function |
| 1723 | * @pdev: pointer to PCI device handle | 1716 | * @hba: per adapter instance |
| 1724 | * | 1717 | * |
| 1725 | * Returns -ENOSYS | 1718 | * Returns -ENOSYS |
| 1726 | */ | 1719 | */ |
| 1727 | static int ufshcd_resume(struct pci_dev *pdev) | 1720 | int ufshcd_resume(struct ufs_hba *hba) |
| 1728 | { | 1721 | { |
| 1729 | /* | 1722 | /* |
| 1730 | * TODO: | 1723 | * TODO: |
| @@ -1737,6 +1730,43 @@ static int ufshcd_resume(struct pci_dev *pdev) | |||
| 1737 | 1730 | ||
| 1738 | return -ENOSYS; | 1731 | return -ENOSYS; |
| 1739 | } | 1732 | } |
| 1733 | EXPORT_SYMBOL_GPL(ufshcd_resume); | ||
| 1734 | |||
| 1735 | #ifdef CONFIG_PM | ||
| 1736 | /** | ||
| 1737 | * ufshcd_pci_suspend - suspend power management function | ||
| 1738 | * @pdev: pointer to PCI device handle | ||
| 1739 | * @state: power state | ||
| 1740 | * | ||
| 1741 | * Returns -ENOSYS | ||
| 1742 | */ | ||
| 1743 | static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 1744 | { | ||
| 1745 | /* | ||
| 1746 | * TODO: | ||
| 1747 | * 1. Call ufshcd_suspend | ||
| 1748 | * 2. Do bus specific power management | ||
| 1749 | */ | ||
| 1750 | |||
| 1751 | return -ENOSYS; | ||
| 1752 | } | ||
| 1753 | |||
| 1754 | /** | ||
| 1755 | * ufshcd_pci_resume - resume power management function | ||
| 1756 | * @pdev: pointer to PCI device handle | ||
| 1757 | * | ||
| 1758 | * Returns -ENOSYS | ||
| 1759 | */ | ||
| 1760 | static int ufshcd_pci_resume(struct pci_dev *pdev) | ||
| 1761 | { | ||
| 1762 | /* | ||
| 1763 | * TODO: | ||
| 1764 | * 1. Call ufshcd_resume | ||
| 1765 | * 2. Do bus specific wake up | ||
| 1766 | */ | ||
| 1767 | |||
| 1768 | return -ENOSYS; | ||
| 1769 | } | ||
| 1740 | #endif /* CONFIG_PM */ | 1770 | #endif /* CONFIG_PM */ |
| 1741 | 1771 | ||
| 1742 | /** | 1772 | /** |
| @@ -1748,27 +1778,39 @@ static void ufshcd_hba_free(struct ufs_hba *hba) | |||
| 1748 | { | 1778 | { |
| 1749 | iounmap(hba->mmio_base); | 1779 | iounmap(hba->mmio_base); |
| 1750 | ufshcd_free_hba_memory(hba); | 1780 | ufshcd_free_hba_memory(hba); |
| 1751 | pci_release_regions(hba->pdev); | ||
| 1752 | } | 1781 | } |
| 1753 | 1782 | ||
| 1754 | /** | 1783 | /** |
| 1755 | * ufshcd_remove - de-allocate PCI/SCSI host and host memory space | 1784 | * ufshcd_remove - de-allocate SCSI host and host memory space |
| 1756 | * data structure memory | 1785 | * data structure memory |
| 1757 | * @pdev - pointer to PCI handle | 1786 | * @hba - per adapter instance |
| 1758 | */ | 1787 | */ |
| 1759 | static void ufshcd_remove(struct pci_dev *pdev) | 1788 | void ufshcd_remove(struct ufs_hba *hba) |
| 1760 | { | 1789 | { |
| 1761 | struct ufs_hba *hba = pci_get_drvdata(pdev); | ||
| 1762 | |||
| 1763 | /* disable interrupts */ | 1790 | /* disable interrupts */ |
| 1764 | ufshcd_int_config(hba, UFSHCD_INT_DISABLE); | 1791 | ufshcd_int_config(hba, UFSHCD_INT_DISABLE); |
| 1765 | free_irq(pdev->irq, hba); | ||
| 1766 | 1792 | ||
| 1767 | ufshcd_hba_stop(hba); | 1793 | ufshcd_hba_stop(hba); |
| 1768 | ufshcd_hba_free(hba); | 1794 | ufshcd_hba_free(hba); |
| 1769 | 1795 | ||
| 1770 | scsi_remove_host(hba->host); | 1796 | scsi_remove_host(hba->host); |
| 1771 | scsi_host_put(hba->host); | 1797 | scsi_host_put(hba->host); |
| 1798 | } | ||
| 1799 | EXPORT_SYMBOL_GPL(ufshcd_remove); | ||
| 1800 | |||
| 1801 | /** | ||
| 1802 | * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space | ||
| 1803 | * data structure memory | ||
| 1804 | * @pdev - pointer to PCI handle | ||
| 1805 | */ | ||
| 1806 | static void ufshcd_pci_remove(struct pci_dev *pdev) | ||
| 1807 | { | ||
| 1808 | struct ufs_hba *hba = pci_get_drvdata(pdev); | ||
| 1809 | |||
| 1810 | disable_irq(pdev->irq); | ||
| 1811 | free_irq(pdev->irq, hba); | ||
| 1812 | ufshcd_remove(hba); | ||
| 1813 | pci_release_regions(pdev); | ||
| 1772 | pci_set_drvdata(pdev, NULL); | 1814 | pci_set_drvdata(pdev, NULL); |
| 1773 | pci_clear_master(pdev); | 1815 | pci_clear_master(pdev); |
| 1774 | pci_disable_device(pdev); | 1816 | pci_disable_device(pdev); |
| @@ -1781,74 +1823,60 @@ static void ufshcd_remove(struct pci_dev *pdev) | |||
| 1781 | * | 1823 | * |
| 1782 | * Returns 0 for success, non-zero for failure | 1824 | * Returns 0 for success, non-zero for failure |
| 1783 | */ | 1825 | */ |
| 1784 | static int ufshcd_set_dma_mask(struct ufs_hba *hba) | 1826 | static int ufshcd_set_dma_mask(struct pci_dev *pdev) |
| 1785 | { | 1827 | { |
| 1786 | int err; | 1828 | int err; |
| 1787 | u64 dma_mask; | ||
| 1788 | |||
| 1789 | /* | ||
| 1790 | * If controller supports 64 bit addressing mode, then set the DMA | ||
| 1791 | * mask to 64-bit, else set the DMA mask to 32-bit | ||
| 1792 | */ | ||
| 1793 | if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) | ||
| 1794 | dma_mask = DMA_BIT_MASK(64); | ||
| 1795 | else | ||
| 1796 | dma_mask = DMA_BIT_MASK(32); | ||
| 1797 | |||
| 1798 | err = pci_set_dma_mask(hba->pdev, dma_mask); | ||
| 1799 | if (err) | ||
| 1800 | return err; | ||
| 1801 | |||
| 1802 | err = pci_set_consistent_dma_mask(hba->pdev, dma_mask); | ||
| 1803 | 1829 | ||
| 1830 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) | ||
| 1831 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) | ||
| 1832 | return 0; | ||
| 1833 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
| 1834 | if (!err) | ||
| 1835 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
| 1804 | return err; | 1836 | return err; |
| 1805 | } | 1837 | } |
| 1806 | 1838 | ||
| 1807 | /** | 1839 | /** |
| 1808 | * ufshcd_probe - probe routine of the driver | 1840 | * ufshcd_init - Driver initialization routine |
| 1809 | * @pdev: pointer to PCI device handle | 1841 | * @dev: pointer to device handle |
| 1810 | * @id: PCI device id | 1842 | * @hba_handle: driver private handle |
| 1811 | * | 1843 | * @mmio_base: base register address |
| 1844 | * @irq: Interrupt line of device | ||
| 1812 | * Returns 0 on success, non-zero value on failure | 1845 | * Returns 0 on success, non-zero value on failure |
| 1813 | */ | 1846 | */ |
| 1814 | static int ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 1847 | int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, |
| 1848 | void __iomem *mmio_base, unsigned int irq) | ||
| 1815 | { | 1849 | { |
| 1816 | struct Scsi_Host *host; | 1850 | struct Scsi_Host *host; |
| 1817 | struct ufs_hba *hba; | 1851 | struct ufs_hba *hba; |
| 1818 | int err; | 1852 | int err; |
| 1819 | 1853 | ||
| 1820 | err = pci_enable_device(pdev); | 1854 | if (!dev) { |
| 1821 | if (err) { | 1855 | dev_err(dev, |
| 1822 | dev_err(&pdev->dev, "pci_enable_device failed\n"); | 1856 | "Invalid memory reference for dev is NULL\n"); |
| 1857 | err = -ENODEV; | ||
| 1823 | goto out_error; | 1858 | goto out_error; |
| 1824 | } | 1859 | } |
| 1825 | 1860 | ||
| 1826 | pci_set_master(pdev); | 1861 | if (!mmio_base) { |
| 1862 | dev_err(dev, | ||
| 1863 | "Invalid memory reference for mmio_base is NULL\n"); | ||
| 1864 | err = -ENODEV; | ||
| 1865 | goto out_error; | ||
| 1866 | } | ||
| 1827 | 1867 | ||
| 1828 | host = scsi_host_alloc(&ufshcd_driver_template, | 1868 | host = scsi_host_alloc(&ufshcd_driver_template, |
| 1829 | sizeof(struct ufs_hba)); | 1869 | sizeof(struct ufs_hba)); |
| 1830 | if (!host) { | 1870 | if (!host) { |
| 1831 | dev_err(&pdev->dev, "scsi_host_alloc failed\n"); | 1871 | dev_err(dev, "scsi_host_alloc failed\n"); |
| 1832 | err = -ENOMEM; | 1872 | err = -ENOMEM; |
| 1833 | goto out_disable; | 1873 | goto out_error; |
| 1834 | } | 1874 | } |
| 1835 | hba = shost_priv(host); | 1875 | hba = shost_priv(host); |
| 1836 | |||
| 1837 | err = pci_request_regions(pdev, UFSHCD); | ||
| 1838 | if (err < 0) { | ||
| 1839 | dev_err(&pdev->dev, "request regions failed\n"); | ||
| 1840 | goto out_host_put; | ||
| 1841 | } | ||
| 1842 | |||
| 1843 | hba->mmio_base = pci_ioremap_bar(pdev, 0); | ||
| 1844 | if (!hba->mmio_base) { | ||
| 1845 | dev_err(&pdev->dev, "memory map failed\n"); | ||
| 1846 | err = -ENOMEM; | ||
| 1847 | goto out_release_regions; | ||
| 1848 | } | ||
| 1849 | |||
| 1850 | hba->host = host; | 1876 | hba->host = host; |
| 1851 | hba->pdev = pdev; | 1877 | hba->dev = dev; |
| 1878 | hba->mmio_base = mmio_base; | ||
| 1879 | hba->irq = irq; | ||
| 1852 | 1880 | ||
| 1853 | /* Read capabilities registers */ | 1881 | /* Read capabilities registers */ |
| 1854 | ufshcd_hba_capabilities(hba); | 1882 | ufshcd_hba_capabilities(hba); |
| @@ -1856,17 +1884,11 @@ static int ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1856 | /* Get UFS version supported by the controller */ | 1884 | /* Get UFS version supported by the controller */ |
| 1857 | hba->ufs_version = ufshcd_get_ufs_version(hba); | 1885 | hba->ufs_version = ufshcd_get_ufs_version(hba); |
| 1858 | 1886 | ||
| 1859 | err = ufshcd_set_dma_mask(hba); | ||
| 1860 | if (err) { | ||
| 1861 | dev_err(&pdev->dev, "set dma mask failed\n"); | ||
| 1862 | goto out_iounmap; | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | /* Allocate memory for host memory space */ | 1887 | /* Allocate memory for host memory space */ |
| 1866 | err = ufshcd_memory_alloc(hba); | 1888 | err = ufshcd_memory_alloc(hba); |
| 1867 | if (err) { | 1889 | if (err) { |
| 1868 | dev_err(&pdev->dev, "Memory allocation failed\n"); | 1890 | dev_err(hba->dev, "Memory allocation failed\n"); |
| 1869 | goto out_iounmap; | 1891 | goto out_disable; |
| 1870 | } | 1892 | } |
| 1871 | 1893 | ||
| 1872 | /* Configure LRB */ | 1894 | /* Configure LRB */ |
| @@ -1888,46 +1910,102 @@ static int ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1888 | INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler); | 1910 | INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler); |
| 1889 | 1911 | ||
| 1890 | /* IRQ registration */ | 1912 | /* IRQ registration */ |
| 1891 | err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba); | 1913 | err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba); |
| 1892 | if (err) { | 1914 | if (err) { |
| 1893 | dev_err(&pdev->dev, "request irq failed\n"); | 1915 | dev_err(hba->dev, "request irq failed\n"); |
| 1894 | goto out_lrb_free; | 1916 | goto out_lrb_free; |
| 1895 | } | 1917 | } |
| 1896 | 1918 | ||
| 1897 | /* Enable SCSI tag mapping */ | 1919 | /* Enable SCSI tag mapping */ |
| 1898 | err = scsi_init_shared_tag_map(host, host->can_queue); | 1920 | err = scsi_init_shared_tag_map(host, host->can_queue); |
| 1899 | if (err) { | 1921 | if (err) { |
| 1900 | dev_err(&pdev->dev, "init shared queue failed\n"); | 1922 | dev_err(hba->dev, "init shared queue failed\n"); |
| 1901 | goto out_free_irq; | 1923 | goto out_free_irq; |
| 1902 | } | 1924 | } |
| 1903 | 1925 | ||
| 1904 | pci_set_drvdata(pdev, hba); | 1926 | err = scsi_add_host(host, hba->dev); |
| 1905 | |||
| 1906 | err = scsi_add_host(host, &pdev->dev); | ||
| 1907 | if (err) { | 1927 | if (err) { |
| 1908 | dev_err(&pdev->dev, "scsi_add_host failed\n"); | 1928 | dev_err(hba->dev, "scsi_add_host failed\n"); |
| 1909 | goto out_free_irq; | 1929 | goto out_free_irq; |
| 1910 | } | 1930 | } |
| 1911 | 1931 | ||
| 1912 | /* Initialization routine */ | 1932 | /* Initialization routine */ |
| 1913 | err = ufshcd_initialize_hba(hba); | 1933 | err = ufshcd_initialize_hba(hba); |
| 1914 | if (err) { | 1934 | if (err) { |
| 1915 | dev_err(&pdev->dev, "Initialization failed\n"); | 1935 | dev_err(hba->dev, "Initialization failed\n"); |
| 1916 | goto out_free_irq; | 1936 | goto out_remove_scsi_host; |
| 1917 | } | 1937 | } |
| 1938 | *hba_handle = hba; | ||
| 1918 | 1939 | ||
| 1919 | return 0; | 1940 | return 0; |
| 1920 | 1941 | ||
| 1942 | out_remove_scsi_host: | ||
| 1943 | scsi_remove_host(hba->host); | ||
| 1921 | out_free_irq: | 1944 | out_free_irq: |
| 1922 | free_irq(pdev->irq, hba); | 1945 | free_irq(irq, hba); |
| 1923 | out_lrb_free: | 1946 | out_lrb_free: |
| 1924 | ufshcd_free_hba_memory(hba); | 1947 | ufshcd_free_hba_memory(hba); |
| 1948 | out_disable: | ||
| 1949 | scsi_host_put(host); | ||
| 1950 | out_error: | ||
| 1951 | return err; | ||
| 1952 | } | ||
| 1953 | EXPORT_SYMBOL_GPL(ufshcd_init); | ||
| 1954 | |||
| 1955 | /** | ||
| 1956 | * ufshcd_pci_probe - probe routine of the driver | ||
| 1957 | * @pdev: pointer to PCI device handle | ||
| 1958 | * @id: PCI device id | ||
| 1959 | * | ||
| 1960 | * Returns 0 on success, non-zero value on failure | ||
| 1961 | */ | ||
| 1962 | static int ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
| 1963 | { | ||
| 1964 | struct ufs_hba *hba; | ||
| 1965 | void __iomem *mmio_base; | ||
| 1966 | int err; | ||
| 1967 | |||
| 1968 | err = pci_enable_device(pdev); | ||
| 1969 | if (err) { | ||
| 1970 | dev_err(&pdev->dev, "pci_enable_device failed\n"); | ||
| 1971 | goto out_error; | ||
| 1972 | } | ||
| 1973 | |||
| 1974 | pci_set_master(pdev); | ||
| 1975 | |||
| 1976 | err = pci_request_regions(pdev, UFSHCD); | ||
| 1977 | if (err < 0) { | ||
| 1978 | dev_err(&pdev->dev, "request regions failed\n"); | ||
| 1979 | goto out_disable; | ||
| 1980 | } | ||
| 1981 | |||
| 1982 | mmio_base = pci_ioremap_bar(pdev, 0); | ||
| 1983 | if (!mmio_base) { | ||
| 1984 | dev_err(&pdev->dev, "memory map failed\n"); | ||
| 1985 | err = -ENOMEM; | ||
| 1986 | goto out_release_regions; | ||
| 1987 | } | ||
| 1988 | |||
| 1989 | err = ufshcd_set_dma_mask(pdev); | ||
| 1990 | if (err) { | ||
| 1991 | dev_err(&pdev->dev, "set dma mask failed\n"); | ||
| 1992 | goto out_iounmap; | ||
| 1993 | } | ||
| 1994 | |||
| 1995 | err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq); | ||
| 1996 | if (err) { | ||
| 1997 | dev_err(&pdev->dev, "Initialization failed\n"); | ||
| 1998 | goto out_iounmap; | ||
| 1999 | } | ||
| 2000 | |||
| 2001 | pci_set_drvdata(pdev, hba); | ||
| 2002 | |||
| 2003 | return 0; | ||
| 2004 | |||
| 1925 | out_iounmap: | 2005 | out_iounmap: |
| 1926 | iounmap(hba->mmio_base); | 2006 | iounmap(mmio_base); |
| 1927 | out_release_regions: | 2007 | out_release_regions: |
| 1928 | pci_release_regions(pdev); | 2008 | pci_release_regions(pdev); |
| 1929 | out_host_put: | ||
| 1930 | scsi_host_put(host); | ||
| 1931 | out_disable: | 2009 | out_disable: |
| 1932 | pci_clear_master(pdev); | 2010 | pci_clear_master(pdev); |
| 1933 | pci_disable_device(pdev); | 2011 | pci_disable_device(pdev); |
| @@ -1945,19 +2023,19 @@ MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl); | |||
| 1945 | static struct pci_driver ufshcd_pci_driver = { | 2023 | static struct pci_driver ufshcd_pci_driver = { |
| 1946 | .name = UFSHCD, | 2024 | .name = UFSHCD, |
| 1947 | .id_table = ufshcd_pci_tbl, | 2025 | .id_table = ufshcd_pci_tbl, |
| 1948 | .probe = ufshcd_probe, | 2026 | .probe = ufshcd_pci_probe, |
| 1949 | .remove = ufshcd_remove, | 2027 | .remove = ufshcd_pci_remove, |
| 1950 | .shutdown = ufshcd_shutdown, | 2028 | .shutdown = ufshcd_pci_shutdown, |
| 1951 | #ifdef CONFIG_PM | 2029 | #ifdef CONFIG_PM |
| 1952 | .suspend = ufshcd_suspend, | 2030 | .suspend = ufshcd_pci_suspend, |
| 1953 | .resume = ufshcd_resume, | 2031 | .resume = ufshcd_pci_resume, |
| 1954 | #endif | 2032 | #endif |
| 1955 | }; | 2033 | }; |
| 1956 | 2034 | ||
| 1957 | module_pci_driver(ufshcd_pci_driver); | 2035 | module_pci_driver(ufshcd_pci_driver); |
| 1958 | 2036 | ||
| 1959 | MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, " | 2037 | MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>"); |
| 1960 | "Vinayak Holikatti <h.vinayak@samsung.com>"); | 2038 | MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>"); |
| 1961 | MODULE_DESCRIPTION("Generic UFS host controller driver"); | 2039 | MODULE_DESCRIPTION("Generic UFS host controller driver"); |
| 1962 | MODULE_LICENSE("GPL"); | 2040 | MODULE_LICENSE("GPL"); |
| 1963 | MODULE_VERSION(UFSHCD_DRIVER_VERSION); | 2041 | MODULE_VERSION(UFSHCD_DRIVER_VERSION); |
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index 6e3510f71167..0c164847a3ef 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h | |||
| @@ -2,45 +2,35 @@ | |||
| 2 | * Universal Flash Storage Host controller driver | 2 | * Universal Flash Storage Host controller driver |
| 3 | * | 3 | * |
| 4 | * This code is based on drivers/scsi/ufs/ufshci.h | 4 | * This code is based on drivers/scsi/ufs/ufshci.h |
| 5 | * Copyright (C) 2011-2012 Samsung India Software Operations | 5 | * Copyright (C) 2011-2013 Samsung India Software Operations |
| 6 | * | 6 | * |
| 7 | * Santosh Yaraganavi <santosh.sy@samsung.com> | 7 | * Authors: |
| 8 | * Vinayak Holikatti <h.vinayak@samsung.com> | 8 | * Santosh Yaraganavi <santosh.sy@samsung.com> |
| 9 | * Vinayak Holikatti <h.vinayak@samsung.com> | ||
| 9 | * | 10 | * |
| 10 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
| 11 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
| 12 | * as published by the Free Software Foundation; either version 2 | 13 | * as published by the Free Software Foundation; either version 2 |
| 13 | * of the License, or (at your option) any later version. | 14 | * of the License, or (at your option) any later version. |
| 15 | * See the COPYING file in the top-level directory or visit | ||
| 16 | * <http://www.gnu.org/licenses/gpl-2.0.html> | ||
| 14 | * | 17 | * |
| 15 | * This program is distributed in the hope that it will be useful, | 18 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | * GNU General Public License for more details. | 21 | * GNU General Public License for more details. |
| 19 | * | 22 | * |
| 20 | * NO WARRANTY | 23 | * This program is provided "AS IS" and "WITH ALL FAULTS" and |
| 21 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | 24 | * without warranty of any kind. You are solely responsible for |
| 22 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | 25 | * determining the appropriateness of using and distributing |
| 23 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | 26 | * the program and assume all risks associated with your exercise |
| 24 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | 27 | * of rights with respect to the program, including but not limited |
| 25 | * solely responsible for determining the appropriateness of using and | 28 | * to infringement of third party rights, the risks and costs of |
| 26 | * distributing the Program and assumes all risks associated with its | 29 | * program errors, damage to or loss of data, programs or equipment, |
| 27 | * exercise of rights under this Agreement, including but not limited to | 30 | * and unavailability or interruption of operations. Under no |
| 28 | * the risks and costs of program errors, damage to or loss of data, | 31 | * circumstances will the contributor of this Program be liable for |
| 29 | * programs or equipment, and unavailability or interruption of operations. | 32 | * any damages of any kind arising from your use or distribution of |
| 30 | 33 | * this program. | |
| 31 | * DISCLAIMER OF LIABILITY | ||
| 32 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 33 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 34 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 35 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 36 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 37 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 38 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 39 | |||
| 40 | * You should have received a copy of the GNU General Public License | ||
| 41 | * along with this program; if not, write to the Free Software | ||
| 42 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 43 | * USA. | ||
| 44 | */ | 34 | */ |
| 45 | 35 | ||
| 46 | #ifndef _UFSHCI_H | 36 | #ifndef _UFSHCI_H |
