pm8001_init.c 45.1 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
 * 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_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,
130
	.lldd_port_formed	= pm8001_port_formed,
J
jack wang 已提交
131 132 133
};

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

/**
160 161
 * pm8001_free - free hba
 * @pm8001_ha:	our hba structure.
J
jack wang 已提交
162 163 164 165 166 167 168 169 170 171
 */
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) {
172
			dma_free_coherent(&pm8001_ha->pdev->dev,
173 174
				(pm8001_ha->memoryMap.region[i].total_len +
				pm8001_ha->memoryMap.region[i].alignment),
J
jack wang 已提交
175 176 177 178 179
				pm8001_ha->memoryMap.region[i].virt_ptr,
				pm8001_ha->memoryMap.region[i].phys_addr);
			}
	}
	PM8001_CHIP_DISP->chip_iounmap(pm8001_ha);
180
	flush_workqueue(pm8001_wq);
181
	bitmap_free(pm8001_ha->tags);
J
jack wang 已提交
182 183 184 185
	kfree(pm8001_ha);
}

#ifdef PM8001_USE_TASKLET
186 187

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

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

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

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

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

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

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

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

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

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

	count = pm8001_ha->max_q_num;
	/* Queues are chosen based on the number of cores/msix availability */
293
	ib_offset = pm8001_ha->ib_offset  = USI_MAX_MEMCNT_BASE;
294 295 296 297 298
	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;

299
	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
J
jack wang 已提交
300
		pm8001_phy_init(pm8001_ha, i);
301 302 303 304 305
		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 已提交
306 307 308 309 310 311 312 313 314 315 316 317 318

	/* 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;

319
	for (i = 0; i < count; i++) {
320 321
		ibq = &pm8001_ha->inbnd_q_tbl[i];
		spin_lock_init(&ibq->iq_lock);
322
		/* MPI Memory region 3 for consumer Index of inbound queues */
323 324 325 326
		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;
327 328 329

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

349
	for (i = 0; i < count; i++) {
350 351
		obq = &pm8001_ha->outbnd_q_tbl[i];
		spin_lock_init(&obq->oq_lock);
352
		/* MPI Memory region 4 for producer Index of outbound queues */
353 354 355 356
		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;
357 358 359

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

379
	}
J
jack wang 已提交
380 381 382 383 384
	/* 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;

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

388 389 390 391
	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;
392
	for (i = 0; i < pm8001_ha->max_memcnt; i++) {
J
Joe Perches 已提交
393 394
		struct mpi_mem *region = &pm8001_ha->memoryMap.region[i];

J
jack wang 已提交
395
		if (pm8001_mem_alloc(pm8001_ha->pdev,
J
Joe Perches 已提交
396 397 398 399 400 401 402 403
				     &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 已提交
404 405 406
		}
	}

407 408 409 410 411 412 413
	/* 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 已提交
414
	for (i = 0; i < PM8001_MAX_DEVICES; i++) {
415
		pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED;
J
jack wang 已提交
416 417
		pm8001_ha->devices[i].id = i;
		pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;
V
Viswas G 已提交
418
		atomic_set(&pm8001_ha->devices[i].running_req, 0);
J
jack wang 已提交
419 420 421 422 423
	}
	pm8001_ha->flags = PM8001F_INIT_TIME;
	/* Initialize tags */
	pm8001_tag_init(pm8001_ha);
	return 0;
424 425 426 427

