pm8001_init.c 45.2 KB
Newer Older
J
jack wang 已提交
1
/*
2
 * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver
J
jack wang 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
 *
 * Copyright (c) 2008-2009 USI Co., Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 */

41
#include <linux/slab.h>
J
jack wang 已提交
42 43
#include "pm8001_sas.h"
#include "pm8001_chips.h"
44
#include "pm80xx_hwi.h"
J
jack wang 已提交
45

46 47 48 49
static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING;
module_param(logging_level, ulong, 0644);
MODULE_PARM_DESC(logging_level, " bits for enabling logging info.");

50 51 52 53 54 55 56 57
static ulong link_rate = LINKRATE_15 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120;
module_param(link_rate, ulong, 0644);
MODULE_PARM_DESC(link_rate, "Enable link rate.\n"
		" 1: Link rate 1.5G\n"
		" 2: Link rate 3.0G\n"
		" 4: Link rate 6.0G\n"
		" 8: Link rate 12.0G\n");

J
jack wang 已提交
58
static struct scsi_transport_template *pm8001_stt;
59
static int pm8001_init_ccb_tag(struct pm8001_hba_info *, struct Scsi_Host *, struct pci_dev *);
J
jack wang 已提交
60

61
/*
62 63 64
 * chip info structure to identify chip key functionality as
 * encryption available/not, no of ports, hw specific function ref
 */
J
jack wang 已提交
65
static const struct pm8001_chip_info pm8001_chips[] = {
66
	[chip_8001] = {0,  8, &pm8001_8001_dispatch,},
67 68 69 70
	[chip_8008] = {0,  8, &pm8001_80xx_dispatch,},
	[chip_8009] = {1,  8, &pm8001_80xx_dispatch,},
	[chip_8018] = {0,  16, &pm8001_80xx_dispatch,},
	[chip_8019] = {1,  16, &pm8001_80xx_dispatch,},
71 72 73
	[chip_8074] = {0,  8, &pm8001_80xx_dispatch,},
	[chip_8076] = {0,  16, &pm8001_80xx_dispatch,},
	[chip_8077] = {0,  16, &pm8001_80xx_dispatch,},
74
	[chip_8006] = {0,  16, &pm8001_80xx_dispatch,},
75 76
	[chip_8070] = {0,  8, &pm8001_80xx_dispatch,},
	[chip_8072] = {0,  16, &pm8001_80xx_dispatch,},
J
jack wang 已提交
77 78 79 80 81
};
static int pm8001_id;

LIST_HEAD(hba_list);

82 83
struct workqueue_struct *pm8001_wq;

84
/*
J
jack wang 已提交
85 86 87 88 89 90
 * The main structure which LLDD must register for scsi core.
 */
static struct scsi_host_template pm8001_sht = {
	.module			= THIS_MODULE,
	.name			= DRV_NAME,
	.queuecommand		= sas_queuecommand,
91
	.dma_need_drain		= ata_scsi_dma_need_drain,
J
jack wang 已提交
92
	.target_alloc		= sas_target_alloc,
93
	.slave_configure	= sas_slave_configure,
J
jack wang 已提交
94 95 96 97 98 99
	.scan_finished		= pm8001_scan_finished,
	.scan_start		= pm8001_scan_start,
	.change_queue_depth	= sas_change_queue_depth,
	.bios_param		= sas_bios_param,
	.can_queue		= 1,
	.this_id		= -1,
100
	.sg_tablesize		= PM8001_MAX_DMA_SG,
J
jack wang 已提交
101 102
	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
	.eh_device_reset_handler = sas_eh_device_reset_handler,
103
	.eh_target_reset_handler = sas_eh_target_reset_handler,
104
	.slave_alloc		= sas_slave_alloc,
J
jack wang 已提交
105 106
	.target_destroy		= sas_target_destroy,
	.ioctl			= sas_ioctl,
107 108 109
#ifdef CONFIG_COMPAT
	.compat_ioctl		= sas_ioctl,
#endif
110
	.shost_groups		= pm8001_host_groups,
111
	.track_queue_depth	= 1,
J
jack wang 已提交
112 113
};

114
/*
J
jack wang 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
 * Sas layer call this function to execute specific task.
 */
static struct sas_domain_function_template pm8001_transport_ops = {
	.lldd_dev_found		= pm8001_dev_found,
	.lldd_dev_gone		= pm8001_dev_gone,

	.lldd_execute_task	= pm8001_queue_command,
	.lldd_control_phy	= pm8001_phy_control,

	.lldd_abort_task	= pm8001_abort_task,
	.lldd_abort_task_set	= pm8001_abort_task_set,
	.lldd_clear_aca		= pm8001_clear_aca,
	.lldd_clear_task_set	= pm8001_clear_task_set,
	.lldd_I_T_nexus_reset   = pm8001_I_T_nexus_reset,
	.lldd_lu_reset		= pm8001_lu_reset,
	.lldd_query_task	= pm8001_query_task,
131
	.lldd_port_formed	= pm8001_port_formed,
J
jack wang 已提交
132 133 134
};

/**
135 136 137
 * pm8001_phy_init - initiate our adapter phys
 * @pm8001_ha: our hba structure.
 * @phy_id: phy id.
J
jack wang 已提交
138
 */
139
static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id)
J
jack wang 已提交
140 141 142
{
	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
	struct asd_sas_phy *sas_phy = &phy->sas_phy;
143
	phy->phy_state = PHY_LINK_DISABLE;
J
jack wang 已提交
144 145 146 147 148 149 150 151 152 153
	phy->pm8001_ha = pm8001_ha;
	sas_phy->enabled = (phy_id < pm8001_ha->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;
154
	sas_phy->sas_addr = (u8 *)&phy->dev_sas_addr;
J
jack wang 已提交
155 156 157 158 159 160
	sas_phy->frame_rcvd = &phy->frame_rcvd[0];
	sas_phy->ha = (struct sas_ha_struct *)pm8001_ha->shost->hostdata;
	sas_phy->lldd_phy = phy;
}

/**
161 162
 * pm8001_free - free hba
 * @pm8001_ha:	our hba structure.
J
jack wang 已提交
163 164 165 166 167 168 169 170 171 172
 */
static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
{
	int i;

	if (!pm8001_ha)
		return;

	for (i = 0; i < USI_MAX_MEMCNT; i++) {
		if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) {
173
			dma_free_coherent(&pm8001_ha->pdev->dev,
174 175
				(pm8001_ha->memoryMap.region[i].total_len +
				pm8001_ha->memoryMap.region[i].alignment),
J
jack wang 已提交
176 177 178 179 180
				pm8001_ha->memoryMap.region[i].virt_ptr,
				pm8001_ha->memoryMap.region[i].phys_addr);
			}
	}
	PM8001_CHIP_DISP->chip_iounmap(pm8001_ha);
181
	flush_workqueue(pm8001_wq);
J
jack wang 已提交
182 183 184 185 186
	kfree(pm8001_ha->tags);
	kfree(pm8001_ha);
}

#ifdef PM8001_USE_TASKLET
187 188

/**
189
 * pm8001_tasklet() - tasklet for 64 msi-x interrupt handler
190 191 192
 * @opaque: the passed general host adapter struct
 * Note: pm8001_tasklet is common for pm8001 & pm80xx
 */
J
jack wang 已提交
193 194 195
static void pm8001_tasklet(unsigned long opaque)
{
	struct pm8001_hba_info *pm8001_ha;
196 197 198 199
	struct isr_param *irq_vector;

	irq_vector = (struct isr_param *)opaque;
	pm8001_ha = irq_vector->drv_inst;
J
jack wang 已提交
200 201
	if (unlikely(!pm8001_ha))
		BUG_ON(1);
202
	PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
203 204 205 206 207 208 209
}
#endif

/**
 * pm8001_interrupt_handler_msix - main MSIX interrupt handler.
 * It obtains the vector number and calls the equivalent bottom
 * half or services directly.
210
 * @irq: interrupt number
211 212 213 214 215
 * @opaque: the passed outbound queue/vector. Host structure is
 * retrieved from the same.
 */
