Blame view

drivers/scsi/mvsas/mv_init.c 22.4 KB
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
1
  /*
20b09c299   Andy Yan   [SCSI] mvsas: add...
2
3
4
5
   * Marvell 88SE64xx/88SE94xx pci init
   *
   * Copyright 2007 Red Hat, Inc.
   * Copyright 2008 Marvell. <kewei@marvell.com>
0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
6
   * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
20b09c299   Andy Yan   [SCSI] mvsas: add...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   *
   * This file is licensed under GPLv2.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation; version 2 of the
   * License.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   * USA
  */
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
25

dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
26
27
  
  #include "mv_sas.h"
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
28

0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
29
30
31
32
33
34
35
36
37
38
39
40
  static int lldd_max_execute_num = 1;
  module_param_named(collector, lldd_max_execute_num, int, S_IRUGO);
  MODULE_PARM_DESC(collector, "
  "
  	"\tIf greater than one, tells the SAS Layer to run in Task Collector
  "
  	"\tMode.  If 1 or 0, tells the SAS Layer to run in Direct Mode.
  "
  	"\tThe mvsas SAS LLDD supports both modes.
  "
  	"\tDefault: 1 (Direct Mode).
  ");
83c7b61cf   Xiangliang Yu   [SCSI] mvsas: Add...
41
  int interrupt_coalescing = 0x80;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
42
  static struct scsi_transport_template *mvs_stt;
0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
43
  struct kmem_cache *mvs_task_list_cache;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
44
  static const struct mvs_chip_info mvs_chips[] = {
a4632aae8   Xiangliang Yu   [SCSI] mvsas: Add...
45
46
47
48
49
50
51
52
53
  	[chip_6320] =	{ 1, 2, 0x400, 17, 16, 6,  9, &mvs_64xx_dispatch, },
  	[chip_6440] =	{ 1, 4, 0x400, 17, 16, 6,  9, &mvs_64xx_dispatch, },
  	[chip_6485] =	{ 1, 8, 0x800, 33, 32, 6, 10, &mvs_64xx_dispatch, },
  	[chip_9180] =	{ 2, 4, 0x800, 17, 64, 8,  9, &mvs_94xx_dispatch, },
  	[chip_9480] =	{ 2, 4, 0x800, 17, 64, 8,  9, &mvs_94xx_dispatch, },
  	[chip_9445] =	{ 1, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
  	[chip_9485] =	{ 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
  	[chip_1300] =	{ 1, 4, 0x400, 17, 16, 6,  9, &mvs_64xx_dispatch, },
  	[chip_1320] =	{ 2, 4, 0x800, 17, 64, 8,  9, &mvs_94xx_dispatch, },
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
54
  };
83c7b61cf   Xiangliang Yu   [SCSI] mvsas: Add...
55
  struct device_attribute *mvst_host_attrs[];
20b09c299   Andy Yan   [SCSI] mvsas: add...
56
  #define SOC_SAS_NUM 2
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
57
58
59
60
61
  static struct scsi_host_template mvs_sht = {
  	.module			= THIS_MODULE,
  	.name			= DRV_NAME,
  	.queuecommand		= sas_queuecommand,
  	.target_alloc		= sas_target_alloc,
e211e2c7b   Dan Williams   [SCSI] mvsas: rem...
62
  	.slave_configure	= sas_slave_configure,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
63
64
65
66
67
68
69
70
71
  	.slave_destroy		= sas_slave_destroy,
  	.scan_finished		= mvs_scan_finished,
  	.scan_start		= mvs_scan_start,
  	.change_queue_depth	= sas_change_queue_depth,
  	.change_queue_type	= sas_change_queue_type,
  	.bios_param		= sas_bios_param,
  	.can_queue		= 1,
  	.cmd_per_lun		= 1,
  	.this_id		= -1,
b89e8f539   Xiangliang Yu   [SCSI] mvsas: Rem...
72
  	.sg_tablesize		= SG_ALL,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
73
74
  	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
  	.use_clustering		= ENABLE_CLUSTERING,
9dc9fd948   Srinivas   [SCSI] mvsas: fix...
75
  	.eh_device_reset_handler = sas_eh_device_reset_handler,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
76
  	.eh_bus_reset_handler	= sas_eh_bus_reset_handler,
e211e2c7b   Dan Williams   [SCSI] mvsas: rem...
77
  	.slave_alloc		= sas_slave_alloc,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
78
79
  	.target_destroy		= sas_target_destroy,
  	.ioctl			= sas_ioctl,
83c7b61cf   Xiangliang Yu   [SCSI] mvsas: Add...
80
  	.shost_attrs		= mvst_host_attrs,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
81
82
83
  };
  
  static struct sas_domain_function_template mvs_transport_ops = {
20b09c299   Andy Yan   [SCSI] mvsas: add...
84
  	.lldd_dev_found 	= mvs_dev_found,
9dc9fd948   Srinivas   [SCSI] mvsas: fix...
85
  	.lldd_dev_gone		= mvs_dev_gone,
20b09c299   Andy Yan   [SCSI] mvsas: add...
86
  	.lldd_execute_task	= mvs_queue_command,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
87
  	.lldd_control_phy	= mvs_phy_control,
20b09c299   Andy Yan   [SCSI] mvsas: add...
88
89
90
91
  
  	.lldd_abort_task	= mvs_abort_task,
  	.lldd_abort_task_set    = mvs_abort_task_set,
  	.lldd_clear_aca         = mvs_clear_aca,
9dc9fd948   Srinivas   [SCSI] mvsas: fix...
92
  	.lldd_clear_task_set    = mvs_clear_task_set,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
93
  	.lldd_I_T_nexus_reset	= mvs_I_T_nexus_reset,
20b09c299   Andy Yan   [SCSI] mvsas: add...
94
95
  	.lldd_lu_reset 		= mvs_lu_reset,
  	.lldd_query_task	= mvs_query_task,
20b09c299   Andy Yan   [SCSI] mvsas: add...
96
97
  	.lldd_port_formed	= mvs_port_formed,
  	.lldd_port_deformed     = mvs_port_deformed,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
98
99
100
101
102
103
  };
  
  static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
  {
  	struct mvs_phy *phy = &mvi->phy[phy_id];
  	struct asd_sas_phy *sas_phy = &phy->sas_phy;
20b09c299   Andy Yan   [SCSI] mvsas: add...
104
  	phy->mvi = mvi;
84fbd0cea   Xiangliang Yu   [SCSI] mvsas: mis...
105
  	phy->port = NULL;
20b09c299   Andy Yan   [SCSI] mvsas: add...
106
  	init_timer(&phy->timer);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
107
108
109
110
111
112
113
114
115
116
117
118
  	sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0;
  	sas_phy->class = SAS;
  	sas_phy->iproto = SAS_PROTOCOL_ALL;
  	sas_phy->tproto = 0;
  	sas_phy->type = PHY_TYPE_PHYSICAL;
  	sas_phy->role = PHY_ROLE_INITIATOR;
  	sas_phy->oob_mode = OOB_NOT_CONNECTED;
  	sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
  
  	sas_phy->id = phy_id;
  	sas_phy->sas_addr = &mvi->sas_addr[0];
  	sas_phy->frame_rcvd = &phy->frame_rcvd[0];
20b09c299   Andy Yan   [SCSI] mvsas: add...
119
  	sas_phy->ha = (struct sas_ha_struct *)mvi->shost->hostdata;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
120
121
122
123
124
  	sas_phy->lldd_phy = phy;
  }
  
  static void mvs_free(struct mvs_info *mvi)
  {
20b09c299   Andy Yan   [SCSI] mvsas: add...
125
126
  	struct mvs_wq *mwq;
  	int slot_nr;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
127
128
129
  
  	if (!mvi)
  		return;
20b09c299   Andy Yan   [SCSI] mvsas: add...
130
131
132
  	if (mvi->flags & MVF_FLAG_SOC)
  		slot_nr = MVS_SOC_SLOTS;
  	else
b89e8f539   Xiangliang Yu   [SCSI] mvsas: Rem...
133
  		slot_nr = MVS_CHIP_SLOT_SZ;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
134

0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
135
136
  	if (mvi->dma_pool)
  		pci_pool_destroy(mvi->dma_pool);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
137
138
  
  	if (mvi->tx)
20b09c299   Andy Yan   [SCSI] mvsas: add...
139
  		dma_free_coherent(mvi->dev,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
140
141
142
  				  sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ,
  				  mvi->tx, mvi->tx_dma);
  	if (mvi->rx_fis)
20b09c299   Andy Yan   [SCSI] mvsas: add...
143
  		dma_free_coherent(mvi->dev, MVS_RX_FISL_SZ,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
144
145
  				  mvi->rx_fis, mvi->rx_fis_dma);
  	if (mvi->rx)
20b09c299   Andy Yan   [SCSI] mvsas: add...
146
  		dma_free_coherent(mvi->dev,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
147
148
149
  				  sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1),
  				  mvi->rx, mvi->rx_dma);
  	if (mvi->slot)
20b09c299   Andy Yan   [SCSI] mvsas: add...
150
151
  		dma_free_coherent(mvi->dev,
  				  sizeof(*mvi->slot) * slot_nr,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
152
  				  mvi->slot, mvi->slot_dma);
8882f0813   Xiangliang Yu   [SCSI] mvsas: fix...
153

20b09c299   Andy Yan   [SCSI] mvsas: add...
154
155
156
  	if (mvi->bulk_buffer)
  		dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE,
  				  mvi->bulk_buffer, mvi->bulk_buffer_dma);
8882f0813   Xiangliang Yu   [SCSI] mvsas: fix...
157
158
159
  	if (mvi->bulk_buffer1)
  		dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE,
  				  mvi->bulk_buffer1, mvi->bulk_buffer_dma1);
20b09c299   Andy Yan   [SCSI] mvsas: add...
160
161
  
  	MVS_CHIP_DISP->chip_iounmap(mvi);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
162
163
  	if (mvi->shost)
  		scsi_host_put(mvi->shost);
20b09c299   Andy Yan   [SCSI] mvsas: add...
164
165
  	list_for_each_entry(mwq, &mvi->wq_list, entry)
  		cancel_delayed_work(&mwq->work_q);
b89e8f539   Xiangliang Yu   [SCSI] mvsas: Rem...
166
  	kfree(mvi->tags);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
167
168
  	kfree(mvi);
  }
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
169
  #ifdef CONFIG_SCSI_MVSAS_TASKLET