err_out_nodev:
	for (i = 0; i < pm8001_ha->max_memcnt; i++) {
		if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) {
428
			dma_free_coherent(&pm8001_ha->pdev->dev,
429 430 431 432 433 434
				(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 已提交
435 436 437 438 439
err_out:
	return 1;
}

/**
440
 * pm8001_ioremap - remap the pci high physical address to kernel virtual
J
jack wang 已提交
441
 * address so that we can access them.
442
 * @pm8001_ha: our hba structure.
J
jack wang 已提交
443 444 445 446 447 448 449 450 451
 */
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)*/
452
	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
J
jack wang 已提交
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
		/*
		** 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);
471 472 473
			if (!pm8001_ha->io_mem[logicalBar].memvirtaddr) {
				pm8001_dbg(pm8001_ha, INIT,
					"Failed to ioremap bar %d, logicalBar %d",
474
				   bar, logicalBar);
475 476
				return -ENOMEM;
			}
477 478 479 480 481 482
			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 已提交
483 484 485
		} else {
			pm8001_ha->io_mem[logicalBar].membase	= 0;
			pm8001_ha->io_mem[logicalBar].memsize	= 0;
486
			pm8001_ha->io_mem[logicalBar].memvirtaddr = NULL;
J
jack wang 已提交
487 488 489 490 491 492 493 494 495 496 497 498
		}
		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.
 */
499
static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
500 501 502
				 const struct pci_device_id *ent,
				struct Scsi_Host *shost)

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

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

	pm8001_ha->pdev = pdev;
	pm8001_ha->dev = &pdev->dev;
514
	pm8001_ha->chip_id = ent->driver_data;
J
jack wang 已提交
515 516 517 518 519
	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++;
520
	pm8001_ha->logging_level = logging_level;
521
	pm8001_ha->non_fatal_count = 0;
522 523 524 525 526
	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;
527 528
		pm8001_dbg(pm8001_ha, FAIL,
			   "Setting link rate to default value\n");
529
	}
J
jack wang 已提交
530
	sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
531 532 533 534 535 536
	/* 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 已提交
537
#ifdef PM8001_USE_TASKLET
538
	/* Tasklet for non msi-x interrupt handler */
539 540
	if ((!pdev->msix_cap || !pci_msi_enabled())
	    || (pm8001_ha->chip_id == chip_8001))
541 542 543 544 545 546
		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 已提交
547
#endif
548 549
	if (pm8001_ioremap(pm8001_ha))
		goto failed_pci_alloc;
550
	if (!pm8001_alloc(pm8001_ha, ent))
J
jack wang 已提交
551
		return pm8001_ha;
552
failed_pci_alloc:
J
jack wang 已提交
553 554 555 556 557 558 559 560 561 562 563 564
	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;

565 566 567 568
	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 已提交
569 570 571 572 573 574 575 576 577 578 579
			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.
 */
580 581
static int pm8001_prep_sas_ha_init(struct Scsi_Host *shost,
				   const struct pm8001_chip_info *chip_info)