static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
{
216 217
	struct isr_param *irq_vector;
	struct pm8001_hba_info *pm8001_ha;
218
	irqreturn_t ret = IRQ_HANDLED;
219 220 221
	irq_vector = (struct isr_param *)opaque;
	pm8001_ha = irq_vector->drv_inst;

222 223
	if (unlikely(!pm8001_ha))
		return IRQ_NONE;
224
	if (!PM8001_CHIP_DISP->is_our_interrupt(pm8001_ha))
225 226
		return IRQ_NONE;
#ifdef PM8001_USE_TASKLET
227
	tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id]);
228
#else
229
	ret = PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
J
jack wang 已提交
230
#endif
231 232
	return ret;
}
J
jack wang 已提交
233

234 235
/**
 * pm8001_interrupt_handler_intx - main INTx interrupt handler.
236
 * @irq: interrupt number
237
 * @dev_id: sas_ha structure. The HBA is retrieved from sas_ha structure.
238
 */
J
jack wang 已提交
239

240
static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
J
jack wang 已提交
241 242 243
{
	struct pm8001_hba_info *pm8001_ha;
	irqreturn_t ret = IRQ_HANDLED;
244
	struct sas_ha_struct *sha = dev_id;
J
jack wang 已提交
245 246 247
	pm8001_ha = sha->lldd_ha;
	if (unlikely(!pm8001_ha))
		return IRQ_NONE;
248
	if (!PM8001_CHIP_DISP->is_our_interrupt(pm8001_ha))
J
jack wang 已提交
249
		return IRQ_NONE;
250

J
jack wang 已提交
251
#ifdef PM8001_USE_TASKLET
252
	tasklet_schedule(&pm8001_ha->tasklet[0]);
J
jack wang 已提交
253
#else
254
	ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
J
jack wang 已提交
255 256 257 258
#endif
	return ret;
}

259 260 261
static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha);
static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha);

J
jack wang 已提交
262 263
/**
 * pm8001_alloc - initiate our hba structure and 6 DMAs area.
264 265
 * @pm8001_ha: our hba structure.
 * @ent: PCI device ID structure to match on
J
jack wang 已提交
266
 */
267 268
static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
			const struct pci_device_id *ent)
J
jack wang 已提交
269
{
270 271
	int i, count = 0, rc = 0;
	u32 ci_offset, ib_offset, ob_offset, pi_offset;
272 273
	struct inbound_queue_table *ibq;
	struct outbound_queue_table *obq;
274

J
jack wang 已提交
275
	spin_lock_init(&pm8001_ha->lock);
276
	spin_lock_init(&pm8001_ha->bitmap_lock);
277 278
	pm8001_dbg(pm8001_ha, INIT, "pm8001_alloc: PHY:%x\n",
		   pm8001_ha->chip->n_phy);
279 280 281 282

	/* Setup Interrupt */
	rc = pm8001_setup_irq(pm8001_ha);
	if (rc) {
283 284
		pm8001_dbg(pm8001_ha, FAIL,
			   "pm8001_setup_irq failed [ret: %d]\n", rc);
285 286 287 288 289 290 291 292 293
		goto err_out_shost;
	}
	/* Request Interrupt */
	rc = pm8001_request_irq(pm8001_ha);
	if (rc)
		goto err_out_shost;

	count = pm8001_ha->max_q_num;
	/* Queues are chosen based on the number of cores/msix availability */
294
	ib_offset = pm8001_ha->ib_offset  = USI_MAX_MEMCNT_BASE;
295 296 297 298 299
	ci_offset = pm8001_ha->ci_offset  = ib_offset + count;
	ob_offset = pm8001_ha->ob_offset  = ci_offset + count;
	pi_offset = pm8001_ha->pi_offset  = ob_offset + count;
	pm8001_ha->max_memcnt = pi_offset + count;

300
	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
J
jack wang 已提交
301
		pm8001_phy_init(pm8001_ha, i);
302 303 304 305 306
		pm8001_ha->port[i].wide_port_phymap = 0;
		pm8001_ha->port[i].port_attached = 0;
		pm8001_ha->port[i].port_state = 0;
		INIT_LIST_HEAD(&pm8001_ha->port[i].list);
	}
J
jack wang 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319

	/* MPI Memory region 1 for AAP Event Log for fw */
	pm8001_ha->memoryMap.region[AAP1].num_elements = 1;
	pm8001_ha->memoryMap.region[AAP1].element_size = PM8001_EVENT_LOG_SIZE;
	pm8001_ha->memoryMap.region[AAP1].total_len = PM8001_EVENT_LOG_SIZE;
	pm8001_ha->memoryMap.region[AAP1].alignment = 32;

	/* MPI Memory region 2 for IOP Event Log for fw */
	pm8001_ha->memoryMap.region[IOP].num_elements = 1;
	pm8001_ha->memoryMap.region[IOP].element_size = PM8001_EVENT_LOG_SIZE;
	pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE;
	pm8001_ha->memoryMap.region[IOP].alignment = 32;

320
	for (i = 0; i < count; i++) {
321 322
		ibq = &pm8001_ha->inbnd_q_tbl[i];
		spin_lock_init(&ibq->iq_lock);
323
		/* MPI Memory region 3 for consumer Index of inbound queues */
324 325 326 327
		pm8001_ha->memoryMap.region[ci_offset+i].num_elements = 1;
		pm8001_ha->memoryMap.region[ci_offset+i].element_size = 4;
		pm8001_ha->memoryMap.region[ci_offset+i].total_len = 4;
		pm8001_ha->memoryMap.region[ci_offset+i].alignment = 4;
328 329 330

		if ((ent->driver_data) != chip_8001) {
			/* MPI Memory region 5 inbound queues */
331
			pm8001_ha->memoryMap.region[ib_offset+i].num_elements =
332
						PM8001_MPI_QUEUE;
333 334 335
			pm8001_ha->memoryMap.region[ib_offset+i].element_size
								= 128;
			pm8001_ha->memoryMap.region[ib_offset+i].total_len =
336
						PM8001_MPI_QUEUE * 128;
337 338
			pm8001_ha->memoryMap.region[ib_offset+i].alignment
								= 128;
339
		} else {
340
			pm8001_ha->memoryMap.region[ib_offset+i].num_elements =
341
						PM8001_MPI_QUEUE;
342 343 344
			pm8001_ha->memoryMap.region[ib_offset+i].element_size
								= 64;
			pm8001_ha->memoryMap.region[ib_offset+i].total_len =
345
						PM8001_MPI_QUEUE * 64;
346
			pm8001_ha->memoryMap.region[ib_offset+i].alignment = 64;
347 348 349
		}
	}

350
	for (i = 0; i < count; i++) {
351 352
		obq = &pm8001_ha->outbnd_q_tbl[i];
		spin_lock_init(&obq->oq_lock);
353
		/* MPI Memory region 4 for producer Index of outbound queues */
354 355 356 357
		pm8001_ha->memoryMap.region[pi_offset+i].num_elements = 1;
		pm8001_ha->memoryMap.region[pi_offset+i].element_size = 4;
		pm8001_ha->memoryMap.region[pi_offset+i].total_len = 4;
		pm8001_ha->memoryMap.region[pi_offset+i].alignment = 4;
358 359 360

		if (ent->driver_data != chip_8001) {
			/* MPI Memory region 6 Outbound queues */
361
			pm8001_ha->memoryMap.region[ob_offset+i].num_elements =
362
						PM8001_MPI_QUEUE;
363 364 365
			pm8001_ha->memoryMap.region[ob_offset+i].element_size
								= 128;
			pm8001_ha->memoryMap.region[ob_offset+i].total_len =
366
						PM8001_MPI_QUEUE * 128;
367 368
			pm8001_ha->memoryMap.region[ob_offset+i].alignment
								= 128;
369 370
		} else {
			/* MPI Memory region 6 Outbound queues */
371
			pm8001_ha->memoryMap.region[ob_offset+i].num_elements =
372
						PM8001_MPI_QUEUE;
373 374 375
			pm8001_ha->memoryMap.region[ob_offset+i].element_size
								= 64;
			pm8001_ha->memoryMap.region[ob_offset+i].total_len =
376
						PM8001_MPI_QUEUE * 64;
377
			pm8001_ha->memoryMap.region[ob_offset+i].alignment = 64;
378
		}
J
jack wang 已提交
379

380
	}