20b09c299   Andy Yan   [SCSI] mvsas: add...
170
  static void mvs_tasklet(unsigned long opaque)
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
171
  {
20b09c299   Andy Yan   [SCSI] mvsas: add...
172
173
  	u32 stat;
  	u16 core_nr, i = 0;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
174

20b09c299   Andy Yan   [SCSI] mvsas: add...
175
176
177
178
179
180
181
182
  	struct mvs_info *mvi;
  	struct sas_ha_struct *sha = (struct sas_ha_struct *)opaque;
  
  	core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
  	mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
  
  	if (unlikely(!mvi))
  		BUG_ON(1);
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
183
184
185
  	stat = MVS_CHIP_DISP->isr_status(mvi, mvi->pdev->irq);
  	if (!stat)
  		goto out;
20b09c299   Andy Yan   [SCSI] mvsas: add...
186
187
  	for (i = 0; i < core_nr; i++) {
  		mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
188
  		MVS_CHIP_DISP->isr(mvi, mvi->pdev->irq, stat);
20b09c299   Andy Yan   [SCSI] mvsas: add...
189
  	}
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
190
191
  out:
  	MVS_CHIP_DISP->interrupt_enable(mvi);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
192

dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
193
194
195
196
197
  }
  #endif
  
  static irqreturn_t mvs_interrupt(int irq, void *opaque)
  {
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
198
  	u32 core_nr;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
199
  	u32 stat;
20b09c299   Andy Yan   [SCSI] mvsas: add...
200
201
  	struct mvs_info *mvi;
  	struct sas_ha_struct *sha = opaque;
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
202
203
204
  #ifndef CONFIG_SCSI_MVSAS_TASKLET
  	u32 i;
  #endif
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
205

20b09c299   Andy Yan   [SCSI] mvsas: add...
206
207
  	core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
  	mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
208

20b09c299   Andy Yan   [SCSI] mvsas: add...
209
  	if (unlikely(!mvi))
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
210
  		return IRQ_NONE;
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
211
212
213
  #ifdef CONFIG_SCSI_MVSAS_TASKLET
  	MVS_CHIP_DISP->interrupt_disable(mvi);
  #endif
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
214

20b09c299   Andy Yan   [SCSI] mvsas: add...
215
  	stat = MVS_CHIP_DISP->isr_status(mvi, irq);
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
216
217
218
219
  	if (!stat) {
  	#ifdef CONFIG_SCSI_MVSAS_TASKLET
  		MVS_CHIP_DISP->interrupt_enable(mvi);
  	#endif
20b09c299   Andy Yan   [SCSI] mvsas: add...
220
  		return IRQ_NONE;
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
221
  	}
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
222

6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
223
224
  #ifdef CONFIG_SCSI_MVSAS_TASKLET
  	tasklet_schedule(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
225
  #else
20b09c299   Andy Yan   [SCSI] mvsas: add...
226
227
228
229
  	for (i = 0; i < core_nr; i++) {
  		mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
  		MVS_CHIP_DISP->isr(mvi, irq, stat);
  	}
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
230
231
232
  #endif
  	return IRQ_HANDLED;
  }
20b09c299   Andy Yan   [SCSI] mvsas: add...
233
  static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
234
  {
9dc9fd948   Srinivas   [SCSI] mvsas: fix...
235
  	int i = 0, slot_nr;
0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
236
  	char pool_name[32];
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
237

20b09c299   Andy Yan   [SCSI] mvsas: add...
238
239
240
  	if (mvi->flags & MVF_FLAG_SOC)
  		slot_nr = MVS_SOC_SLOTS;
  	else
b89e8f539   Xiangliang Yu   [SCSI] mvsas: Rem...
241
  		slot_nr = MVS_CHIP_SLOT_SZ;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
242
243
  
  	spin_lock_init(&mvi->lock);
20b09c299   Andy Yan   [SCSI] mvsas: add...
244
  	for (i = 0; i < mvi->chip->n_phy; i++) {
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
245
  		mvs_phy_init(mvi, i);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
246
247
248
249
  		mvi->port[i].wide_port_phymap = 0;
  		mvi->port[i].port_attached = 0;
  		INIT_LIST_HEAD(&mvi->port[i].list);
  	}
20b09c299   Andy Yan   [SCSI] mvsas: add...
250
251
252
253
254
  	for (i = 0; i < MVS_MAX_DEVICES; i++) {
  		mvi->devices[i].taskfileset = MVS_ID_NOT_MAPPED;
  		mvi->devices[i].dev_type = NO_DEVICE;
  		mvi->devices[i].device_id = i;
  		mvi->devices[i].dev_status = MVS_DEV_NORMAL;
9dc9fd948   Srinivas   [SCSI] mvsas: fix...
255
  		init_timer(&mvi->devices[i].timer);
20b09c299   Andy Yan   [SCSI] mvsas: add...
256
  	}
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
257
258
259
260
  
  	/*
  	 * alloc and init our DMA areas
  	 */
20b09c299   Andy Yan   [SCSI] mvsas: add...
261
  	mvi->tx = dma_alloc_coherent(mvi->dev,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
262
263
264
265
266
  				     sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ,
  				     &mvi->tx_dma, GFP_KERNEL);
  	if (!mvi->tx)
  		goto err_out;
  	memset(mvi->tx, 0, sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ);
20b09c299   Andy Yan   [SCSI] mvsas: add...
267
  	mvi->rx_fis = dma_alloc_coherent(mvi->dev, MVS_RX_FISL_SZ,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
268
269
270
271
  					 &mvi->rx_fis_dma, GFP_KERNEL);
  	if (!mvi->rx_fis)
  		goto err_out;
  	memset(mvi->rx_fis, 0, MVS_RX_FISL_SZ);
20b09c299   Andy Yan   [SCSI] mvsas: add...
272
  	mvi->rx = dma_alloc_coherent(mvi->dev,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
273
274
275
276
277
  				     sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1),
  				     &mvi->rx_dma, GFP_KERNEL);
  	if (!mvi->rx)
  		goto err_out;
  	memset(mvi->rx, 0, sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1));
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
278
279
  	mvi->rx[0] = cpu_to_le32(0xfff);
  	mvi->rx_cons = 0xfff;