J
jack wang 已提交
582 583 584 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
{
	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.
 */
626 627
static void  pm8001_post_sas_ha_init(struct Scsi_Host *shost,
				     const struct pm8001_chip_info *chip_info)
J
jack wang 已提交
628 629 630 631 632 633 634 635 636
{
	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;
637 638
		sha->sas_phy[i]->sas_addr =
			(u8 *)&pm8001_ha->phy[i].dev_sas_addr;
J
jack wang 已提交
639 640 641
	}
	sha->sas_ha_name = DRV_NAME;
	sha->dev = pm8001_ha->dev;
642
	sha->strict_wide_ports = 1;
J
jack wang 已提交
643 644 645 646 647 648 649 650
	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
651
 * @pm8001_ha: our ha struct.
J
jack wang 已提交
652
 *
653
 * Currently we just set the fixed SAS address to our HBA, for manufacture,
J
jack wang 已提交
654 655 656 657
 * it should read from the EEPROM
 */
static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
{
658
	u8 i, j;
659
	u8 sas_add[8];
J
jack wang 已提交
660
#ifdef PM8001_READ_VPD
661 662 663 664
	/* 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 已提交
665
	DECLARE_COMPLETION_ONSTACK(completion);
666
	struct pm8001_ioctl_payload payload;
667
	u16 deviceid;
668 669
	int rc;

670
	pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
J
jack wang 已提交
671
	pm8001_ha->nvmd_completion = &completion;
672 673

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

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

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

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

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

778 779 780 781 782 783 784 785 786 787 788 789 790
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;
};

/**
791
 * pm8001_get_internal_phy_settings - Retrieves the internal PHY settings
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
 * @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;
}

/**
811
 * pm8001_get_external_phy_settings - Retrieves the external PHY settings
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
 * @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;
}

/**
831
 * pm8001_get_phy_mask - Retrieves the mask that denotes if a PHY is int/ext
832 833 834 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
 * @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:
862 863 864
		pm8001_dbg(pm8001_ha, INIT,
			   "Unknown subsystem device=0x%.04x\n",
			   pm8001_ha->pdev->subsystem_device);
865 866 867 868
	}
}

/**
869
 * pm8001_set_phy_settings_ven_117c_12G() - Configure ATTO 12Gb PHY settings
870 871 872 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
 * @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;
}

903
/**
904
 * pm8001_configure_phy_settings - Configures PHY settings based on vendor ID.
905 906 907 908 909 910
 * @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:
911 912 913 914 915
		if (pm8001_ha->pdev->device == 0x0042) /* 6Gb */
			return 0;
		else
			return pm8001_set_phy_settings_ven_117c_12G(pm8001_ha);

916 917 918 919 920 921 922 923 924
	case PCI_VENDOR_ID_ADAPTEC2:
	case 0:
		return 0;

	default:
		return pm8001_get_phy_settings_info(pm8001_ha);
	}
}

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

	/* 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;
	}

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

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

955 956 957
	/* Maximum queue number updating in HBA structure */
	pm8001_ha->max_q_num = number_of_intr;

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

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

970 971 972
	if (pm8001_ha->chip_id != chip_8001)
		flag &= ~IRQF_SHARED;

973 974 975
	pm8001_dbg(pm8001_ha, INIT,
		   "pci_enable_msix request number of intr %d\n",
		   pm8001_ha->number_of_intr);
976

977 978 979 980
	if (nr_irqs > ARRAY_SIZE(pm8001_ha->intr_drvname))
		nr_irqs = ARRAY_SIZE(pm8001_ha->intr_drvname);

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

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

J
jack wang 已提交
1001 1002 1003 1004
	return rc;
}
#endif

1005 1006 1007 1008 1009 1010 1011 1012 1013
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);
1014
	pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n");
1015 1016 1017 1018
#endif
	return 0;
}

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

	pdev = pm8001_ha->pdev;

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

intx:
1040
	/* initialize the INT-X interrupt */
1041 1042
	pm8001_ha->irq_vector[0].irq_id = 0;
	pm8001_ha->irq_vector[0].drv_inst = pm8001_ha;
1043
	rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
1044
		pm8001_ha->name, SHOST_TO_SAS_HA(pm8001_ha->shost));
J
jack wang 已提交
1045 1046 1047 1048 1049 1050 1051 1052 1053
	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
1054 1055
 * pci driver it is invoked, all struct and hardware initialization should be
 * done here, also, register interrupt.
J
jack wang 已提交
1056
 */
1057 1058
static int pm8001_pci_probe(struct pci_dev *pdev,
			    const struct pci_device_id *ent)
J
jack wang 已提交
1059 1060 1061
{
	unsigned int rc;
	u32	pci_reg;
1062
	u8	i = 0;
J
jack wang 已提交
1063 1064 1065
	struct pm8001_hba_info *pm8001_ha;
	struct Scsi_Host *shost = NULL;
	const struct pm8001_chip_info *chip;
1066
	struct sas_ha_struct *sha;
J
jack wang 已提交
1067 1068

	dev_printk(KERN_INFO, &pdev->dev,
1069
		"pm80xx: driver version %s\n", DRV_VERSION);
J
jack wang 已提交
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
	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];
1095 1096
	sha = kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
	if (!sha) {
J
jack wang 已提交
1097 1098 1099
		rc = -ENOMEM;
		goto err_out_free_host;
	}
