1dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik/* 220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * Marvell 88SE64xx/88SE94xx pci init 320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * Copyright 2007 Red Hat, Inc. 520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * Copyright 2008 Marvell. <kewei@marvell.com> 60b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * This file is licensed under GPLv2. 920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 1020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * This program is free software; you can redistribute it and/or 1120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * modify it under the terms of the GNU General Public License as 1220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * published by the Free Software Foundation; version 2 of the 1320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * License. 1420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 1520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * This program is distributed in the hope that it will be useful, 1620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * but WITHOUT ANY WARRANTY; without even the implied warranty of 1720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * General Public License for more details. 1920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 2020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * You should have received a copy of the GNU General Public License 2120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * along with this program; if not, write to the Free Software 2220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 2320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * USA 2420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan*/ 25dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 26dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 27dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#include "mv_sas.h" 28dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 290b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yustatic int lldd_max_execute_num = 1; 300b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yumodule_param_named(collector, lldd_max_execute_num, int, S_IRUGO); 310b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang YuMODULE_PARM_DESC(collector, "\n" 320b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu "\tIf greater than one, tells the SAS Layer to run in Task Collector\n" 330b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu "\tMode. If 1 or 0, tells the SAS Layer to run in Direct Mode.\n" 340b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu "\tThe mvsas SAS LLDD supports both modes.\n" 350b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu "\tDefault: 1 (Direct Mode).\n"); 360b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu 3783c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yuint interrupt_coalescing = 0x80; 3883c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 39dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic struct scsi_transport_template *mvs_stt; 400b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yustruct kmem_cache *mvs_task_list_cache; 41dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic const struct mvs_chip_info mvs_chips[] = { 42a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu [chip_6320] = { 1, 2, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, }, 43a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu [chip_6440] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, }, 44a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu [chip_6485] = { 1, 8, 0x800, 33, 32, 6, 10, &mvs_64xx_dispatch, }, 45a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu [chip_9180] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, }, 46a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu [chip_9480] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, }, 47a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu [chip_9445] = { 1, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, }, 48a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu [chip_9485] = { 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, }, 49a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu [chip_1300] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, }, 50a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu [chip_1320] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, }, 51dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik}; 52dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 5383c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yustruct device_attribute *mvst_host_attrs[]; 5483c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 5520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#define SOC_SAS_NUM 2 5620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 57dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic struct scsi_host_template mvs_sht = { 58dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .module = THIS_MODULE, 59dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .name = DRV_NAME, 60dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .queuecommand = sas_queuecommand, 61dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .target_alloc = sas_target_alloc, 62e211e2c7b6e7f470c818ef67c952954e1b46a46dDan Williams .slave_configure = sas_slave_configure, 63dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .scan_finished = mvs_scan_finished, 64dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .scan_start = mvs_scan_start, 65dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .change_queue_depth = sas_change_queue_depth, 66dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .change_queue_type = sas_change_queue_type, 67dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .bios_param = sas_bios_param, 68dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .can_queue = 1, 69dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .cmd_per_lun = 1, 70dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .this_id = -1, 71b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu .sg_tablesize = SG_ALL, 72dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .max_sectors = SCSI_DEFAULT_MAX_SECTORS, 73dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .use_clustering = ENABLE_CLUSTERING, 749dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas .eh_device_reset_handler = sas_eh_device_reset_handler, 75dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .eh_bus_reset_handler = sas_eh_bus_reset_handler, 76dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .target_destroy = sas_target_destroy, 77dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .ioctl = sas_ioctl, 7883c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu .shost_attrs = mvst_host_attrs, 79dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik}; 80dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 81dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic struct sas_domain_function_template mvs_transport_ops = { 8220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .lldd_dev_found = mvs_dev_found, 839dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas .lldd_dev_gone = mvs_dev_gone, 8420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .lldd_execute_task = mvs_queue_command, 85dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .lldd_control_phy = mvs_phy_control, 8620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 8720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .lldd_abort_task = mvs_abort_task, 8820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .lldd_abort_task_set = mvs_abort_task_set, 8920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .lldd_clear_aca = mvs_clear_aca, 909dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas .lldd_clear_task_set = mvs_clear_task_set, 91dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .lldd_I_T_nexus_reset = mvs_I_T_nexus_reset, 9220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .lldd_lu_reset = mvs_lu_reset, 9320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .lldd_query_task = mvs_query_task, 9420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .lldd_port_formed = mvs_port_formed, 9520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .lldd_port_deformed = mvs_port_deformed, 9620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 97dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik}; 98dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 99dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id) 100dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 101dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_phy *phy = &mvi->phy[phy_id]; 102dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct asd_sas_phy *sas_phy = &phy->sas_phy; 103dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 10420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->mvi = mvi; 10584fbd0cea11b80d7b7097343d5262004d42b8a9aXiangliang Yu phy->port = NULL; 10620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan init_timer(&phy->timer); 107dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0; 108dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->class = SAS; 109dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->iproto = SAS_PROTOCOL_ALL; 110dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->tproto = 0; 111dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->type = PHY_TYPE_PHYSICAL; 112dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->role = PHY_ROLE_INITIATOR; 113dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->oob_mode = OOB_NOT_CONNECTED; 114dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN; 115dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 116dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->id = phy_id; 117dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->sas_addr = &mvi->sas_addr[0]; 118dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->frame_rcvd = &phy->frame_rcvd[0]; 11920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_phy->ha = (struct sas_ha_struct *)mvi->shost->hostdata; 120dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->lldd_phy = phy; 121dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 122dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 123dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic void mvs_free(struct mvs_info *mvi) 124dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 12520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_wq *mwq; 12620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int slot_nr; 127dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 128dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!mvi) 129dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return; 130dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 13120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->flags & MVF_FLAG_SOC) 13220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan slot_nr = MVS_SOC_SLOTS; 13320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 134b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu slot_nr = MVS_CHIP_SLOT_SZ; 135dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1360b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu if (mvi->dma_pool) 1370b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu pci_pool_destroy(mvi->dma_pool); 138dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 139dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (mvi->tx) 14020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_free_coherent(mvi->dev, 141dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ, 142dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->tx, mvi->tx_dma); 143dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (mvi->rx_fis) 14420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_free_coherent(mvi->dev, MVS_RX_FISL_SZ, 145dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->rx_fis, mvi->rx_fis_dma); 146dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (mvi->rx) 14720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_free_coherent(mvi->dev, 148dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1), 149dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->rx, mvi->rx_dma); 150dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (mvi->slot) 15120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_free_coherent(mvi->dev, 15220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sizeof(*mvi->slot) * slot_nr, 153dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->slot, mvi->slot_dma); 1548882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu 15520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->bulk_buffer) 15620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE, 15720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->bulk_buffer, mvi->bulk_buffer_dma); 1588882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu if (mvi->bulk_buffer1) 1598882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE, 1608882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu mvi->bulk_buffer1, mvi->bulk_buffer_dma1); 16120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 16220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->chip_iounmap(mvi); 163dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (mvi->shost) 164dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik scsi_host_put(mvi->shost); 16520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan list_for_each_entry(mwq, &mvi->wq_list, entry) 16620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan cancel_delayed_work(&mwq->work_q); 167b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu kfree(mvi->tags); 168dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik kfree(mvi); 169dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 170dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1716f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu#ifdef CONFIG_SCSI_MVSAS_TASKLET 17220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_tasklet(unsigned long opaque) 173dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 17420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 stat; 17520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u16 core_nr, i = 0; 176dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 17720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi; 17820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = (struct sas_ha_struct *)opaque; 17920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 18020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; 18120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; 18220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 18320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (unlikely(!mvi)) 18420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan BUG_ON(1); 18520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 1866f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu stat = MVS_CHIP_DISP->isr_status(mvi, mvi->pdev->irq); 1876f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu if (!stat) 1886f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu goto out; 1896f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu 19020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < core_nr; i++) { 19120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; 1926f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu MVS_CHIP_DISP->isr(mvi, mvi->pdev->irq, stat); 19320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 1946f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yuout: 1956f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu MVS_CHIP_DISP->interrupt_enable(mvi); 196dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 197dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 198dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#endif 199dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 200dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic irqreturn_t mvs_interrupt(int irq, void *opaque) 201dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 2026f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu u32 core_nr; 203dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik u32 stat; 20420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi; 20520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = opaque; 2066f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu#ifndef CONFIG_SCSI_MVSAS_TASKLET 2076f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu u32 i; 2086f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu#endif 209dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 21020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; 21120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; 212dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 21320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (unlikely(!mvi)) 214dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return IRQ_NONE; 2156f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu#ifdef CONFIG_SCSI_MVSAS_TASKLET 2166f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu MVS_CHIP_DISP->interrupt_disable(mvi); 2176f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu#endif 218dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 21920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan stat = MVS_CHIP_DISP->isr_status(mvi, irq); 2206f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu if (!stat) { 2216f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu #ifdef CONFIG_SCSI_MVSAS_TASKLET 2226f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu MVS_CHIP_DISP->interrupt_enable(mvi); 2236f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu #endif 22420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return IRQ_NONE; 2256f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu } 226dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 2276f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu#ifdef CONFIG_SCSI_MVSAS_TASKLET 2286f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu tasklet_schedule(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet); 229dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#else 23020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < core_nr; i++) { 23120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; 23220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->isr(mvi, irq, stat); 23320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 234dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#endif 235dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return IRQ_HANDLED; 236dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 237dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 23820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost) 239dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 2409dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas int i = 0, slot_nr; 2410b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu char pool_name[32]; 242dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 24320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->flags & MVF_FLAG_SOC) 24420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan slot_nr = MVS_SOC_SLOTS; 24520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 246b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu slot_nr = MVS_CHIP_SLOT_SZ; 247dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 248dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik spin_lock_init(&mvi->lock); 24920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < mvi->chip->n_phy; i++) { 250dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_phy_init(mvi, i); 251dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->port[i].wide_port_phymap = 0; 252dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->port[i].port_attached = 0; 253dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik INIT_LIST_HEAD(&mvi->port[i].list); 254dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 25520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < MVS_MAX_DEVICES; i++) { 25620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->devices[i].taskfileset = MVS_ID_NOT_MAPPED; 25720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->devices[i].dev_type = NO_DEVICE; 25820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->devices[i].device_id = i; 25920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->devices[i].dev_status = MVS_DEV_NORMAL; 2609dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas init_timer(&mvi->devices[i].timer); 26120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 262dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 263dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* 264dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik * alloc and init our DMA areas 265dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik */ 26620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->tx = dma_alloc_coherent(mvi->dev, 267dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ, 268dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik &mvi->tx_dma, GFP_KERNEL); 269dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!mvi->tx) 270dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 271dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik memset(mvi->tx, 0, sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ); 27220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->rx_fis = dma_alloc_coherent(mvi->dev, MVS_RX_FISL_SZ, 273dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik &mvi->rx_fis_dma, GFP_KERNEL); 274dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!mvi->rx_fis) 275dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 276dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik memset(mvi->rx_fis, 0, MVS_RX_FISL_SZ); 277dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 27820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->rx = dma_alloc_coherent(mvi->dev, 279dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1), 280dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik &mvi->rx_dma, GFP_KERNEL); 281dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!mvi->rx) 282dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 283dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik memset(mvi->rx, 0, sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1)); 284dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->rx[0] = cpu_to_le32(0xfff); 285dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->rx_cons = 0xfff; 286dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 28720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->slot = dma_alloc_coherent(mvi->dev, 28820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sizeof(*mvi->slot) * slot_nr, 289dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik &mvi->slot_dma, GFP_KERNEL); 290dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!mvi->slot) 291dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 29220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memset(mvi->slot, 0, sizeof(*mvi->slot) * slot_nr); 293dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 29420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->bulk_buffer = dma_alloc_coherent(mvi->dev, 29520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan TRASH_BUCKET_SIZE, 29620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan &mvi->bulk_buffer_dma, GFP_KERNEL); 29720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!mvi->bulk_buffer) 29820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out; 2998882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu 3008882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu mvi->bulk_buffer1 = dma_alloc_coherent(mvi->dev, 3018882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu TRASH_BUCKET_SIZE, 3028882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu &mvi->bulk_buffer_dma1, GFP_KERNEL); 3038882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu if (!mvi->bulk_buffer1) 3048882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu goto err_out; 3058882f081329a82737b7471b97e59ce8c407f6655Xiangliang Yu 3060b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu sprintf(pool_name, "%s%d", "mvs_dma_pool", mvi->id); 3070b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu mvi->dma_pool = pci_pool_create(pool_name, mvi->pdev, MVS_SLOT_BUF_SZ, 16, 0); 3080b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu if (!mvi->dma_pool) { 3090b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu printk(KERN_DEBUG "failed to create dma pool %s.\n", pool_name); 310dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 311dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 3120b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu mvi->tags_num = slot_nr; 3130b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu 31420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* Initialize tags */ 31520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_tag_init(mvi); 31620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return 0; 31720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanerr_out: 31820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return 1; 31920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 32020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 321dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 32220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex) 32320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 32420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long res_start, res_len, res_flag, res_flag_ex = 0; 32520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct pci_dev *pdev = mvi->pdev; 32620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (bar_ex != -1) { 32720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* 32820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * ioremap main and peripheral registers 32920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan */ 33020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res_start = pci_resource_start(pdev, bar_ex); 33120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res_len = pci_resource_len(pdev, bar_ex); 33220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!res_start || !res_len) 33320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out; 33420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 33520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res_flag_ex = pci_resource_flags(pdev, bar_ex); 33620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (res_flag_ex & IORESOURCE_MEM) { 33720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (res_flag_ex & IORESOURCE_CACHEABLE) 33820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->regs_ex = ioremap(res_start, res_len); 33920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 34020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->regs_ex = ioremap_nocache(res_start, 34120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res_len); 34220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else 34320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->regs_ex = (void *)res_start; 34420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!mvi->regs_ex) 34520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out; 34620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 34720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 34820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res_start = pci_resource_start(pdev, bar); 34920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res_len = pci_resource_len(pdev, bar); 35020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!res_start || !res_len) 35120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out; 35220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 35320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res_flag = pci_resource_flags(pdev, bar); 35420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (res_flag & IORESOURCE_CACHEABLE) 35520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->regs = ioremap(res_start, res_len); 35620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 35720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->regs = ioremap_nocache(res_start, res_len); 35820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 35920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!mvi->regs) { 36020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->regs_ex && (res_flag_ex & IORESOURCE_MEM)) 36120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan iounmap(mvi->regs_ex); 36220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->regs_ex = NULL; 363dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 36420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 36520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 36620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return 0; 36720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanerr_out: 36820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return -1; 36920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 37020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 37120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_iounmap(void __iomem *regs) 37220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 37320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan iounmap(regs); 37420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 37520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 37620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev, 37720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan const struct pci_device_id *ent, 37820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct Scsi_Host *shost, unsigned int id) 37920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 38084fbd0cea11b80d7b7097343d5262004d42b8a9aXiangliang Yu struct mvs_info *mvi = NULL; 38120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 38220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 383b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu mvi = kzalloc(sizeof(*mvi) + 384b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu (1L << mvs_chips[ent->driver_data].slot_width) * 385b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu sizeof(struct mvs_slot_info), GFP_KERNEL); 38620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!mvi) 38720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return NULL; 388dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 38920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->pdev = pdev; 39020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->dev = &pdev->dev; 39120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->chip_id = ent->driver_data; 39220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->chip = &mvs_chips[mvi->chip_id]; 39320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan INIT_LIST_HEAD(&mvi->wq_list); 39420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 39520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan ((struct mvs_prv_info *)sha->lldd_ha)->mvi[id] = mvi; 39620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan ((struct mvs_prv_info *)sha->lldd_ha)->n_phy = mvi->chip->n_phy; 39720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 39820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->id = id; 39920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->sas = sha; 40020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->shost = shost; 40120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 402b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu mvi->tags = kzalloc(MVS_CHIP_SLOT_SZ>>3, GFP_KERNEL); 403b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu if (!mvi->tags) 404b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu goto err_out; 405b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu 40620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (MVS_CHIP_DISP->chip_ioremap(mvi)) 40720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out; 40820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!mvs_alloc(mvi, shost)) 40920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return mvi; 410dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikerr_out: 411dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_free(mvi); 412dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return NULL; 413dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 414dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 415dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic int pci_go_64(struct pci_dev *pdev) 416dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 417dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik int rc; 418dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 419dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { 420dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); 421dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) { 422dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 423dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) { 424dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 425dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik "64-bit DMA enable failed\n"); 426dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return rc; 427dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 428dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 429dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } else { 430dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 431dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) { 432dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 433dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik "32-bit DMA enable failed\n"); 434dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return rc; 435dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 436dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 437dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) { 438dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 439dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik "32-bit consistent DMA enable failed\n"); 440dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return rc; 441dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 442dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 443dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 444dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return rc; 445dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 446dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 44720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost, 44820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan const struct mvs_chip_info *chip_info) 44920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 45020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int phy_nr, port_nr; unsigned short core_nr; 45120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_phy **arr_phy; 45220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_port **arr_port; 45320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 45420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 45520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan core_nr = chip_info->n_host; 45620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy_nr = core_nr * chip_info->n_phy; 45720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan port_nr = phy_nr; 45820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 45920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memset(sha, 0x00, sizeof(struct sas_ha_struct)); 46020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan arr_phy = kcalloc(phy_nr, sizeof(void *), GFP_KERNEL); 46120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan arr_port = kcalloc(port_nr, sizeof(void *), GFP_KERNEL); 46220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!arr_phy || !arr_port) 46320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto exit_free; 46420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 46520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->sas_phy = arr_phy; 46620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->sas_port = arr_port; 4679dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas sha->core.shost = shost; 46820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 46920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->lldd_ha = kzalloc(sizeof(struct mvs_prv_info), GFP_KERNEL); 47020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!sha->lldd_ha) 47120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto exit_free; 47220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 47320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan ((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr; 47420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 47520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan shost->transportt = mvs_stt; 476a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu shost->max_id = MVS_MAX_DEVICES; 47720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan shost->max_lun = ~0; 47820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan shost->max_channel = 1; 47920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan shost->max_cmd_len = 16; 48020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 48120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return 0; 48220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanexit_free: 48320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kfree(arr_phy); 48420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kfree(arr_port); 48520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return -1; 48620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 48720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 48820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 48920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost, 49020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan const struct mvs_chip_info *chip_info) 49120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 49220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int can_queue, i = 0, j = 0; 49320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi = NULL; 49420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 49520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned short nr_core = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; 49620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 49720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (j = 0; j < nr_core; j++) { 49820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j]; 49920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < chip_info->n_phy; i++) { 50020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->sas_phy[j * chip_info->n_phy + i] = 50120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan &mvi->phy[i].sas_phy; 50220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->sas_port[j * chip_info->n_phy + i] = 50320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan &mvi->port[i].sas_port; 50420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 50520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 50620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 50720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->sas_ha_name = DRV_NAME; 50820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->dev = mvi->dev; 50920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->lldd_module = THIS_MODULE; 51020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->sas_addr = &mvi->sas_addr[0]; 51120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 51220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->num_phys = nr_core * chip_info->n_phy; 51320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 5140b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu sha->lldd_max_execute_num = lldd_max_execute_num; 51520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 51620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->flags & MVF_FLAG_SOC) 51720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan can_queue = MVS_SOC_CAN_QUEUE; 51820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 519b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu can_queue = MVS_CHIP_SLOT_SZ; 52020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 52120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->lldd_queue_size = can_queue; 522a4632aae8b662b1f32fe3fc558a813cd5c3daae6Xiangliang Yu shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG); 52320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan shost->can_queue = can_queue; 524b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE; 52520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sha->core.shost = mvi->shost; 52620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 52720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 52820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_init_sas_add(struct mvs_info *mvi) 52920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 53020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u8 i; 53120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < mvi->chip->n_phy; i++) { 53220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->phy[i].dev_sas_addr = 0x5005043011ab0000ULL; 53320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->phy[i].dev_sas_addr = 53420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan cpu_to_be64((u64)(*(u64 *)&mvi->phy[i].dev_sas_addr)); 53520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 53620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 53720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(mvi->sas_addr, &mvi->phy[0].dev_sas_addr, SAS_ADDR_SIZE); 53820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 53920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 540dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic int __devinit mvs_pci_init(struct pci_dev *pdev, 541dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik const struct pci_device_id *ent) 542dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 54320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned int rc, nhost = 0; 544dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_info *mvi; 5456f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu struct mvs_prv_info *mpi; 546dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik irq_handler_t irq_handler = mvs_interrupt; 54720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct Scsi_Host *shost = NULL; 54820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan const struct mvs_chip_info *chip; 549dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 55020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_INFO, &pdev->dev, 55120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan "mvsas: driver version %s\n", DRV_VERSION); 552dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = pci_enable_device(pdev); 553dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) 55420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out_enable; 555dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 556dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik pci_set_master(pdev); 557dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 558dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = pci_request_regions(pdev, DRV_NAME); 559dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) 560dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out_disable; 561dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 562dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = pci_go_64(pdev); 563dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) 564dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out_regions; 565dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 56620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan shost = scsi_host_alloc(&mvs_sht, sizeof(void *)); 56720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!shost) { 568dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = -ENOMEM; 569dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out_regions; 570dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 571dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 57220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan chip = &mvs_chips[ent->driver_data]; 57320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan SHOST_TO_SAS_HA(shost) = 57420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kcalloc(1, sizeof(struct sas_ha_struct), GFP_KERNEL); 57520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!SHOST_TO_SAS_HA(shost)) { 57620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kfree(shost); 57720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = -ENOMEM; 57820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out_regions; 579dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 580dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 58120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_prep_sas_ha_init(shost, chip); 58220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc) { 58320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kfree(shost); 58420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = -ENOMEM; 58520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out_regions; 58620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 587dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 58820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost)); 589dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 59020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan do { 59120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = mvs_pci_alloc(pdev, ent, shost, nhost); 59220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!mvi) { 59320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = -ENOMEM; 59420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out_regions; 59520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 59620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 597f1f82a919d7fff21ee8c0ef4b9731fb38f2a65dbXiangliang Yu memset(&mvi->hba_info_param, 0xFF, 598f1f82a919d7fff21ee8c0ef4b9731fb38f2a65dbXiangliang Yu sizeof(struct hba_info_page)); 599f1f82a919d7fff21ee8c0ef4b9731fb38f2a65dbXiangliang Yu 60020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_init_sas_add(mvi); 60120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 60220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->instance = nhost; 60320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = MVS_CHIP_DISP->chip_init(mvi); 60420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc) { 60520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_free(mvi); 60620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out_regions; 60720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 60820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan nhost++; 60920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } while (nhost < chip->n_host); 6106f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu mpi = (struct mvs_prv_info *)(SHOST_TO_SAS_HA(shost)->lldd_ha); 6116f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu#ifdef CONFIG_SCSI_MVSAS_TASKLET 6126f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu tasklet_init(&(mpi->mv_tasklet), mvs_tasklet, 6139dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas (unsigned long)SHOST_TO_SAS_HA(shost)); 6149dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas#endif 61520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 61620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_post_sas_ha_init(shost, chip); 61720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 61820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = scsi_add_host(shost, &pdev->dev); 619dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) 620dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out_shost; 621dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 62220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); 62320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc) 62420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_out_shost; 62520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, 62620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan DRV_NAME, SHOST_TO_SAS_HA(shost)); 62720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc) 62820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto err_not_sas; 629dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 63020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->interrupt_enable(mvi); 631dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 632dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik scsi_scan_host(mvi->shost); 633dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 634dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 0; 635dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 63620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanerr_not_sas: 63720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_unregister_ha(SHOST_TO_SAS_HA(shost)); 638dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikerr_out_shost: 639dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik scsi_remove_host(mvi->shost); 640dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikerr_out_regions: 641dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik pci_release_regions(pdev); 642dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikerr_out_disable: 643dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik pci_disable_device(pdev); 64420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanerr_out_enable: 645dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return rc; 646dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 647dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 648dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic void __devexit mvs_pci_remove(struct pci_dev *pdev) 649dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 65020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned short core_nr, i = 0; 65120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = pci_get_drvdata(pdev); 65220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi = NULL; 653dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 65420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; 65520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; 656dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 6576f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu#ifdef CONFIG_SCSI_MVSAS_TASKLET 6586f8ac161b8b3332a9d96d6650ed3bae81baab30bXiangliang Yu tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet); 65920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#endif 660dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 66120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan pci_set_drvdata(pdev, NULL); 66220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_unregister_ha(sha); 66320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_remove_host(mvi->shost); 66420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan scsi_remove_host(mvi->shost); 66520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 66620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->interrupt_disable(mvi); 667b89e8f539ff8bcf2a1464578fa91cb96cc433fc3Xiangliang Yu free_irq(mvi->pdev->irq, sha); 66820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < core_nr; i++) { 66920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; 670dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_free(mvi); 671dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 67220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kfree(sha->sas_phy); 67320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kfree(sha->sas_port); 67420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kfree(sha); 67520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan pci_release_regions(pdev); 676dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik pci_disable_device(pdev); 67720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return; 678dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 679dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 680dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic struct pci_device_id __devinitdata mvs_pci_table[] = { 681dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik { PCI_VDEVICE(MARVELL, 0x6320), chip_6320 }, 682dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik { PCI_VDEVICE(MARVELL, 0x6340), chip_6440 }, 683dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik { 684dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .vendor = PCI_VENDOR_ID_MARVELL, 685dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .device = 0x6440, 686dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .subvendor = PCI_ANY_ID, 687dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .subdevice = 0x6480, 688dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .class = 0, 689dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .class_mask = 0, 69020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan .driver_data = chip_6485, 691dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik }, 692dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik { PCI_VDEVICE(MARVELL, 0x6440), chip_6440 }, 69320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan { PCI_VDEVICE(MARVELL, 0x6485), chip_6485 }, 69420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan { PCI_VDEVICE(MARVELL, 0x9480), chip_9480 }, 69520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan { PCI_VDEVICE(MARVELL, 0x9180), chip_9180 }, 696f31491dc73a6459d601da8d9a5817a31c7dfc17bNick Cheng { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 }, 697f31491dc73a6459d601da8d9a5817a31c7dfc17bNick Cheng { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 }, 6987ec4ad0125db0222e397508c190b01c8f2b5f7cdSrinivas { PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 }, 699463b8977ecebf8cf590c33191d43ea0b059381c6HighPoint Linux Team { PCI_VDEVICE(TTI, 0x2710), chip_9480 }, 700463b8977ecebf8cf590c33191d43ea0b059381c6HighPoint Linux Team { PCI_VDEVICE(TTI, 0x2720), chip_9480 }, 701463b8977ecebf8cf590c33191d43ea0b059381c6HighPoint Linux Team { PCI_VDEVICE(TTI, 0x2721), chip_9480 }, 702463b8977ecebf8cf590c33191d43ea0b059381c6HighPoint Linux Team { PCI_VDEVICE(TTI, 0x2722), chip_9480 }, 703463b8977ecebf8cf590c33191d43ea0b059381c6HighPoint Linux Team { PCI_VDEVICE(TTI, 0x2740), chip_9480 }, 704463b8977ecebf8cf590c33191d43ea0b059381c6HighPoint Linux Team { PCI_VDEVICE(TTI, 0x2744), chip_9480 }, 705463b8977ecebf8cf590c33191d43ea0b059381c6HighPoint Linux Team { PCI_VDEVICE(TTI, 0x2760), chip_9480 }, 7068214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu { 7078214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .vendor = 0x1b4b, 708f7e45b6a09fad88b4d1e87d55c26e79578c5fa18Xiangliang Yu .device = 0x9480, 709f7e45b6a09fad88b4d1e87d55c26e79578c5fa18Xiangliang Yu .subvendor = PCI_ANY_ID, 710f7e45b6a09fad88b4d1e87d55c26e79578c5fa18Xiangliang Yu .subdevice = 0x9480, 711f7e45b6a09fad88b4d1e87d55c26e79578c5fa18Xiangliang Yu .class = 0, 712f7e45b6a09fad88b4d1e87d55c26e79578c5fa18Xiangliang Yu .class_mask = 0, 713f7e45b6a09fad88b4d1e87d55c26e79578c5fa18Xiangliang Yu .driver_data = chip_9480, 714f7e45b6a09fad88b4d1e87d55c26e79578c5fa18Xiangliang Yu }, 715f7e45b6a09fad88b4d1e87d55c26e79578c5fa18Xiangliang Yu { 716f7e45b6a09fad88b4d1e87d55c26e79578c5fa18Xiangliang Yu .vendor = 0x1b4b, 7178214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .device = 0x9445, 7188214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .subvendor = PCI_ANY_ID, 7198214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .subdevice = 0x9480, 7208214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .class = 0, 7218214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .class_mask = 0, 7228214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .driver_data = chip_9445, 7238214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu }, 7248214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu { 7258214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .vendor = 0x1b4b, 7268214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .device = 0x9485, 7278214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .subvendor = PCI_ANY_ID, 7288214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .subdevice = 0x9480, 7298214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .class = 0, 7308214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .class_mask = 0, 7318214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu .driver_data = chip_9485, 7328214028344b4a38aabf73d95347e1e35538c75f6Xiangliang Yu }, 73399a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1021), chip_9485}, /* OCZ RevoDrive3 */ 73499a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1022), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ 73599a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1040), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ 73699a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1041), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ 73799a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1042), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ 73899a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1043), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ 73999a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1044), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ 74099a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1080), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ 74199a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1083), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ 74299a700bcc75429ba84a672d04f0b650dcc5b3042Robin H. Johnson { PCI_VDEVICE(OCZ, 0x1084), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ 743dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 744dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik { } /* terminate list */ 745dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik}; 746dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 747dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic struct pci_driver mvs_pci_driver = { 748dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .name = DRV_NAME, 749dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .id_table = mvs_pci_table, 750dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .probe = mvs_pci_init, 751dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik .remove = __devexit_p(mvs_pci_remove), 752dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik}; 753dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 75483c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yustatic ssize_t 75583c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yumvs_show_driver_version(struct device *cdev, 75683c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu struct device_attribute *attr, char *buffer) 75783c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu{ 75883c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu return snprintf(buffer, PAGE_SIZE, "%s\n", DRV_VERSION); 75983c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu} 76083c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 76183c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yustatic DEVICE_ATTR(driver_version, 76283c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu S_IRUGO, 76383c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu mvs_show_driver_version, 76483c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu NULL); 76583c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 76683c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yustatic ssize_t 76783c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yumvs_store_interrupt_coalescing(struct device *cdev, 76883c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu struct device_attribute *attr, 76983c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu const char *buffer, size_t size) 77083c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu{ 77183c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu int val = 0; 77283c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu struct mvs_info *mvi = NULL; 77383c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu struct Scsi_Host *shost = class_to_shost(cdev); 77483c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 77583c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu u8 i, core_nr; 77683c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu if (buffer == NULL) 77783c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu return size; 77883c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 77983c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu if (sscanf(buffer, "%d", &val) != 1) 78083c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu return -EINVAL; 78183c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 78283c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu if (val >= 0x10000) { 78383c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu mv_dprintk("interrupt coalescing timer %d us is" 78483c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu "too long\n", val); 78583c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu return strlen(buffer); 78683c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu } 78783c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 78883c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu interrupt_coalescing = val; 78983c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 79083c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; 79183c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; 79283c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 79383c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu if (unlikely(!mvi)) 79483c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu return -EINVAL; 79583c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 79683c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu for (i = 0; i < core_nr; i++) { 79783c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; 79883c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu if (MVS_CHIP_DISP->tune_interrupt) 79983c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu MVS_CHIP_DISP->tune_interrupt(mvi, 80083c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu interrupt_coalescing); 80183c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu } 80283c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu mv_dprintk("set interrupt coalescing time to %d us\n", 80383c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu interrupt_coalescing); 80483c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu return strlen(buffer); 80583c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu} 80683c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 80783c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yustatic ssize_t mvs_show_interrupt_coalescing(struct device *cdev, 80883c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu struct device_attribute *attr, char *buffer) 80983c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu{ 81083c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu return snprintf(buffer, PAGE_SIZE, "%d\n", interrupt_coalescing); 81183c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu} 81283c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 81383c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yustatic DEVICE_ATTR(interrupt_coalescing, 81483c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu S_IRUGO|S_IWUSR, 81583c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu mvs_show_interrupt_coalescing, 81683c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu mvs_store_interrupt_coalescing); 81783c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 81820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan/* task handler */ 81920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstruct task_struct *mvs_th; 820dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic int __init mvs_init(void) 821dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 822dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik int rc; 823dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_stt = sas_domain_attach_transport(&mvs_transport_ops); 824dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!mvs_stt) 825dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return -ENOMEM; 826dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 8270b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu mvs_task_list_cache = kmem_cache_create("mvs_task_list", sizeof(struct mvs_task_list), 8280b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu 0, SLAB_HWCACHE_ALIGN, NULL); 8290b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu if (!mvs_task_list_cache) { 8300b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu rc = -ENOMEM; 8310b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu mv_printk("%s: mvs_task_list_cache alloc failed! \n", __func__); 8320b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu goto err_out; 8330b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu } 8340b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu 835dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = pci_register_driver(&mvs_pci_driver); 83620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 837dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) 838dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 839dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 840dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 0; 841dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 842dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikerr_out: 843dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_release_transport(mvs_stt); 844dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return rc; 845dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 846dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 847dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic void __exit mvs_exit(void) 848dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 849dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik pci_unregister_driver(&mvs_pci_driver); 850dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_release_transport(mvs_stt); 8510b15fb1fdfd403726542cb6111bc916b7a9f7fadXiangliang Yu kmem_cache_destroy(mvs_task_list_cache); 852dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 853dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 85483c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yustruct device_attribute *mvst_host_attrs[] = { 85583c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu &dev_attr_driver_version, 85683c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu &dev_attr_interrupt_coalescing, 85783c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu NULL, 85883c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu}; 85983c7b61cf49c2659829050fec240601415c7f9d9Xiangliang Yu 860dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikmodule_init(mvs_init); 861dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikmodule_exit(mvs_exit); 862dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 863dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff GarzikMODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>"); 864dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff GarzikMODULE_DESCRIPTION("Marvell 88SE6440 SAS/SATA controller driver"); 865dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff GarzikMODULE_VERSION(DRV_VERSION); 866dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff GarzikMODULE_LICENSE("GPL"); 86720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#ifdef CONFIG_PCI 868dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff GarzikMODULE_DEVICE_TABLE(pci, mvs_pci_table); 86920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#endif 870