20b09c299   Andy Yan   [SCSI] mvsas: add...
280
281
  	mvi->slot = dma_alloc_coherent(mvi->dev,
  				       sizeof(*mvi->slot) * slot_nr,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
282
283
284
  				       &mvi->slot_dma, GFP_KERNEL);
  	if (!mvi->slot)
  		goto err_out;
20b09c299   Andy Yan   [SCSI] mvsas: add...
285
  	memset(mvi->slot, 0, sizeof(*mvi->slot) * slot_nr);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
286

20b09c299   Andy Yan   [SCSI] mvsas: add...
287
288
289
290
291
  	mvi->bulk_buffer = dma_alloc_coherent(mvi->dev,
  				       TRASH_BUCKET_SIZE,
  				       &mvi->bulk_buffer_dma, GFP_KERNEL);
  	if (!mvi->bulk_buffer)
  		goto err_out;
8882f0813   Xiangliang Yu   [SCSI] mvsas: fix...
292
293
294
295
296
297
  
  	mvi->bulk_buffer1 = dma_alloc_coherent(mvi->dev,
  				       TRASH_BUCKET_SIZE,
  				       &mvi->bulk_buffer_dma1, GFP_KERNEL);
  	if (!mvi->bulk_buffer1)
  		goto err_out;
0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
298
299
300
301
302
  	sprintf(pool_name, "%s%d", "mvs_dma_pool", mvi->id);
  	mvi->dma_pool = pci_pool_create(pool_name, mvi->pdev, MVS_SLOT_BUF_SZ, 16, 0);
  	if (!mvi->dma_pool) {
  			printk(KERN_DEBUG "failed to create dma pool %s.
  ", pool_name);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
303
  			goto err_out;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
304
  	}
0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
305
  	mvi->tags_num = slot_nr;
20b09c299   Andy Yan   [SCSI] mvsas: add...
306
307
308
309
310
311
  	/* Initialize tags */
  	mvs_tag_init(mvi);
  	return 0;
  err_out:
  	return 1;
  }
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
312