1100
	SHOST_TO_SAS_HA(shost) = sha;
J
jack wang 已提交
1101 1102 1103 1104 1105 1106 1107

	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));
1108 1109
	/* ent->driver variable is used to differentiate between controllers */
	pm8001_ha = pm8001_pci_alloc(pdev, ent, shost);
J
jack wang 已提交
1110 1111 1112 1113
	if (!pm8001_ha) {
		rc = -ENOMEM;
		goto err_out_free;
	}
1114

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

1123 1124 1125 1126
	rc = pm8001_init_ccb_tag(pm8001_ha, shost, pdev);
	if (rc)
		goto err_out_enable;

J
jack wang 已提交
1127 1128 1129 1130
	rc = scsi_add_host(shost, &pdev->dev);
	if (rc)
		goto err_out_ha_free;

1131
	PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
1132 1133 1134
	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);
1135 1136
		/* setup thermal configuration. */
		pm80xx_set_thermal_config(pm8001_ha);
1137 1138
	}

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

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

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

1173
/**
1174 1175 1176
 * pm8001_init_ccb_tag - allocate memory to CCB and tag.
 * @pm8001_ha: our hba card information.
 * @shost: scsi host which has been allocated outside.
1177
 * @pdev: pci device.
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
 */
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;

1194
	pm8001_ha->tags = bitmap_zalloc(ccb_count, GFP_KERNEL);
1195 1196 1197 1198
	if (!pm8001_ha->tags)
		goto err_out;

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

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

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

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

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

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

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

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

J
jack wang 已提交
1361 1362 1363
	rc = pm8001_request_irq(pm8001_ha);
	if (rc)
		goto err_out_disable;
1364
#ifdef PM8001_USE_TASKLET
1365
	/*  Tasklet for non msi-x interrupt handler */
1366 1367
	if ((!pdev->msix_cap || !pci_msi_enabled()) ||
	    (pm8001_ha->chip_id == chip_8001))
1368 1369 1370 1371 1372 1373
		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]));
1374
#endif
1375
	PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
1376 1377 1378 1379
	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);
	}
1380 1381 1382

	/* Chip documentation for the 8070 and 8072 SPCv    */
	/* states that a 500ms minimum delay is required    */
J
Julia Lawall 已提交
1383
	/* before issuing commands. Otherwise, the firmware */
1384 1385 1386 1387 1388 1389 1390 1391 1392
	/* 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 已提交
1393 1394 1395 1396 1397 1398 1399
	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 已提交
1400 1401 1402 1403
	return 0;

err_out_disable:
	scsi_remove_host(pm8001_ha->shost);
1404

J
jack wang 已提交
1405 1406 1407
	return rc;
}

1408 1409 1410
/* update of pci device, vendor id and driver data with
 * unique value for each of the controller
 */
1411
static struct pci_device_id pm8001_pci_table[] = {
1412
	{ PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 },
1413 1414
	{ PCI_VDEVICE(PMC_Sierra, 0x8006), chip_8006 },
	{ PCI_VDEVICE(ADAPTEC2, 0x8006), chip_8006 },
1415
	{ PCI_VDEVICE(ATTO, 0x0042), chip_8001 },
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
	/* 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 },
1426 1427 1428 1429 1430 1431
	{ 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 },
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451
	{ 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 },
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
	{ 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 },
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
	{ 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 已提交
1484 1485 1486
	{} /* terminate list */
};

1487 1488 1489 1490
static SIMPLE_DEV_PM_OPS(pm8001_pci_pm_ops,
			 pm8001_pci_suspend,
			 pm8001_pci_resume);

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

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

1506
	pm8001_wq = alloc_workqueue("pm80xx", 0, 0);
1507 1508 1509
	if (!pm8001_wq)
		goto err;

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

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

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

module_init(pm8001_init);
module_exit(pm8001_exit);

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