J
jack wang 已提交
381 382 383 384 385
	/* Memory region write DMA*/
	pm8001_ha->memoryMap.region[NVMD].num_elements = 1;
	pm8001_ha->memoryMap.region[NVMD].element_size = 4096;
	pm8001_ha->memoryMap.region[NVMD].total_len = 4096;

386 387 388
	/* Memory region for fw flash */
	pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096;

389 390 391 392
	pm8001_ha->memoryMap.region[FORENSIC_MEM].num_elements = 1;
	pm8001_ha->memoryMap.region[FORENSIC_MEM].total_len = 0x10000;
	pm8001_ha->memoryMap.region[FORENSIC_MEM].element_size = 0x10000;
	pm8001_ha->memoryMap.region[FORENSIC_MEM].alignment = 0x10000;
393
	for (i = 0; i < pm8001_ha->max_memcnt; i++) {
J
Joe Perches 已提交
394 395
		struct mpi_mem *region = &pm8001_ha->memoryMap.region[i];

J
jack wang 已提交
396
		if (pm8001_mem_alloc(pm8001_ha->pdev,
J
Joe Perches 已提交
397 398 399 400 401 402 403 404
				     &region->virt_ptr,
				     &region->phys_addr,
				     &region->phys_addr_hi,
				     &region->phys_addr_lo,
				     region->total_len,
				     region->alignment) != 0) {
			pm8001_dbg(pm8001_ha, FAIL, "Mem%d alloc failed\n", i);
			goto err_out;
J
jack wang 已提交
405 406 407
		}
	}

408 409 410 411 412 413 414
	/* Memory region for devices*/
	pm8001_ha->devices = kzalloc(PM8001_MAX_DEVICES
				* sizeof(struct pm8001_device), GFP_KERNEL);
	if (!pm8001_ha->devices) {
		rc = -ENOMEM;
		goto err_out_nodev;
	}
J
jack wang 已提交
415
	for (i = 0; i < PM8001_MAX_DEVICES; i++) {
416
		pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED;
J
jack wang 已提交
417 418
		pm8001_ha->devices[i].id = i;
		pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;
V
Viswas G 已提交
419
		atomic_set(&pm8001_ha->devices[i].running_req, 0);
J
jack wang 已提交
420 421 422 423 424
	}
	pm8001_ha->flags = PM8001F_INIT_TIME;
	/* Initialize tags */
	pm8001_tag_init(pm8001_ha);
	return 0;
425

426 427
err_out_shost:
	scsi_remove_host(pm8001_ha->shost);
428 429 430
err_out_nodev:
	for (i = 0; i < pm8001_ha->max_memcnt; i++) {
		if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) {
431
			dma_free_coherent(&pm8001_ha->pdev->dev,
432 433 434 435 436 437
				(pm8001_ha->memoryMap.region[i].total_len +
				pm8001_ha->memoryMap.region[i].alignment),
				pm8001_ha->memoryMap.region[i].virt_ptr,
				pm8001_ha->memoryMap.region[i].phys_addr);
		}
	}
J
jack wang 已提交
438 439 440 441 442
err_out:
	return 1;
}

/**
443
 * pm8001_ioremap - remap the pci high physical address to kernel virtual
J
jack wang 已提交
444
 * address so that we can access them.
445
 * @pm8001_ha: our hba structure.
J
jack wang 已提交
446 447 448 449 450 451 452 453 454
 */
static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
{
	u32 bar;
	u32 logicalBar = 0;
	struct pci_dev *pdev;

	pdev = pm8001_ha->pdev;
	/* map pci mem (PMC pci base 0-3)*/
455
	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
J
jack wang 已提交
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
		/*
		** logical BARs for SPC:
		** bar 0 and 1 - logical BAR0
		** bar 2 and 3 - logical BAR1
		** bar4 - logical BAR2
		** bar5 - logical BAR3
		** Skip the appropriate assignments:
		*/
		if ((bar == 1) || (bar == 3))
			continue;
		if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {
			pm8001_ha->io_mem[logicalBar].membase =
				pci_resource_start(pdev, bar);
			pm8001_ha->io_mem[logicalBar].memsize =
				pci_resource_len(pdev, bar);
			pm8001_ha->io_mem[logicalBar].memvirtaddr =
				ioremap(pm8001_ha->io_mem[logicalBar].membase,
				pm8001_ha->io_mem[logicalBar].memsize);
474 475 476
			if (!pm8001_ha->io_mem[logicalBar].memvirtaddr) {
				pm8001_dbg(pm8001_ha, INIT,
					"Failed to ioremap bar %d, logicalBar %d",
477
				   bar, logicalBar);
478 479
				return -ENOMEM;
			}
480 481 482 483 484 485
			pm8001_dbg(pm8001_ha, INIT,
				   "base addr %llx virt_addr=%llx len=%d\n",
				   (u64)pm8001_ha->io_mem[logicalBar].membase,
				   (u64)(unsigned long)
				   pm8001_ha->io_mem[logicalBar].memvirtaddr,
				   pm8001_ha->io_mem[logicalBar].memsize);
J
jack wang 已提交
486 487 488
		} else {
			pm8001_ha->io_mem[logicalBar].membase	= 0;
			pm8001_ha->io_mem[logicalBar].memsize	= 0;
489
			pm8001_ha->io_mem[logicalBar].memvirtaddr = NULL;
J
jack wang 已提交
490 491 492 493 494 495 496 497 498 499 500 501
		}
		logicalBar++;
	}
	return 0;
}

/**
 * pm8001_pci_alloc - initialize our ha card structure
 * @pdev: pci device.
 * @ent: ent
 * @shost: scsi host struct which has been initialized before.
 */
502
static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
503 504 505
				 const struct pci_device_id *ent,
				struct Scsi_Host *shost)

J
jack wang 已提交
506 507 508
{
	struct pm8001_hba_info *pm8001_ha;
	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
509
	int j;
J
jack wang 已提交
510 511 512 513 514 515 516

	pm8001_ha = sha->lldd_ha;
	if (!pm8001_ha)
		return NULL;

	pm8001_ha->pdev = pdev;
	pm8001_ha->dev = &pdev->dev;
517
	pm8001_ha->chip_id = ent->driver_data;
J
jack wang 已提交
518 519 520 521 522
	pm8001_ha->chip = &pm8001_chips[pm8001_ha->chip_id];
	pm8001_ha->irq = pdev->irq;
	pm8001_ha->sas = sha;
	pm8001_ha->shost = shost;
	pm8001_ha->id = pm8001_id++;
523
	pm8001_ha->logging_level = logging_level;
524
	pm8001_ha->non_fatal_count = 0;
525 526 527 528 529
	if (link_rate >= 1 && link_rate <= 15)
		pm8001_ha->link_rate = (link_rate << 8);
	else {
		pm8001_ha->link_rate = LINKRATE_15 | LINKRATE_30 |
			LINKRATE_60 | LINKRATE_120;
530 531
		pm8001_dbg(pm8001_ha, FAIL,
			   "Setting link rate to default value\n");
532
	}
J
jack wang 已提交
533
	sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
534 535 536 537 538 539
	/* IOMB size is 128 for 8088/89 controllers */
	if (pm8001_ha->chip_id != chip_8001)
		pm8001_ha->iomb_size = IOMB_SIZE_SPCV;
	else
		pm8001_ha->iomb_size = IOMB_SIZE_SPC;

J
jack wang 已提交
540
#ifdef PM8001_USE_TASKLET
541
	/* Tasklet for non msi-x interrupt handler */
542 543
	if ((!pdev->msix_cap || !pci_msi_enabled())
	    || (pm8001_ha->chip_id == chip_8001))
544 545 546 547 548 549
		tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
			(unsigned long)&(pm8001_ha->irq_vector[0]));
	else
		for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
			tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
				(unsigned long)&(pm8001_ha->irq_vector[j]));
J
jack wang 已提交
550
#endif
551 552
	if (pm8001_ioremap(pm8001_ha))
		goto failed_pci_alloc;
553
	if (!pm8001_alloc(pm8001_ha, ent))
J
jack wang 已提交
554
		return pm8001_ha;
555
failed_pci_alloc:
J
jack wang 已提交
556 557 558 559 560 561 562 563 564 565 566 567
	pm8001_free(pm8001_ha);
	return NULL;
}