20b09c299   Andy Yan   [SCSI] mvsas: add...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex)
  {
  	unsigned long res_start, res_len, res_flag, res_flag_ex = 0;
  	struct pci_dev *pdev = mvi->pdev;
  	if (bar_ex != -1) {
  		/*
  		 * ioremap main and peripheral registers
  		 */
  		res_start = pci_resource_start(pdev, bar_ex);
  		res_len = pci_resource_len(pdev, bar_ex);
  		if (!res_start || !res_len)
  			goto err_out;
  
  		res_flag_ex = pci_resource_flags(pdev, bar_ex);
  		if (res_flag_ex & IORESOURCE_MEM) {
  			if (res_flag_ex & IORESOURCE_CACHEABLE)
  				mvi->regs_ex = ioremap(res_start, res_len);
  			else
  				mvi->regs_ex = ioremap_nocache(res_start,
  						res_len);
  		} else
  			mvi->regs_ex = (void *)res_start;
  		if (!mvi->regs_ex)
  			goto err_out;
  	}
  
  	res_start = pci_resource_start(pdev, bar);
  	res_len = pci_resource_len(pdev, bar);
  	if (!res_start || !res_len)
  		goto err_out;
  
  	res_flag = pci_resource_flags(pdev, bar);
  	if (res_flag & IORESOURCE_CACHEABLE)
  		mvi->regs = ioremap(res_start, res_len);
  	else
  		mvi->regs = ioremap_nocache(res_start, res_len);
  
  	if (!mvi->regs) {
  		if (mvi->regs_ex && (res_flag_ex & IORESOURCE_MEM))
  			iounmap(mvi->regs_ex);
  		mvi->regs_ex = NULL;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
354
  		goto err_out;
20b09c299   Andy Yan   [SCSI] mvsas: add...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
  	}
  
  	return 0;
  err_out:
  	return -1;
  }
  
  void mvs_iounmap(void __iomem *regs)
  {
  	iounmap(regs);
  }
  
  static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
  				const struct pci_device_id *ent,
  				struct Scsi_Host *shost, unsigned int id)
  {
84fbd0cea   Xiangliang Yu   [SCSI] mvsas: mis...
371
  	struct mvs_info *mvi = NULL;
20b09c299   Andy Yan   [SCSI] mvsas: add...
372
  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
b89e8f539   Xiangliang Yu   [SCSI] mvsas: Rem...
373
374
375
  	mvi = kzalloc(sizeof(*mvi) +
  		(1L << mvs_chips[ent->driver_data].slot_width) *
  		sizeof(struct mvs_slot_info), GFP_KERNEL);
20b09c299   Andy Yan   [SCSI] mvsas: add...
376
377
  	if (!mvi)
  		return NULL;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
378

20b09c299   Andy Yan   [SCSI] mvsas: add...
379
380
381
382
383
  	mvi->pdev = pdev;
  	mvi->dev = &pdev->dev;
  	mvi->chip_id = ent->driver_data;
  	mvi->chip = &mvs_chips[mvi->chip_id];
  	INIT_LIST_HEAD(&mvi->wq_list);
20b09c299   Andy Yan   [SCSI] mvsas: add...
384
385
386
387
388
389
390
  
  	((struct mvs_prv_info *)sha->lldd_ha)->mvi[id] = mvi;
  	((struct mvs_prv_info *)sha->lldd_ha)->n_phy = mvi->chip->n_phy;
  
  	mvi->id = id;
  	mvi->sas = sha;
  	mvi->shost = shost;
20b09c299   Andy Yan   [SCSI] mvsas: add...
391

b89e8f539   Xiangliang Yu   [SCSI] mvsas: Rem...
392
393
394
  	mvi->tags = kzalloc(MVS_CHIP_SLOT_SZ>>3, GFP_KERNEL);
  	if (!mvi->tags)
  		goto err_out;
20b09c299   Andy Yan   [SCSI] mvsas: add...
395
396
397
398
  	if (MVS_CHIP_DISP->chip_ioremap(mvi))
  		goto err_out;
  	if (!mvs_alloc(mvi, shost))
  		return mvi;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
399
400
401
402
  err_out:
  	mvs_free(mvi);
  	return NULL;
  }
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
  static int pci_go_64(struct pci_dev *pdev)
  {
  	int rc;
  
  	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
  		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
  		if (rc) {
  			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
  			if (rc) {
  				dev_printk(KERN_ERR, &pdev->dev,
  					   "64-bit DMA enable failed
  ");
  				return rc;
  			}
  		}
  	} else {
  		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
  		if (rc) {
  			dev_printk(KERN_ERR, &pdev->dev,
  				   "32-bit DMA enable failed
  ");
  			return rc;
  		}
  		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
  		if (rc) {
  			dev_printk(KERN_ERR, &pdev->dev,
  				   "32-bit consistent DMA enable failed
  ");
  			return rc;
  		}
  	}
  
  	return rc;
  }
20b09c299   Andy Yan   [SCSI] mvsas: add...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
  				const struct mvs_chip_info *chip_info)
  {
  	int phy_nr, port_nr; unsigned short core_nr;
  	struct asd_sas_phy **arr_phy;
  	struct asd_sas_port **arr_port;
  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
  
  	core_nr = chip_info->n_host;
  	phy_nr  = core_nr * chip_info->n_phy;
  	port_nr = phy_nr;
  
  	memset(sha, 0x00, sizeof(struct sas_ha_struct));
  	arr_phy  = kcalloc(phy_nr, sizeof(void *), GFP_KERNEL);
  	arr_port = kcalloc(port_nr, sizeof(void *), GFP_KERNEL);
  	if (!arr_phy || !arr_port)
  		goto exit_free;
  
  	sha->sas_phy = arr_phy;
  	sha->sas_port = arr_port;
9dc9fd948   Srinivas   [SCSI] mvsas: fix...
457
  	sha->core.shost = shost;
20b09c299   Andy Yan   [SCSI] mvsas: add...
458
459
460
461
462
463
464
465
  
  	sha->lldd_ha = kzalloc(sizeof(struct mvs_prv_info), GFP_KERNEL);
  	if (!sha->lldd_ha)
  		goto exit_free;
  
  	((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr;
  
  	shost->transportt = mvs_stt;
a4632aae8   Xiangliang Yu   [SCSI] mvsas: Add...
466
  	shost->max_id = MVS_MAX_DEVICES;
20b09c299   Andy Yan   [SCSI] mvsas: add...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
  	shost->max_lun = ~0;
  	shost->max_channel = 1;
  	shost->max_cmd_len = 16;
  
  	return 0;
  exit_free:
  	kfree(arr_phy);
  	kfree(arr_port);
  	return -1;
  
  }
  
  static void  __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
  			const struct mvs_chip_info *chip_info)
  {
  	int can_queue, i = 0, j = 0;
  	struct mvs_info *mvi = NULL;
  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
  	unsigned short nr_core = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
  
  	for (j = 0; j < nr_core; j++) {
  		mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j];
  		for (i = 0; i < chip_info->n_phy; i++) {
  			sha->sas_phy[j * chip_info->n_phy  + i] =
  				&mvi->phy[i].sas_phy;
  			sha->sas_port[j * chip_info->n_phy + i] =
  				&mvi->port[i].sas_port;
  		}
  	}
  
  	sha->sas_ha_name = DRV_NAME;
  	sha->dev = mvi->dev;
  	sha->lldd_module = THIS_MODULE;
  	sha->sas_addr = &mvi->sas_addr[0];
  
  	sha->num_phys = nr_core * chip_info->n_phy;
0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
503
  	sha->lldd_max_execute_num = lldd_max_execute_num;
20b09c299   Andy Yan   [SCSI] mvsas: add...
504
505
506
507
  
  	if (mvi->flags & MVF_FLAG_SOC)
  		can_queue = MVS_SOC_CAN_QUEUE;
  	else
b89e8f539   Xiangliang Yu   [SCSI] mvsas: Rem...
508
  		can_queue = MVS_CHIP_SLOT_SZ;
20b09c299   Andy Yan   [SCSI] mvsas: add...
509
510
  
  	sha->lldd_queue_size = can_queue;
a4632aae8   Xiangliang Yu   [SCSI] mvsas: Add...
511
  	shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG);
20b09c299   Andy Yan   [SCSI] mvsas: add...
512
  	shost->can_queue = can_queue;
b89e8f539   Xiangliang Yu   [SCSI] mvsas: Rem...
513
  	mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
20b09c299   Andy Yan   [SCSI] mvsas: add...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
  	sha->core.shost = mvi->shost;
  }
  
  static void mvs_init_sas_add(struct mvs_info *mvi)
  {
  	u8 i;
  	for (i = 0; i < mvi->chip->n_phy; i++) {
  		mvi->phy[i].dev_sas_addr = 0x5005043011ab0000ULL;
  		mvi->phy[i].dev_sas_addr =
  			cpu_to_be64((u64)(*(u64 *)&mvi->phy[i].dev_sas_addr));
  	}
  
  	memcpy(mvi->sas_addr, &mvi->phy[0].dev_sas_addr, SAS_ADDR_SIZE);
  }
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
528
529
530
  static int __devinit mvs_pci_init(struct pci_dev *pdev,
  				  const struct pci_device_id *ent)
  {
20b09c299   Andy Yan   [SCSI] mvsas: add...
531
  	unsigned int rc, nhost = 0;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
532
  	struct mvs_info *mvi;
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
533
  	struct mvs_prv_info *mpi;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
534
  	irq_handler_t irq_handler = mvs_interrupt;
20b09c299   Andy Yan   [SCSI] mvsas: add...
535
536
  	struct Scsi_Host *shost = NULL;
  	const struct mvs_chip_info *chip;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
537

20b09c299   Andy Yan   [SCSI] mvsas: add...
538
539
540
  	dev_printk(KERN_INFO, &pdev->dev,
  		"mvsas: driver version %s
  ", DRV_VERSION);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
541
542
  	rc = pci_enable_device(pdev);
  	if (rc)
20b09c299   Andy Yan   [SCSI] mvsas: add...
543
  		goto err_out_enable;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
544
545
546
547
548
549
550
551
552
553
  
  	pci_set_master(pdev);
  
  	rc = pci_request_regions(pdev, DRV_NAME);
  	if (rc)
  		goto err_out_disable;
  
  	rc = pci_go_64(pdev);
  	if (rc)
  		goto err_out_regions;
20b09c299   Andy Yan   [SCSI] mvsas: add...
554
555
  	shost = scsi_host_alloc(&mvs_sht, sizeof(void *));
  	if (!shost) {
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
556
557
558
  		rc = -ENOMEM;
  		goto err_out_regions;
  	}
20b09c299   Andy Yan   [SCSI] mvsas: add...
559
560
561
562
563
564
565
  	chip = &mvs_chips[ent->driver_data];
  	SHOST_TO_SAS_HA(shost) =
  		kcalloc(1, sizeof(struct sas_ha_struct), GFP_KERNEL);
  	if (!SHOST_TO_SAS_HA(shost)) {
  		kfree(shost);
  		rc = -ENOMEM;
  		goto err_out_regions;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
566
  	}
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
567

20b09c299   Andy Yan   [SCSI] mvsas: add...
568
569
570
571
572
573
  	rc = mvs_prep_sas_ha_init(shost, chip);
  	if (rc) {
  		kfree(shost);
  		rc = -ENOMEM;
  		goto err_out_regions;
  	}
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
574

20b09c299   Andy Yan   [SCSI] mvsas: add...
575
  	pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost));
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
576

