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