/**
 * pci_go_44 - pm8001 specified, its DMA is 44 bit rather than 64 bit
 * @pdev: pci device.
 */
static int pci_go_44(struct pci_dev *pdev)
{
	int rc;

568 569 570 571
	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
	if (rc) {
		rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
		if (rc)
J
jack wang 已提交
572 573 574 575 576 577 578 579 580 581 582
			dev_printk(KERN_ERR, &pdev->dev,
				"32-bit DMA enable failed\n");
	}
	return rc;
}

/**
 * pm8001_prep_sas_ha_init - allocate memory in general hba struct && init them.
 * @shost: scsi host which has been allocated outside.
 * @chip_info: our ha struct.
 */
583 584
static int pm8001_prep_sas_ha_init(struct Scsi_Host *shost,
				   const struct pm8001_chip_info *chip_info)
J
jack wang 已提交
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
{
	int phy_nr, port_nr;
	struct asd_sas_phy **arr_phy;
	struct asd_sas_port **arr_port;
	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);

	phy_nr = chip_info->n_phy;
	port_nr = phy_nr;
	memset(sha, 0x00, sizeof(*sha));
	arr_phy = kcalloc(phy_nr, sizeof(void *), GFP_KERNEL);
	if (!arr_phy)
		goto exit;
	arr_port = kcalloc(port_nr, sizeof(void *), GFP_KERNEL);
	if (!arr_port)
		goto exit_free2;

	sha->sas_phy = arr_phy;
	sha->sas_port = arr_port;
	sha->lldd_ha = kzalloc(sizeof(struct pm8001_hba_info), GFP_KERNEL);
	if (!sha->lldd_ha)
		goto exit_free1;

	shost->transportt = pm8001_stt;
	shost->max_id = PM8001_MAX_DEVICES;
	shost->max_lun = 8;
	shost->max_channel = 0;
	shost->unique_id = pm8001_id;
	shost->max_cmd_len = 16;
	shost->can_queue = PM8001_CAN_QUEUE;
	shost->cmd_per_lun = 32;
	return 0;
exit_free1:
	kfree(arr_port);
exit_free2:
	kfree(arr_phy);
exit:
	return -1;
}

/**
 * pm8001_post_sas_ha_init - initialize general hba struct defined in libsas
 * @shost: scsi host which has been allocated outside
 * @chip_info: our ha struct.
 */
629 630
static void  pm8001_post_sas_ha_init(struct Scsi_Host *shost,
				     const struct pm8001_chip_info *chip_info)
J
jack wang 已提交
631 632 633 634 635 636 637 638 639
{
	int i = 0;
	struct pm8001_hba_info *pm8001_ha;
	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);

	pm8001_ha = sha->lldd_ha;
	for (i = 0; i < chip_info->n_phy; i++) {
		sha->sas_phy[i] = &pm8001_ha->phy[i].sas_phy;
		sha->sas_port[i] = &pm8001_ha->port[i].sas_port;
640 641
		sha->sas_phy[i]->sas_addr =
			(u8 *)&pm8001_ha->phy[i].dev_sas_addr;
J
jack wang 已提交
642 643 644
	}
	sha->sas_ha_name = DRV_NAME;
	sha->dev = pm8001_ha->dev;
645
	sha->strict_wide_ports = 1;
J
jack wang 已提交
646 647 648 649 650 651 652 653
	sha->lldd_module = THIS_MODULE;
	sha->sas_addr = &pm8001_ha->sas_addr[0];
	sha->num_phys = chip_info->n_phy;
	sha->core.shost = shost;
}

/**
 * pm8001_init_sas_add - initialize sas address
654
 * @pm8001_ha: our ha struct.
J
jack wang 已提交
655
 *
656
 * Currently we just set the fixed SAS address to our HBA, for manufacture,
J
jack wang 已提交
657 658 659 660
 * it should read from the EEPROM
 */
static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
{
661
	u8 i, j;
662
	u8 sas_add[8];
J
jack wang 已提交
663
#ifdef PM8001_READ_VPD
664 665 666 667
	/* For new SPC controllers WWN is stored in flash vpd
	*  For SPC/SPCve controllers WWN is stored in EEPROM
	*  For Older SPC WWN is stored in NVMD
	*/
J
jack wang 已提交
668
	DECLARE_COMPLETION_ONSTACK(completion);
669
	struct pm8001_ioctl_payload payload;
670
	u16 deviceid;
671 672
	int rc;

673
	pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
J
jack wang 已提交
674
	pm8001_ha->nvmd_completion = &completion;
675 676

	if (pm8001_ha->chip_id == chip_8001) {
677
		if (deviceid == 0x8081 || deviceid == 0x0042) {
678
			payload.minor_function = 4;
679
			payload.rd_length = 4096;
680 681
		} else {
			payload.minor_function = 0;
682
			payload.rd_length = 128;
683
		}
684 685 686 687
	} else if ((pm8001_ha->chip_id == chip_8070 ||
			pm8001_ha->chip_id == chip_8072) &&
			pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) {
		payload.minor_function = 4;
688
		payload.rd_length = 4096;
689 690
	} else {
		payload.minor_function = 1;
691
		payload.rd_length = 4096;
692 693
	}
	payload.offset = 0;
694
	payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL);
695
	if (!payload.func_specific) {
696
		pm8001_dbg(pm8001_ha, INIT, "mem alloc fail\n");
697 698 699 700 701
		return;
	}
	rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
	if (rc) {
		kfree(payload.func_specific);
702
		pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n");
703 704
		return;
	}
J
jack wang 已提交
705
	wait_for_completion(&completion);
706 707 708 709 710 711

	for (i = 0, j = 0; i <= 7; i++, j++) {
		if (pm8001_ha->chip_id == chip_8001) {
			if (deviceid == 0x8081)
				pm8001_ha->sas_addr[j] =
					payload.func_specific[0x704 + i];
712 713 714
			else if (deviceid == 0x0042)
				pm8001_ha->sas_addr[j] =
					payload.func_specific[0x010 + i];
715 716 717 718 719
		} else if ((pm8001_ha->chip_id == chip_8070 ||
				pm8001_ha->chip_id == chip_8072) &&
				pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) {
			pm8001_ha->sas_addr[j] =
					payload.func_specific[0x010 + i];
720 721 722 723
		} else
			pm8001_ha->sas_addr[j] =
					payload.func_specific[0x804 + i];
	}
724
	memcpy(sas_add, pm8001_ha->sas_addr, SAS_ADDR_SIZE);
J
jack wang 已提交
725
	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
726 727
		if (i && ((i % 4) == 0))
			sas_add[7] = sas_add[7] + 4;
728
		memcpy(&pm8001_ha->phy[i].dev_sas_addr,
729
			sas_add, SAS_ADDR_SIZE);
730 731
		pm8001_dbg(pm8001_ha, INIT, "phy %d sas_addr = %016llx\n", i,
			   pm8001_ha->phy[i].dev_sas_addr);
J
jack wang 已提交
732
	}
733
	kfree(payload.func_specific);
J
jack wang 已提交
734 735
#else
	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
736
		pm8001_ha->phy[i].dev_sas_addr = 0x50010c600047f9d0ULL;
J
jack wang 已提交
737 738 739 740 741 742 743 744 745
		pm8001_ha->phy[i].dev_sas_addr =
			cpu_to_be64((u64)
				(*(u64 *)&pm8001_ha->phy[i].dev_sas_addr));
	}
	memcpy(pm8001_ha->sas_addr, &pm8001_ha->phy[0].dev_sas_addr,
		SAS_ADDR_SIZE);
#endif
}

746 747 748 749
/*
 * pm8001_get_phy_settings_info : Read phy setting values.
 * @pm8001_ha : our hba.
 */