20b09c299   Andy Yan   [SCSI] mvsas: add...
577
578
579
580
581
582
  	do {
  		mvi = mvs_pci_alloc(pdev, ent, shost, nhost);
  		if (!mvi) {
  			rc = -ENOMEM;
  			goto err_out_regions;
  		}
f1f82a919   Xiangliang Yu   [SCSI] mvsas: add...
583
584
  		memset(&mvi->hba_info_param, 0xFF,
  			sizeof(struct hba_info_page));
20b09c299   Andy Yan   [SCSI] mvsas: add...
585
586
587
588
589
590
591
592
593
594
  		mvs_init_sas_add(mvi);
  
  		mvi->instance = nhost;
  		rc = MVS_CHIP_DISP->chip_init(mvi);
  		if (rc) {
  			mvs_free(mvi);
  			goto err_out_regions;
  		}
  		nhost++;
  	} while (nhost < chip->n_host);
6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
595
596
597
  	mpi = (struct mvs_prv_info *)(SHOST_TO_SAS_HA(shost)->lldd_ha);
  #ifdef CONFIG_SCSI_MVSAS_TASKLET
  	tasklet_init(&(mpi->mv_tasklet), mvs_tasklet,
9dc9fd948   Srinivas   [SCSI] mvsas: fix...
598
599
  		     (unsigned long)SHOST_TO_SAS_HA(shost));
  #endif