750
static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
751 752 753 754 755 756
{

#ifdef PM8001_READ_VPD
	/*OPTION ROM FLASH read for the SPC cards */
	DECLARE_COMPLETION_ONSTACK(completion);
	struct pm8001_ioctl_payload payload;
757
	int rc;
758 759 760 761 762

	pm8001_ha->nvmd_completion = &completion;
	/* SAS ADDRESS read from flash / EEPROM */
	payload.minor_function = 6;
	payload.offset = 0;
763
	payload.rd_length = 4096;
764
	payload.func_specific = kzalloc(4096, GFP_KERNEL);
765 766
	if (!payload.func_specific)
		return -ENOMEM;
767
	/* Read phy setting values from flash */
768 769 770
	rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
	if (rc) {
		kfree(payload.func_specific);
771
		pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n");
772 773
		return -ENOMEM;
	}
774 775
	wait_for_completion(&completion);
	pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific);
776
	kfree(payload.func_specific);
777
#endif
778
	return 0;
779 780
}

781 782 783 784 785 786 787 788 789 790 791 792 793
struct pm8001_mpi3_phy_pg_trx_config {
	u32 LaneLosCfg;
	u32 LanePgaCfg1;
	u32 LanePisoCfg1;
	u32 LanePisoCfg2;
	u32 LanePisoCfg3;
	u32 LanePisoCfg4;
	u32 LanePisoCfg5;
	u32 LanePisoCfg6;
	u32 LaneBctCtrl;
};

/**
794
 * pm8001_get_internal_phy_settings - Retrieves the internal PHY settings
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
 * @pm8001_ha : our adapter
 * @phycfg : PHY config page to populate
 */
static
void pm8001_get_internal_phy_settings(struct pm8001_hba_info *pm8001_ha,
		struct pm8001_mpi3_phy_pg_trx_config *phycfg)
{
	phycfg->LaneLosCfg   = 0x00000132;
	phycfg->LanePgaCfg1  = 0x00203949;
	phycfg->LanePisoCfg1 = 0x000000FF;
	phycfg->LanePisoCfg2 = 0xFF000001;
	phycfg->LanePisoCfg3 = 0xE7011300;
	phycfg->LanePisoCfg4 = 0x631C40C0;
	phycfg->LanePisoCfg5 = 0xF8102036;
	phycfg->LanePisoCfg6 = 0xF74A1000;
	phycfg->LaneBctCtrl  = 0x00FB33F8;
}

/**
814
 * pm8001_get_external_phy_settings - Retrieves the external PHY settings
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
 * @pm8001_ha : our adapter
 * @phycfg : PHY config page to populate
 */
static
void pm8001_get_external_phy_settings(struct pm8001_hba_info *pm8001_ha,
		struct pm8001_mpi3_phy_pg_trx_config *phycfg)
{
	phycfg->LaneLosCfg   = 0x00000132;
	phycfg->LanePgaCfg1  = 0x00203949;
	phycfg->LanePisoCfg1 = 0x000000FF;
	phycfg->LanePisoCfg2 = 0xFF000001;
	phycfg->LanePisoCfg3 = 0xE7011300;
	phycfg->LanePisoCfg4 = 0x63349140;
	phycfg->LanePisoCfg5 = 0xF8102036;
	phycfg->LanePisoCfg6 = 0xF80D9300;
	phycfg->LaneBctCtrl  = 0x00FB33F8;
}

/**
834
 * pm8001_get_phy_mask - Retrieves the mask that denotes if a PHY is int/ext
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
 * @pm8001_ha : our adapter
 * @phymask : The PHY mask
 */
static
void pm8001_get_phy_mask(struct pm8001_hba_info *pm8001_ha, int *phymask)
{
	switch (pm8001_ha->pdev->subsystem_device) {
	case 0x0070: /* H1280 - 8 external 0 internal */
	case 0x0072: /* H12F0 - 16 external 0 internal */
		*phymask = 0x0000;
		break;

	case 0x0071: /* H1208 - 0 external 8 internal */
	case 0x0073: /* H120F - 0 external 16 internal */
		*phymask = 0xFFFF;
		break;

	case 0x0080: /* H1244 - 4 external 4 internal */
		*phymask = 0x00F0;
		break;

	case 0x0081: /* H1248 - 4 external 8 internal */
		*phymask = 0x0FF0;
		break;

	case 0x0082: /* H1288 - 8 external 8 internal */
		*phymask = 0xFF00;
		break;

	default:
865 866 867
		pm8001_dbg(pm8001_ha, INIT,
			   "Unknown subsystem device=0x%.04x\n",
			   pm8001_ha->pdev->subsystem_device);
868 869 870 871
	}
}

/**
872
 * pm8001_set_phy_settings_ven_117c_12G() - Configure ATTO 12Gb PHY settings
873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
 * @pm8001_ha : our adapter
 */
static
int pm8001_set_phy_settings_ven_117c_12G(struct pm8001_hba_info *pm8001_ha)
{
	struct pm8001_mpi3_phy_pg_trx_config phycfg_int;
	struct pm8001_mpi3_phy_pg_trx_config phycfg_ext;
	int phymask = 0;
	int i = 0;

	memset(&phycfg_int, 0, sizeof(phycfg_int));
	memset(&phycfg_ext, 0, sizeof(phycfg_ext));

	pm8001_get_internal_phy_settings(pm8001_ha, &phycfg_int);
	pm8001_get_external_phy_settings(pm8001_ha, &phycfg_ext);
	pm8001_get_phy_mask(pm8001_ha, &phymask);

	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
		if (phymask & (1 << i)) {/* Internal PHY */
			pm8001_set_phy_profile_single(pm8001_ha, i,
					sizeof(phycfg_int) / sizeof(u32),
					(u32 *)&phycfg_int);

		} else { /* External PHY */
			pm8001_set_phy_profile_single(pm8001_ha, i,
					sizeof(phycfg_ext) / sizeof(u32),
					(u32 *)&phycfg_ext);
		}
	}

	return 0;
}

906
/**
907
 * pm8001_configure_phy_settings - Configures PHY settings based on vendor ID.
908 909 910 911 912 913
 * @pm8001_ha : our hba.
 */
static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha)
{
	switch (pm8001_ha->pdev->subsystem_vendor) {
	case PCI_VENDOR_ID_ATTO:
914 915 916 917 918
		if (pm8001_ha->pdev->device == 0x0042) /* 6Gb */
			return 0;
		else
			return pm8001_set_phy_settings_ven_117c_12G(pm8001_ha);

919 920 921 922 923 924 925 926 927
	case PCI_VENDOR_ID_ADAPTEC2:
	case 0:
		return 0;

	default:
		return pm8001_get_phy_settings_info(pm8001_ha);
	}
}

J
jack wang 已提交
928 929 930
#ifdef PM8001_USE_MSIX
/**
 * pm8001_setup_msix - enable MSI-X interrupt
931
 * @pm8001_ha: our ha struct.
J
jack wang 已提交
932
 */
933
static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
J
jack wang 已提交
934
{
935
	u32 number_of_intr;
936 937
	int rc, cpu_online_count;
	unsigned int allocated_irq_vectors;
938 939 940 941 942 943 944 945

	/* SPCv controllers supports 64 msi-x */
	if (pm8001_ha->chip_id == chip_8001) {
		number_of_intr = 1;
	} else {
		number_of_intr = PM8001_MAX_MSIX_VEC;
	}

946 947
	cpu_online_count = num_online_cpus();
	number_of_intr = min_t(int, cpu_online_count, number_of_intr);
948 949
	rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr,
			number_of_intr, PCI_IRQ_MSIX);
950
	allocated_irq_vectors = rc;
951
	if (rc < 0)
952
		return rc;
953 954 955

	/* Assigns the number of interrupts */
	number_of_intr = min_t(int, allocated_irq_vectors, number_of_intr);
956
	pm8001_ha->number_of_intr = number_of_intr;
957

958 959 960
	/* Maximum queue number updating in HBA structure */
	pm8001_ha->max_q_num = number_of_intr;

961 962 963
	pm8001_dbg(pm8001_ha, INIT,
		   "pci_alloc_irq_vectors request ret:%d no of intr %d\n",
		   rc, pm8001_ha->number_of_intr);
964 965 966 967 968 969 970
	return 0;
}

static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha)
{
	u32 i = 0, j = 0;
	int flag = 0, rc = 0;
971
	int nr_irqs = pm8001_ha->number_of_intr;
972

973 974 975
	if (pm8001_ha->chip_id != chip_8001)
		flag &= ~IRQF_SHARED;

976 977 978
	pm8001_dbg(pm8001_ha, INIT,
		   "pci_enable_msix request number of intr %d\n",
		   pm8001_ha->number_of_intr);
979

980 981 982 983
	if (nr_irqs > ARRAY_SIZE(pm8001_ha->intr_drvname))
		nr_irqs = ARRAY_SIZE(pm8001_ha->intr_drvname);

	for (i = 0; i < nr_irqs; i++) {
984 985 986
		snprintf(pm8001_ha->intr_drvname[i],
			sizeof(pm8001_ha->intr_drvname[0]),
			"%s-%d", pm8001_ha->name, i);
987 988 989
		pm8001_ha->irq_vector[i].irq_id = i;
		pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;

990
		rc = request_irq(pci_irq_vector(pm8001_ha->pdev, i),
991
			pm8001_interrupt_handler_msix, flag,
992 993
			pm8001_ha->intr_drvname[i],
			&(pm8001_ha->irq_vector[i]));
994 995
		if (rc) {
			for (j = 0; j < i; j++) {
996
				free_irq(pci_irq_vector(pm8001_ha->pdev, i),
997
					&(pm8001_ha->irq_vector[i]));
J
jack wang 已提交
998
			}
999
			pci_free_irq_vectors(pm8001_ha->pdev);
1000
			break;
J
jack wang 已提交
1001 1002
		}
	}
1003

J
jack wang 已提交
1004 1005 1006 1007
	return rc;
}
#endif

1008 1009 1010 1011 1012 1013 1014 1015 1016
static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha)
{
	struct pci_dev *pdev;

	pdev = pm8001_ha->pdev;

#ifdef PM8001_USE_MSIX
	if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
		return pm8001_setup_msix(pm8001_ha);
1017
	pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n");
1018 1019 1020 1021
#endif
	return 0;
}

J
jack wang 已提交
1022 1023
/**
 * pm8001_request_irq - register interrupt
1024
 * @pm8001_ha: our ha struct.
J
jack wang 已提交
1025 1026 1027 1028
 */
static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
{
	struct pci_dev *pdev;
1029
	int rc;
J
jack wang 已提交
1030 1031 1032 1033

	pdev = pm8001_ha->pdev;

#ifdef PM8001_USE_MSIX
1034
	if (pdev->msix_cap && pci_msi_enabled())
1035
		return pm8001_request_msix(pm8001_ha);
1036
	else {
1037
		pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n");
J
jack wang 已提交
1038
		goto intx;
1039
	}
J
jack wang 已提交
1040 1041 1042
#endif

intx:
1043
	/* initialize the INT-X interrupt */
1044 1045
	pm8001_ha->irq_vector[0].irq_id = 0;
	pm8001_ha->irq_vector[0].drv_inst = pm8001_ha;
1046
	rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
1047
		pm8001_ha->name, SHOST_TO_SAS_HA(pm8001_ha->shost));
J
jack wang 已提交
1048 1049 1050 1051 1052 1053 1054 1055 1056
	return rc;
}

/**
 * pm8001_pci_probe - probe supported device
 * @pdev: pci device which kernel has been prepared for.
 * @ent: pci device id
 *
 * This function is the main initialization function, when register a new
1057 1058
 * pci driver it is invoked, all struct and hardware initialization should be
 * done here, also, register interrupt.
J
jack wang 已提交
1059
 */
1060 1061
static int pm8001_pci_probe(struct pci_dev *pdev,
			    const struct pci_device_id *ent)
J
jack wang 已提交
1062 1063 1064
{
	unsigned int rc;
	u32	pci_reg;
1065
	u8	i = 0;
J
jack wang 已提交
1066 1067 1068
	struct pm8001_hba_info *pm8001_ha;
	struct Scsi_Host *shost = NULL;
	const struct pm8001_chip_info *chip;
1069
	struct sas_ha_struct *sha;
J
jack wang 已提交
1070 1071

	dev_printk(KERN_INFO, &pdev->dev,
1072
		"pm80xx: driver version %s\n", DRV_VERSION);
J
jack wang 已提交
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
	rc = pci_enable_device(pdev);
	if (rc)
		goto err_out_enable;
	pci_set_master(pdev);
	/*
	 * Enable pci slot busmaster by setting pci command register.
	 * This is required by FW for Cyclone card.
	 */

	pci_read_config_dword(pdev, PCI_COMMAND, &pci_reg);
	pci_reg |= 0x157;
	pci_write_config_dword(pdev, PCI_COMMAND, pci_reg);
	rc = pci_request_regions(pdev, DRV_NAME);
	if (rc)
		goto err_out_disable;
	rc = pci_go_44(pdev);
	if (rc)
		goto err_out_regions;

	shost = scsi_host_alloc(&pm8001_sht, sizeof(void *));
	if (!shost) {
		rc = -ENOMEM;
		goto err_out_regions;
	}
	chip = &pm8001_chips[ent->driver_data];
1098 1099
	sha = kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
	if (!sha) {
J
jack wang 已提交
1100 1101 1102
		rc = -ENOMEM;
		goto err_out_free_host;
	}
1103
	SHOST_TO_SAS_HA(shost) = sha;
J
jack wang 已提交
1104 1105 1106 1107 1108 1109 1110

	rc = pm8001_prep_sas_ha_init(shost, chip);
	if (rc) {
		rc = -ENOMEM;
		goto err_out_free;
	}
	pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost));
1111 1112
	/* ent->driver variable is used to differentiate between controllers */
	pm8001_ha = pm8001_pci_alloc(pdev, ent, shost);
J
jack wang 已提交
1113 1114 1115 1116
	if (!pm8001_ha) {
		rc = -ENOMEM;
		goto err_out_free;
	}
1117

1118
	PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
J
jack wang 已提交
1119
	rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
1120
	if (rc) {
1121 1122
		pm8001_dbg(pm8001_ha, FAIL,
			   "chip_init failed [ret: %d]\n", rc);
J
jack wang 已提交
1123
		goto err_out_ha_free;
1124
	}
J
jack wang 已提交
1125

1126 1127 1128 1129
	rc = pm8001_init_ccb_tag(pm8001_ha, shost, pdev);
	if (rc)
		goto err_out_enable;

J
jack wang 已提交
1130 1131 1132 1133
	rc = scsi_add_host(shost, &pdev->dev);
	if (rc)
		goto err_out_ha_free;

1134
	PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
1135 1136 1137
	if (pm8001_ha->chip_id != chip_8001) {
		for (i = 1; i < pm8001_ha->number_of_intr; i++)
			PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
1138 1139
		/* setup thermal configuration. */
		pm80xx_set_thermal_config(pm8001_ha);
1140 1141
	}

J
jack wang 已提交
1142
	pm8001_init_sas_add(pm8001_ha);
1143
	/* phy setting support for motherboard controller */
1144 1145
	rc = pm8001_configure_phy_settings(pm8001_ha);
	if (rc)
1146 1147
		goto err_out_shost;

J
jack wang 已提交
1148 1149
	pm8001_post_sas_ha_init(shost, chip);
	rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
1150
	if (rc) {
1151 1152
		pm8001_dbg(pm8001_ha, FAIL,
			   "sas_register_ha failed [ret: %d]\n", rc);
J
jack wang 已提交
1153
		goto err_out_shost;
1154 1155
	}
	list_add_tail(&pm8001_ha->list, &hba_list);
1156
	pm8001_ha->flags = PM8001F_RUN_TIME;
1157
	scsi_scan_host(pm8001_ha->shost);
J
jack wang 已提交
1158 1159 1160 1161 1162 1163 1164
	return 0;

err_out_shost:
	scsi_remove_host(pm8001_ha->shost);
err_out_ha_free:
	pm8001_free(pm8001_ha);
err_out_free:
1165
	kfree(sha);
J
jack wang 已提交
1166
err_out_free_host:
1167
	scsi_host_put(shost);
J
jack wang 已提交
1168 1169 1170 1171 1172 1173 1174 1175
err_out_regions:
	pci_release_regions(pdev);
err_out_disable:
	pci_disable_device(pdev);
err_out_enable:
	return rc;
}

1176
/**
1177 1178 1179
 * pm8001_init_ccb_tag - allocate memory to CCB and tag.
 * @pm8001_ha: our hba card information.
 * @shost: scsi host which has been allocated outside.
1180
 * @pdev: pci device.
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201
 */