20b09c299   Andy Yan   [SCSI] mvsas: add...
600
601
602
603
  
  	mvs_post_sas_ha_init(shost, chip);
  
  	rc = scsi_add_host(shost, &pdev->dev);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
604
605
  	if (rc)
  		goto err_out_shost;
20b09c299   Andy Yan   [SCSI] mvsas: add...
606
607
608
609
610
611
612
  	rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
  	if (rc)
  		goto err_out_shost;
  	rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED,
  		DRV_NAME, SHOST_TO_SAS_HA(shost));
  	if (rc)
  		goto err_not_sas;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
613

20b09c299   Andy Yan   [SCSI] mvsas: add...
614
  	MVS_CHIP_DISP->interrupt_enable(mvi);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
615
616
617
618
  
  	scsi_scan_host(mvi->shost);
  
  	return 0;
20b09c299   Andy Yan   [SCSI] mvsas: add...
619
620
  err_not_sas:
  	sas_unregister_ha(SHOST_TO_SAS_HA(shost));
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
621
622
  err_out_shost:
  	scsi_remove_host(mvi->shost);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
623
624
625
626
  err_out_regions:
  	pci_release_regions(pdev);
  err_out_disable:
  	pci_disable_device(pdev);
20b09c299   Andy Yan   [SCSI] mvsas: add...
627
  err_out_enable:
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
628
629
630
631
632
  	return rc;
  }
  
  static void __devexit mvs_pci_remove(struct pci_dev *pdev)
  {
20b09c299   Andy Yan   [SCSI] mvsas: add...
633
634
635
  	unsigned short core_nr, i = 0;
  	struct sas_ha_struct *sha = pci_get_drvdata(pdev);
  	struct mvs_info *mvi = NULL;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
636

20b09c299   Andy Yan   [SCSI] mvsas: add...
637
638
  	core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
  	mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
639

6f8ac161b   Xiangliang Yu   [SCSI] mvsas: Add...
640
641
  #ifdef CONFIG_SCSI_MVSAS_TASKLET
  	tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
20b09c299   Andy Yan   [SCSI] mvsas: add...
642
  #endif
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
643

20b09c299   Andy Yan   [SCSI] mvsas: add...
644
645
646
647
648
649
  	pci_set_drvdata(pdev, NULL);
  	sas_unregister_ha(sha);
  	sas_remove_host(mvi->shost);
  	scsi_remove_host(mvi->shost);
  
  	MVS_CHIP_DISP->interrupt_disable(mvi);
b89e8f539   Xiangliang Yu   [SCSI] mvsas: Rem...
650
  	free_irq(mvi->pdev->irq, sha);
20b09c299   Andy Yan   [SCSI] mvsas: add...
651
652
  	for (i = 0; i < core_nr; i++) {
  		mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
653
  		mvs_free(mvi);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
654
  	}
20b09c299   Andy Yan   [SCSI] mvsas: add...
655
656
657
658
  	kfree(sha->sas_phy);
  	kfree(sha->sas_port);
  	kfree(sha);
  	pci_release_regions(pdev);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
659
  	pci_disable_device(pdev);
20b09c299   Andy Yan   [SCSI] mvsas: add...
660
  	return;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
661
662
663
664
665
666
667
668
669
670
671
672
  }
  
  static struct pci_device_id __devinitdata mvs_pci_table[] = {
  	{ PCI_VDEVICE(MARVELL, 0x6320), chip_6320 },
  	{ PCI_VDEVICE(MARVELL, 0x6340), chip_6440 },
  	{
  		.vendor 	= PCI_VENDOR_ID_MARVELL,
  		.device 	= 0x6440,
  		.subvendor	= PCI_ANY_ID,
  		.subdevice	= 0x6480,
  		.class		= 0,
  		.class_mask	= 0,
20b09c299   Andy Yan   [SCSI] mvsas: add...
673
  		.driver_data	= chip_6485,
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
674
675
  	},
  	{ PCI_VDEVICE(MARVELL, 0x6440), chip_6440 },
20b09c299   Andy Yan   [SCSI] mvsas: add...
676
677
678
  	{ PCI_VDEVICE(MARVELL, 0x6485), chip_6485 },
  	{ PCI_VDEVICE(MARVELL, 0x9480), chip_9480 },
  	{ PCI_VDEVICE(MARVELL, 0x9180), chip_9180 },
f31491dc7   Nick Cheng   [SCSI] mvsas: Sup...
679
680
  	{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
  	{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
7ec4ad012   Srinivas   [SCSI] mvsas: add...
681
  	{ PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
463b8977e   HighPoint Linux Team   [SCSI] mvsas: Add...
682
683
684
685
686
687
688
  	{ PCI_VDEVICE(TTI, 0x2710), chip_9480 },
  	{ PCI_VDEVICE(TTI, 0x2720), chip_9480 },
  	{ PCI_VDEVICE(TTI, 0x2721), chip_9480 },
  	{ PCI_VDEVICE(TTI, 0x2722), chip_9480 },
  	{ PCI_VDEVICE(TTI, 0x2740), chip_9480 },
  	{ PCI_VDEVICE(TTI, 0x2744), chip_9480 },
  	{ PCI_VDEVICE(TTI, 0x2760), chip_9480 },
821402834   Xiangliang Yu   [SCSI] mvsas: add...
689
690
  	{
  		.vendor		= 0x1b4b,
f7e45b6a0   Xiangliang Yu   [SCSI] mvsas: add...
691
692
693
694
695
696
697
698
699
  		.device		= 0x9480,
  		.subvendor	= PCI_ANY_ID,
  		.subdevice	= 0x9480,
  		.class		= 0,
  		.class_mask	= 0,
  		.driver_data	= chip_9480,
  	},
  	{
  		.vendor		= 0x1b4b,
821402834   Xiangliang Yu   [SCSI] mvsas: add...
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
  		.device		= 0x9445,
  		.subvendor	= PCI_ANY_ID,
  		.subdevice	= 0x9480,
  		.class		= 0,
  		.class_mask	= 0,
  		.driver_data	= chip_9445,
  	},
  	{
  		.vendor		= 0x1b4b,
  		.device		= 0x9485,
  		.subvendor	= PCI_ANY_ID,
  		.subdevice	= 0x9480,
  		.class		= 0,
  		.class_mask	= 0,
  		.driver_data	= chip_9485,
  	},
99a700bcc   Robin H. Johnson   [SCSI] mv_sas: OC...
716
717
718
719
720
721
722
723
724
725
  	{ PCI_VDEVICE(OCZ, 0x1021), chip_9485}, /* OCZ RevoDrive3 */
  	{ PCI_VDEVICE(OCZ, 0x1022), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
  	{ PCI_VDEVICE(OCZ, 0x1040), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
  	{ PCI_VDEVICE(OCZ, 0x1041), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
  	{ PCI_VDEVICE(OCZ, 0x1042), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
  	{ PCI_VDEVICE(OCZ, 0x1043), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
  	{ PCI_VDEVICE(OCZ, 0x1044), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
  	{ PCI_VDEVICE(OCZ, 0x1080), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
  	{ PCI_VDEVICE(OCZ, 0x1083), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
  	{ PCI_VDEVICE(OCZ, 0x1084), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
726
727
728
729
730
731
732
733
734
735
  
  	{ }	/* terminate list */
  };
  
  static struct pci_driver mvs_pci_driver = {
  	.name		= DRV_NAME,
  	.id_table	= mvs_pci_table,
  	.probe		= mvs_pci_init,
  	.remove		= __devexit_p(mvs_pci_remove),
  };
83c7b61cf   Xiangliang Yu   [SCSI] mvsas: Add...
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
  static ssize_t
  mvs_show_driver_version(struct device *cdev,
  		struct device_attribute *attr,  char *buffer)
  {
  	return snprintf(buffer, PAGE_SIZE, "%s
  ", DRV_VERSION);
  }
  
  static DEVICE_ATTR(driver_version,
  			 S_IRUGO,
  			 mvs_show_driver_version,
  			 NULL);
  
  static ssize_t
  mvs_store_interrupt_coalescing(struct device *cdev,
  			struct device_attribute *attr,
  			const char *buffer, size_t size)
  {
  	int val = 0;
  	struct mvs_info *mvi = NULL;
  	struct Scsi_Host *shost = class_to_shost(cdev);
  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
  	u8 i, core_nr;
  	if (buffer == NULL)
  		return size;
  
  	if (sscanf(buffer, "%d", &val) != 1)
  		return -EINVAL;
  
  	if (val >= 0x10000) {
  		mv_dprintk("interrupt coalescing timer %d us is"
  			"too long
  ", val);
  		return strlen(buffer);
  	}
  
  	interrupt_coalescing = val;
  
  	core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
  	mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
  
  	if (unlikely(!mvi))
  		return -EINVAL;
  
  	for (i = 0; i < core_nr; i++) {
  		mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
  		if (MVS_CHIP_DISP->tune_interrupt)
  			MVS_CHIP_DISP->tune_interrupt(mvi,
  				interrupt_coalescing);
  	}
  	mv_dprintk("set interrupt coalescing time to %d us
  ",
  		interrupt_coalescing);
  	return strlen(buffer);
  }
  
  static ssize_t mvs_show_interrupt_coalescing(struct device *cdev,
  			struct device_attribute *attr, char *buffer)
  {
  	return snprintf(buffer, PAGE_SIZE, "%d
  ", interrupt_coalescing);
  }
  
  static DEVICE_ATTR(interrupt_coalescing,
  			 S_IRUGO|S_IWUSR,
  			 mvs_show_interrupt_coalescing,
  			 mvs_store_interrupt_coalescing);
20b09c299   Andy Yan   [SCSI] mvsas: add...
803
804
  /* task handler */
  struct task_struct *mvs_th;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
805
806
807
  static int __init mvs_init(void)
  {
  	int rc;
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
808
809
810
  	mvs_stt = sas_domain_attach_transport(&mvs_transport_ops);
  	if (!mvs_stt)
  		return -ENOMEM;
0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
811
812
813
814
815
816
817
818
  	mvs_task_list_cache = kmem_cache_create("mvs_task_list", sizeof(struct mvs_task_list),
  							 0, SLAB_HWCACHE_ALIGN, NULL);
  	if (!mvs_task_list_cache) {
  		rc = -ENOMEM;
  		mv_printk("%s: mvs_task_list_cache alloc failed! 
  ", __func__);
  		goto err_out;
  	}
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
819
  	rc = pci_register_driver(&mvs_pci_driver);
20b09c299   Andy Yan   [SCSI] mvsas: add...
820

dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
821
822
823
824
825
826
827
828
829
830
831
832
833
834
  	if (rc)
  		goto err_out;
  
  	return 0;
  
  err_out:
  	sas_release_transport(mvs_stt);
  	return rc;
  }
  
  static void __exit mvs_exit(void)
  {
  	pci_unregister_driver(&mvs_pci_driver);
  	sas_release_transport(mvs_stt);
0b15fb1fd   Xiangliang Yu   [SCSI] mvsas: add...
835
  	kmem_cache_destroy(mvs_task_list_cache);
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
836
  }
83c7b61cf   Xiangliang Yu   [SCSI] mvsas: Add...
837
838
839
840
841
  struct device_attribute *mvst_host_attrs[] = {
  	&dev_attr_driver_version,
  	&dev_attr_interrupt_coalescing,
  	NULL,
  };
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
842
843
844
845
846
847
848
  module_init(mvs_init);
  module_exit(mvs_exit);
  
  MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
  MODULE_DESCRIPTION("Marvell 88SE6440 SAS/SATA controller driver");
  MODULE_VERSION(DRV_VERSION);
  MODULE_LICENSE("GPL");
20b09c299   Andy Yan   [SCSI] mvsas: add...
849
  #ifdef CONFIG_PCI
dd4969a89   Jeff Garzik   [SCSI] mvsas: spl...
850
  MODULE_DEVICE_TABLE(pci, mvs_pci_table);
20b09c299   Andy Yan   [SCSI] mvsas: add...
851
  #endif