static int
pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost,
			struct pci_dev *pdev)
{
	int i = 0;
	u32 max_out_io, ccb_count;
	u32 can_queue;

	max_out_io = pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io;
	ccb_count = min_t(int, PM8001_MAX_CCB, max_out_io);

	/* Update to the scsi host*/
	can_queue = ccb_count - PM8001_RESERVE_SLOT;
	shost->can_queue = can_queue;

	pm8001_ha->tags = kzalloc(ccb_count, GFP_KERNEL);
	if (!pm8001_ha->tags)
		goto err_out;

	/* Memory region for ccb_info*/
1202
	pm8001_ha->ccb_count = ccb_count;
1203
	pm8001_ha->ccb_info =
1204 1205
		kcalloc(ccb_count, sizeof(struct pm8001_ccb_info), GFP_KERNEL);
	if (!pm8001_ha->ccb_info) {
1206 1207
		pm8001_dbg(pm8001_ha, FAIL,
			   "Unable to allocate memory for ccb\n");
1208 1209 1210
		goto err_out_noccb;
	}
	for (i = 0; i < ccb_count; i++) {
1211
		pm8001_ha->ccb_info[i].buf_prd = dma_alloc_coherent(&pdev->dev,
1212
				sizeof(struct pm8001_prd) * PM8001_MAX_DMA_SG,
1213 1214
				&pm8001_ha->ccb_info[i].ccb_dma_handle,
				GFP_KERNEL);
1215
		if (!pm8001_ha->ccb_info[i].buf_prd) {
1216
			pm8001_dbg(pm8001_ha, FAIL,
1217
				   "ccb prd memory allocation error\n");
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
			goto err_out;
		}
		pm8001_ha->ccb_info[i].task = NULL;
		pm8001_ha->ccb_info[i].ccb_tag = 0xffffffff;
		pm8001_ha->ccb_info[i].device = NULL;
		++pm8001_ha->tags_num;
	}
	return 0;

err_out_noccb:
	kfree(pm8001_ha->devices);
err_out:
	return -ENOMEM;
}

1233
static void pm8001_pci_remove(struct pci_dev *pdev)
J
jack wang 已提交
1234 1235 1236
{
	struct sas_ha_struct *sha = pci_get_drvdata(pdev);
	struct pm8001_hba_info *pm8001_ha;
1237
	int i, j;
J
jack wang 已提交
1238 1239 1240 1241
	pm8001_ha = sha->lldd_ha;
	sas_unregister_ha(sha);
	sas_remove_host(pm8001_ha->shost);
	list_del(&pm8001_ha->list);
1242
	PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
1243
	PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
J
jack wang 已提交
1244 1245 1246

#ifdef PM8001_USE_MSIX
	for (i = 0; i < pm8001_ha->number_of_intr; i++)
1247
		synchronize_irq(pci_irq_vector(pdev, i));
J
jack wang 已提交
1248
	for (i = 0; i < pm8001_ha->number_of_intr; i++)
1249 1250
		free_irq(pci_irq_vector(pdev, i), &pm8001_ha->irq_vector[i]);
	pci_free_irq_vectors(pdev);
J
jack wang 已提交
1251 1252 1253 1254
#else
	free_irq(pm8001_ha->irq, sha);
#endif
#ifdef PM8001_USE_TASKLET
1255
	/* For non-msix and msix interrupts */
1256 1257
	if ((!pdev->msix_cap || !pci_msi_enabled()) ||
	    (pm8001_ha->chip_id == chip_8001))
1258 1259 1260 1261
		tasklet_kill(&pm8001_ha->tasklet[0]);
	else
		for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
			tasklet_kill(&pm8001_ha->tasklet[j]);
J
jack wang 已提交
1262
#endif
1263
	scsi_host_put(pm8001_ha->shost);
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273

	for (i = 0; i < pm8001_ha->ccb_count; i++) {
		dma_free_coherent(&pm8001_ha->pdev->dev,
			sizeof(struct pm8001_prd) * PM8001_MAX_DMA_SG,
			pm8001_ha->ccb_info[i].buf_prd,
			pm8001_ha->ccb_info[i].ccb_dma_handle);
	}
	kfree(pm8001_ha->ccb_info);
	kfree(pm8001_ha->devices);

J
jack wang 已提交
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
	pm8001_free(pm8001_ha);
	kfree(sha->sas_phy);
	kfree(sha->sas_port);
	kfree(sha);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
}

/**
 * pm8001_pci_suspend - power management suspend main entry point
1284
 * @dev: Device struct
J
jack wang 已提交
1285
 *
1286
 * Return: 0 on success, anything else on error.
J
jack wang 已提交
1287
 */
1288
static int __maybe_unused pm8001_pci_suspend(struct device *dev)
J
jack wang 已提交
1289
{
1290
	struct pci_dev *pdev = to_pci_dev(dev);
J
jack wang 已提交
1291
	struct sas_ha_struct *sha = pci_get_drvdata(pdev);
1292
	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
1293
	int  i, j;
B
Bradley Grove 已提交
1294
	sas_suspend_ha(sha);
1295
	flush_workqueue(pm8001_wq);
J
jack wang 已提交
1296
	scsi_block_requests(pm8001_ha->shost);
1297
	if (!pdev->pm_cap) {
1298
		dev_err(dev, " PCI PM not supported\n");
J
jack wang 已提交
1299 1300
		return -ENODEV;
	}
1301
	PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
1302
	PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
J
jack wang 已提交
1303 1304
#ifdef PM8001_USE_MSIX
	for (i = 0; i < pm8001_ha->number_of_intr; i++)
1305
		synchronize_irq(pci_irq_vector(pdev, i));
J
jack wang 已提交
1306
	for (i = 0; i < pm8001_ha->number_of_intr; i++)
1307 1308
		free_irq(pci_irq_vector(pdev, i), &pm8001_ha->irq_vector[i]);
	pci_free_irq_vectors(pdev);
J
jack wang 已提交
1309 1310 1311 1312
#else
	free_irq(pm8001_ha->irq, sha);
#endif
#ifdef PM8001_USE_TASKLET
1313
	/* For non-msix and msix interrupts */
1314 1315
	if ((!pdev->msix_cap || !pci_msi_enabled()) ||
	    (pm8001_ha->chip_id == chip_8001))
1316 1317 1318 1319
		tasklet_kill(&pm8001_ha->tasklet[0]);
	else
		for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
			tasklet_kill(&pm8001_ha->tasklet[j]);
J
jack wang 已提交
1320
#endif
1321
	pm8001_info(pm8001_ha, "pdev=0x%p, slot=%s, entering "
1322 1323
		      "suspended state\n", pdev,
		      pm8001_ha->name);
J
jack wang 已提交
1324 1325 1326 1327 1328
	return 0;
}

/**
 * pm8001_pci_resume - power management resume main entry point
1329
 * @dev: Device struct
J
jack wang 已提交
1330
 *
1331
 * Return: 0 on success, anything else on error.
J
jack wang 已提交
1332
 */
1333
static int __maybe_unused pm8001_pci_resume(struct device *dev)
J
jack wang 已提交
1334
{
1335
	struct pci_dev *pdev = to_pci_dev(dev);
J
jack wang 已提交
1336 1337 1338
	struct sas_ha_struct *sha = pci_get_drvdata(pdev);
	struct pm8001_hba_info *pm8001_ha;
	int rc;
1339
	u8 i = 0, j;
J
jack wang 已提交
1340
	u32 device_state;
B
Bradley Grove 已提交
1341
	DECLARE_COMPLETION_ONSTACK(completion);
J
jack wang 已提交
1342 1343 1344
	pm8001_ha = sha->lldd_ha;
	device_state = pdev->current_state;

1345
	pm8001_info(pm8001_ha, "pdev=0x%p, slot=%s, resuming from previous operating state [D%d]\n",
1346
		      pdev, pm8001_ha->name, device_state);
J
jack wang 已提交
1347 1348 1349 1350

	rc = pci_go_44(pdev);
	if (rc)
		goto err_out_disable;
B
Bradley Grove 已提交
1351
	sas_prep_resume_ha(sha);
1352 1353 1354
	/* chip soft rst only for spc */
	if (pm8001_ha->chip_id == chip_8001) {
		PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
1355
		pm8001_dbg(pm8001_ha, INIT, "chip soft reset successful\n");
1356
	}
J
jack wang 已提交
1357 1358 1359
	rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
	if (rc)
		goto err_out_disable;
1360 1361 1362 1363

	/* disable all the interrupt bits */
	PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);

J
jack wang 已提交
1364 1365 1366
	rc = pm8001_request_irq(pm8001_ha);
	if (rc)
		goto err_out_disable;
1367
#ifdef PM8001_USE_TASKLET
1368
	/*  Tasklet for non msi-x interrupt handler */
1369 1370
	if ((!pdev->msix_cap || !pci_msi_enabled()) ||
	    (pm8001_ha->chip_id == chip_8001))
1371 1372 1373 1374 1375 1376
		tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
			(unsigned long)&(pm8001_ha->irq_vector[0]));
	else
		for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
			tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
				(unsigned long)&(pm8001_ha->irq_vector[j]));
1377
#endif
1378
	PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
1379 1380 1381 1382
	if (pm8001_ha->chip_id != chip_8001) {
		for (i = 1; i < pm8001_ha->number_of_intr; i++)
			PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
	}
1383 1384 1385

	/* Chip documentation for the 8070 and 8072 SPCv    */
	/* states that a 500ms minimum delay is required    */
J
Julia Lawall 已提交
1386
	/* before issuing commands. Otherwise, the firmware */
1387 1388 1389 1390 1391 1392 1393 1394 1395
	/* will enter an unrecoverable state.               */

	if (pm8001_ha->chip_id == chip_8070 ||
		pm8001_ha->chip_id == chip_8072) {
		mdelay(500);
	}

	/* Spin up the PHYs */

B
Bradley Grove 已提交
1396 1397 1398 1399 1400 1401 1402
	pm8001_ha->flags = PM8001F_RUN_TIME;
	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
		pm8001_ha->phy[i].enable_completion = &completion;
		PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
		wait_for_completion(&completion);
	}
	sas_resume_ha(sha);
J
jack wang 已提交
1403 1404 1405 1406
	return 0;

err_out_disable:
	scsi_remove_host(pm8001_ha->shost);
1407

J
jack wang 已提交
1408 1409 1410
	return rc;
}

1411 1412 1413
/* update of pci device, vendor id and driver data with
 * unique value for each of the controller
 */
1414
static struct pci_device_id pm8001_pci_table[] = {
1415
	{ PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 },
1416 1417
	{ PCI_VDEVICE(PMC_Sierra, 0x8006), chip_8006 },
	{ PCI_VDEVICE(ADAPTEC2, 0x8006), chip_8006 },
1418
	{ PCI_VDEVICE(ATTO, 0x0042), chip_8001 },
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
	/* Support for SPC/SPCv/SPCve controllers */
	{ PCI_VDEVICE(ADAPTEC2, 0x8001), chip_8001 },
	{ PCI_VDEVICE(PMC_Sierra, 0x8008), chip_8008 },
	{ PCI_VDEVICE(ADAPTEC2, 0x8008), chip_8008 },
	{ PCI_VDEVICE(PMC_Sierra, 0x8018), chip_8018 },
	{ PCI_VDEVICE(ADAPTEC2, 0x8018), chip_8018 },
	{ PCI_VDEVICE(PMC_Sierra, 0x8009), chip_8009 },
	{ PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 },
	{ PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 },
	{ PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 },
1429 1430 1431 1432 1433 1434
	{ PCI_VDEVICE(PMC_Sierra, 0x8074), chip_8074 },
	{ PCI_VDEVICE(ADAPTEC2, 0x8074), chip_8074 },
	{ PCI_VDEVICE(PMC_Sierra, 0x8076), chip_8076 },
	{ PCI_VDEVICE(ADAPTEC2, 0x8076), chip_8076 },
	{ PCI_VDEVICE(PMC_Sierra, 0x8077), chip_8077 },
	{ PCI_VDEVICE(ADAPTEC2, 0x8077), chip_8077 },
1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8081,
		PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8081,
		PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8001 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8088,
		PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8008 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8088,
		PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8008 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8089,
		PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8009 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8089,
		PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8009 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8088,
		PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8018 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8088,
		PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8018 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8089,
		PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8089,
		PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 },
1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8074,
		PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8074 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8076,
		PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8076 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8077,
		PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8077 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8074,
		PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8074 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8076,
		PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8076 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8077,
		PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8077 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8076,
		PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8076 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8077,
		PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8077 },
	{ PCI_VENDOR_ID_ADAPTEC2, 0x8074,
		PCI_VENDOR_ID_ADAPTEC2, 0x0404, 0, 0, chip_8074 },
1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486
	{ PCI_VENDOR_ID_ATTO, 0x8070,
		PCI_VENDOR_ID_ATTO, 0x0070, 0, 0, chip_8070 },
	{ PCI_VENDOR_ID_ATTO, 0x8070,
		PCI_VENDOR_ID_ATTO, 0x0071, 0, 0, chip_8070 },
	{ PCI_VENDOR_ID_ATTO, 0x8072,
		PCI_VENDOR_ID_ATTO, 0x0072, 0, 0, chip_8072 },
	{ PCI_VENDOR_ID_ATTO, 0x8072,
		PCI_VENDOR_ID_ATTO, 0x0073, 0, 0, chip_8072 },
	{ PCI_VENDOR_ID_ATTO, 0x8070,
		PCI_VENDOR_ID_ATTO, 0x0080, 0, 0, chip_8070 },
	{ PCI_VENDOR_ID_ATTO, 0x8072,
		PCI_VENDOR_ID_ATTO, 0x0081, 0, 0, chip_8072 },
	{ PCI_VENDOR_ID_ATTO, 0x8072,
		PCI_VENDOR_ID_ATTO, 0x0082, 0, 0, chip_8072 },
J
jack wang 已提交
1487 1488 1489
	{} /* terminate list */
};

1490 1491 1492 1493
static SIMPLE_DEV_PM_OPS(pm8001_pci_pm_ops,
			 pm8001_pci_suspend,
			 pm8001_pci_resume);

J
jack wang 已提交
1494 1495 1496 1497
static struct pci_driver pm8001_pci_driver = {
	.name		= DRV_NAME,
	.id_table	= pm8001_pci_table,
	.probe		= pm8001_pci_probe,
1498
	.remove		= pm8001_pci_remove,
1499
	.driver.pm	= &pm8001_pci_pm_ops,
J
jack wang 已提交
1500 1501 1502 1503 1504 1505 1506
};

/**
 *	pm8001_init - initialize scsi transport template
 */
static int __init pm8001_init(void)
{
1507 1508
	int rc = -ENOMEM;

1509
	pm8001_wq = alloc_workqueue("pm80xx", 0, 0);
1510 1511 1512
	if (!pm8001_wq)
		goto err;

J
jack wang 已提交
1513 1514 1515
	pm8001_id = 0;
	pm8001_stt = sas_domain_attach_transport(&pm8001_transport_ops);
	if (!pm8001_stt)
1516
		goto err_wq;
J
jack wang 已提交
1517 1518
	rc = pci_register_driver(&pm8001_pci_driver);
	if (rc)
1519
		goto err_tp;
J
jack wang 已提交
1520
	return 0;
1521 1522

err_tp:
J
jack wang 已提交
1523
	sas_release_transport(pm8001_stt);
1524 1525 1526
err_wq:
	destroy_workqueue(pm8001_wq);
err:
J
jack wang 已提交
1527 1528 1529 1530 1531 1532 1533
	return rc;
}

static void __exit pm8001_exit(void)
{
	pci_unregister_driver(&pm8001_pci_driver);
	sas_release_transport(pm8001_stt);
1534
	destroy_workqueue(pm8001_wq);
J
jack wang 已提交
1535 1536 1537 1538 1539 1540
}

module_init(pm8001_init);
module_exit(pm8001_exit);

MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>");
1541 1542
MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>");
MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>");
1543
MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>");
1544
MODULE_DESCRIPTION(
1545
		"PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077/8070/8072 "
1546
		"SAS/SATA controller driver");
J
jack wang 已提交
1547 1548 1549 1550
MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, pm8001_pci_table);