aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pm8001/pm8001_init.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-11 18:24:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-11 18:24:22 -0400
commit4c4445013f792f82855079ac377bf5d75af4581c (patch)
treefbdc80d7bd7cf3c40f85048b6f5e9c1357ca50d6 /drivers/scsi/pm8001/pm8001_init.c
parentac4e01093f6d7b051c5d6a3e61ea5337774ac36a (diff)
parent297b8a07347555f0d2fafa4a1ddfc332d2d4afa9 (diff)
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull second SCSI update from James "Jaj B" Bottomley: "This is the final round of SCSI patches for the merge window. It consists mostly of driver updates (bnx2fc, ibmfc, fnic, lpfc, be2iscsi, pm80xx, qla4x and ipr). There's also the power management updates that complete the patches in Jens' tree, an iscsi refcounting problem fix from the last pull, some dif handling in scsi_debug fixes, a few nice code cleanups and an error handling busy bug fix." * tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (92 commits) [SCSI] qla2xxx: Update firmware link in Kconfig file. [SCSI] iscsi class, qla4xxx: fix sess/conn refcounting when find fns are used [SCSI] sas: unify the pointlessly separated enums sas_dev_type and sas_device_type [SCSI] pm80xx: thermal, sas controller config and error handling update [SCSI] pm80xx: NCQ error handling changes [SCSI] pm80xx: WWN Modification for PM8081/88/89 controllers [SCSI] pm80xx: Changed module name and debug messages update [SCSI] pm80xx: Firmware flash memory free fix, with addition of new memory region for it [SCSI] pm80xx: SPC new firmware changes for device id 0x8081 alone [SCSI] pm80xx: Added SPCv/ve specific hardware functionalities and relevant changes in common files [SCSI] pm80xx: MSI-X implementation for using 64 interrupts [SCSI] pm80xx: Updated common functions common for SPC and SPCv/ve [SCSI] pm80xx: Multiple inbound/outbound queue configuration [SCSI] pm80xx: Added SPCv/ve specific ids, variables and modify for SPC [SCSI] lpfc: fix up Kconfig dependencies [SCSI] Handle MLQUEUE busy response in scsi_send_eh_cmnd [SCSI] sd: change to auto suspend mode [SCSI] sd: use REQ_PM in sd's runtime suspend operation [SCSI] qla4xxx: Fix iocb_cnt calculation in qla4xxx_send_mbox_iocb() [SCSI] ufs: Correct the expected data transfersize ...
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_init.c')
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c383
1 files changed, 295 insertions, 88 deletions
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 3d5e522e00fc..e4b9bc7f5410 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver 2 * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver
3 * 3 *
4 * Copyright (c) 2008-2009 USI Co., Ltd. 4 * Copyright (c) 2008-2009 USI Co., Ltd.
5 * All rights reserved. 5 * All rights reserved.
@@ -44,8 +44,16 @@
44 44
45static struct scsi_transport_template *pm8001_stt; 45static struct scsi_transport_template *pm8001_stt;
46 46
47/**
48 * chip info structure to identify chip key functionality as
49 * encryption available/not, no of ports, hw specific function ref
50 */
47static const struct pm8001_chip_info pm8001_chips[] = { 51static const struct pm8001_chip_info pm8001_chips[] = {
48 [chip_8001] = { 8, &pm8001_8001_dispatch,}, 52 [chip_8001] = {0, 8, &pm8001_8001_dispatch,},
53 [chip_8008] = {0, 8, &pm8001_80xx_dispatch,},
54 [chip_8009] = {1, 8, &pm8001_80xx_dispatch,},
55 [chip_8018] = {0, 16, &pm8001_80xx_dispatch,},
56 [chip_8019] = {1, 16, &pm8001_80xx_dispatch,},
49}; 57};
50static int pm8001_id; 58static int pm8001_id;
51 59
@@ -155,37 +163,75 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
155} 163}
156 164
157#ifdef PM8001_USE_TASKLET 165#ifdef PM8001_USE_TASKLET
166
167/**
168 * tasklet for 64 msi-x interrupt handler
169 * @opaque: the passed general host adapter struct
170 * Note: pm8001_tasklet is common for pm8001 & pm80xx
171 */
158static void pm8001_tasklet(unsigned long opaque) 172static void pm8001_tasklet(unsigned long opaque)
159{ 173{
160 struct pm8001_hba_info *pm8001_ha; 174 struct pm8001_hba_info *pm8001_ha;
175 u32 vec;
161 pm8001_ha = (struct pm8001_hba_info *)opaque; 176 pm8001_ha = (struct pm8001_hba_info *)opaque;
162 if (unlikely(!pm8001_ha)) 177 if (unlikely(!pm8001_ha))
163 BUG_ON(1); 178 BUG_ON(1);
164 PM8001_CHIP_DISP->isr(pm8001_ha); 179 vec = pm8001_ha->int_vector;
180 PM8001_CHIP_DISP->isr(pm8001_ha, vec);
181}
182#endif
183
184static struct pm8001_hba_info *outq_to_hba(u8 *outq)
185{
186 return container_of((outq - *outq), struct pm8001_hba_info, outq[0]);
165} 187}
188
189/**
190 * pm8001_interrupt_handler_msix - main MSIX interrupt handler.
191 * It obtains the vector number and calls the equivalent bottom
192 * half or services directly.
193 * @opaque: the passed outbound queue/vector. Host structure is
194 * retrieved from the same.
195 */
196static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
197{
198 struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque);
199 u8 outq = *(u8 *)opaque;
200 irqreturn_t ret = IRQ_HANDLED;
201 if (unlikely(!pm8001_ha))
202 return IRQ_NONE;
203 if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
204 return IRQ_NONE;
205 pm8001_ha->int_vector = outq;
206#ifdef PM8001_USE_TASKLET
207 tasklet_schedule(&pm8001_ha->tasklet);
208#else
209 ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq);
166#endif 210#endif
211 return ret;
212}
167 213
214/**
215 * pm8001_interrupt_handler_intx - main INTx interrupt handler.
216 * @dev_id: sas_ha structure. The HBA is retrieved from sas_has structure.
217 */
168 218
169 /** 219static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
170 * pm8001_interrupt - when HBA originate a interrupt,we should invoke this
171 * dispatcher to handle each case.
172 * @irq: irq number.
173 * @opaque: the passed general host adapter struct
174 */
175static irqreturn_t pm8001_interrupt(int irq, void *opaque)
176{ 220{
177 struct pm8001_hba_info *pm8001_ha; 221 struct pm8001_hba_info *pm8001_ha;
178 irqreturn_t ret = IRQ_HANDLED; 222 irqreturn_t ret = IRQ_HANDLED;
179 struct sas_ha_struct *sha = opaque; 223 struct sas_ha_struct *sha = dev_id;
180 pm8001_ha = sha->lldd_ha; 224 pm8001_ha = sha->lldd_ha;
181 if (unlikely(!pm8001_ha)) 225 if (unlikely(!pm8001_ha))
182 return IRQ_NONE; 226 return IRQ_NONE;
183 if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) 227 if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
184 return IRQ_NONE; 228 return IRQ_NONE;
229
230 pm8001_ha->int_vector = 0;
185#ifdef PM8001_USE_TASKLET 231#ifdef PM8001_USE_TASKLET
186 tasklet_schedule(&pm8001_ha->tasklet); 232 tasklet_schedule(&pm8001_ha->tasklet);
187#else 233#else
188 ret = PM8001_CHIP_DISP->isr(pm8001_ha); 234 ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
189#endif 235#endif
190 return ret; 236 return ret;
191} 237}
@@ -195,10 +241,14 @@ static irqreturn_t pm8001_interrupt(int irq, void *opaque)
195 * @pm8001_ha:our hba structure. 241 * @pm8001_ha:our hba structure.
196 * 242 *
197 */ 243 */
198static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha) 244static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
245 const struct pci_device_id *ent)
199{ 246{
200 int i; 247 int i;
201 spin_lock_init(&pm8001_ha->lock); 248 spin_lock_init(&pm8001_ha->lock);
249 PM8001_INIT_DBG(pm8001_ha,
250 pm8001_printk("pm8001_alloc: PHY:%x\n",
251 pm8001_ha->chip->n_phy));
202 for (i = 0; i < pm8001_ha->chip->n_phy; i++) { 252 for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
203 pm8001_phy_init(pm8001_ha, i); 253 pm8001_phy_init(pm8001_ha, i);
204 pm8001_ha->port[i].wide_port_phymap = 0; 254 pm8001_ha->port[i].wide_port_phymap = 0;
@@ -222,30 +272,57 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
222 pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE; 272 pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE;
223 pm8001_ha->memoryMap.region[IOP].alignment = 32; 273 pm8001_ha->memoryMap.region[IOP].alignment = 32;
224 274
225 /* MPI Memory region 3 for consumer Index of inbound queues */ 275 for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
226 pm8001_ha->memoryMap.region[CI].num_elements = 1; 276 /* MPI Memory region 3 for consumer Index of inbound queues */
227 pm8001_ha->memoryMap.region[CI].element_size = 4; 277 pm8001_ha->memoryMap.region[CI+i].num_elements = 1;
228 pm8001_ha->memoryMap.region[CI].total_len = 4; 278 pm8001_ha->memoryMap.region[CI+i].element_size = 4;
229 pm8001_ha->memoryMap.region[CI].alignment = 4; 279 pm8001_ha->memoryMap.region[CI+i].total_len = 4;
230 280 pm8001_ha->memoryMap.region[CI+i].alignment = 4;
231 /* MPI Memory region 4 for producer Index of outbound queues */ 281
232 pm8001_ha->memoryMap.region[PI].num_elements = 1; 282 if ((ent->driver_data) != chip_8001) {
233 pm8001_ha->memoryMap.region[PI].element_size = 4; 283 /* MPI Memory region 5 inbound queues */
234 pm8001_ha->memoryMap.region[PI].total_len = 4; 284 pm8001_ha->memoryMap.region[IB+i].num_elements =
235 pm8001_ha->memoryMap.region[PI].alignment = 4; 285 PM8001_MPI_QUEUE;
236 286 pm8001_ha->memoryMap.region[IB+i].element_size = 128;
237 /* MPI Memory region 5 inbound queues */ 287 pm8001_ha->memoryMap.region[IB+i].total_len =
238 pm8001_ha->memoryMap.region[IB].num_elements = PM8001_MPI_QUEUE; 288 PM8001_MPI_QUEUE * 128;
239 pm8001_ha->memoryMap.region[IB].element_size = 64; 289 pm8001_ha->memoryMap.region[IB+i].alignment = 128;
240 pm8001_ha->memoryMap.region[IB].total_len = PM8001_MPI_QUEUE * 64; 290 } else {
241 pm8001_ha->memoryMap.region[IB].alignment = 64; 291 pm8001_ha->memoryMap.region[IB+i].num_elements =
242 292 PM8001_MPI_QUEUE;
243 /* MPI Memory region 6 outbound queues */ 293 pm8001_ha->memoryMap.region[IB+i].element_size = 64;
244 pm8001_ha->memoryMap.region[OB].num_elements = PM8001_MPI_QUEUE; 294 pm8001_ha->memoryMap.region[IB+i].total_len =
245 pm8001_ha->memoryMap.region[OB].element_size = 64; 295 PM8001_MPI_QUEUE * 64;
246 pm8001_ha->memoryMap.region[OB].total_len = PM8001_MPI_QUEUE * 64; 296 pm8001_ha->memoryMap.region[IB+i].alignment = 64;
247 pm8001_ha->memoryMap.region[OB].alignment = 64; 297 }
298 }
299
300 for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
301 /* MPI Memory region 4 for producer Index of outbound queues */
302 pm8001_ha->memoryMap.region[PI+i].num_elements = 1;
303 pm8001_ha->memoryMap.region[PI+i].element_size = 4;
304 pm8001_ha->memoryMap.region[PI+i].total_len = 4;
305 pm8001_ha->memoryMap.region[PI+i].alignment = 4;
306
307 if (ent->driver_data != chip_8001) {
308 /* MPI Memory region 6 Outbound queues */
309 pm8001_ha->memoryMap.region[OB+i].num_elements =
310 PM8001_MPI_QUEUE;
311 pm8001_ha->memoryMap.region[OB+i].element_size = 128;
312 pm8001_ha->memoryMap.region[OB+i].total_len =
313 PM8001_MPI_QUEUE * 128;
314 pm8001_ha->memoryMap.region[OB+i].alignment = 128;
315 } else {
316 /* MPI Memory region 6 Outbound queues */
317 pm8001_ha->memoryMap.region[OB+i].num_elements =
318 PM8001_MPI_QUEUE;
319 pm8001_ha->memoryMap.region[OB+i].element_size = 64;
320 pm8001_ha->memoryMap.region[OB+i].total_len =
321 PM8001_MPI_QUEUE * 64;
322 pm8001_ha->memoryMap.region[OB+i].alignment = 64;
323 }
248 324
325 }
249 /* Memory region write DMA*/ 326 /* Memory region write DMA*/
250 pm8001_ha->memoryMap.region[NVMD].num_elements = 1; 327 pm8001_ha->memoryMap.region[NVMD].num_elements = 1;
251 pm8001_ha->memoryMap.region[NVMD].element_size = 4096; 328 pm8001_ha->memoryMap.region[NVMD].element_size = 4096;
@@ -264,6 +341,9 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
264 pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB * 341 pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB *
265 sizeof(struct pm8001_ccb_info); 342 sizeof(struct pm8001_ccb_info);
266 343
344 /* Memory region for fw flash */
345 pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096;
346
267 for (i = 0; i < USI_MAX_MEMCNT; i++) { 347 for (i = 0; i < USI_MAX_MEMCNT; i++) {
268 if (pm8001_mem_alloc(pm8001_ha->pdev, 348 if (pm8001_mem_alloc(pm8001_ha->pdev,
269 &pm8001_ha->memoryMap.region[i].virt_ptr, 349 &pm8001_ha->memoryMap.region[i].virt_ptr,
@@ -281,7 +361,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
281 361
282 pm8001_ha->devices = pm8001_ha->memoryMap.region[DEV_MEM].virt_ptr; 362 pm8001_ha->devices = pm8001_ha->memoryMap.region[DEV_MEM].virt_ptr;
283 for (i = 0; i < PM8001_MAX_DEVICES; i++) { 363 for (i = 0; i < PM8001_MAX_DEVICES; i++) {
284 pm8001_ha->devices[i].dev_type = NO_DEVICE; 364 pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED;
285 pm8001_ha->devices[i].id = i; 365 pm8001_ha->devices[i].id = i;
286 pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES; 366 pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;
287 pm8001_ha->devices[i].running_req = 0; 367 pm8001_ha->devices[i].running_req = 0;
@@ -339,10 +419,12 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
339 ioremap(pm8001_ha->io_mem[logicalBar].membase, 419 ioremap(pm8001_ha->io_mem[logicalBar].membase,
340 pm8001_ha->io_mem[logicalBar].memsize); 420 pm8001_ha->io_mem[logicalBar].memsize);
341 PM8001_INIT_DBG(pm8001_ha, 421 PM8001_INIT_DBG(pm8001_ha,
342 pm8001_printk("PCI: bar %d, logicalBar %d " 422 pm8001_printk("PCI: bar %d, logicalBar %d ",
343 "virt_addr=%lx,len=%d\n", bar, logicalBar, 423 bar, logicalBar));
344 (unsigned long) 424 PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
345 pm8001_ha->io_mem[logicalBar].memvirtaddr, 425 "base addr %llx virt_addr=%llx len=%d\n",
426 (u64)pm8001_ha->io_mem[logicalBar].membase,
427 (u64)pm8001_ha->io_mem[logicalBar].memvirtaddr,
346 pm8001_ha->io_mem[logicalBar].memsize)); 428 pm8001_ha->io_mem[logicalBar].memsize));
347 } else { 429 } else {
348 pm8001_ha->io_mem[logicalBar].membase = 0; 430 pm8001_ha->io_mem[logicalBar].membase = 0;
@@ -361,8 +443,9 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
361 * @shost: scsi host struct which has been initialized before. 443 * @shost: scsi host struct which has been initialized before.
362 */ 444 */
363static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, 445static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
364 u32 chip_id, 446 const struct pci_device_id *ent,
365 struct Scsi_Host *shost) 447 struct Scsi_Host *shost)
448
366{ 449{
367 struct pm8001_hba_info *pm8001_ha; 450 struct pm8001_hba_info *pm8001_ha;
368 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 451 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
@@ -374,7 +457,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
374 457
375 pm8001_ha->pdev = pdev; 458 pm8001_ha->pdev = pdev;
376 pm8001_ha->dev = &pdev->dev; 459 pm8001_ha->dev = &pdev->dev;
377 pm8001_ha->chip_id = chip_id; 460 pm8001_ha->chip_id = ent->driver_data;
378 pm8001_ha->chip = &pm8001_chips[pm8001_ha->chip_id]; 461 pm8001_ha->chip = &pm8001_chips[pm8001_ha->chip_id];
379 pm8001_ha->irq = pdev->irq; 462 pm8001_ha->irq = pdev->irq;
380 pm8001_ha->sas = sha; 463 pm8001_ha->sas = sha;
@@ -382,12 +465,22 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
382 pm8001_ha->id = pm8001_id++; 465 pm8001_ha->id = pm8001_id++;
383 pm8001_ha->logging_level = 0x01; 466 pm8001_ha->logging_level = 0x01;
384 sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id); 467 sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
468 /* IOMB size is 128 for 8088/89 controllers */
469 if (pm8001_ha->chip_id != chip_8001)
470 pm8001_ha->iomb_size = IOMB_SIZE_SPCV;
471 else
472 pm8001_ha->iomb_size = IOMB_SIZE_SPC;
473
385#ifdef PM8001_USE_TASKLET 474#ifdef PM8001_USE_TASKLET
475 /**
476 * default tasklet for non msi-x interrupt handler/first msi-x
477 * interrupt handler
478 **/
386 tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, 479 tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
387 (unsigned long)pm8001_ha); 480 (unsigned long)pm8001_ha);
388#endif 481#endif
389 pm8001_ioremap(pm8001_ha); 482 pm8001_ioremap(pm8001_ha);
390 if (!pm8001_alloc(pm8001_ha)) 483 if (!pm8001_alloc(pm8001_ha, ent))
391 return pm8001_ha; 484 return pm8001_ha;
392 pm8001_free(pm8001_ha); 485 pm8001_free(pm8001_ha);
393 return NULL; 486 return NULL;
@@ -512,21 +605,50 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost,
512 */ 605 */
513static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) 606static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
514{ 607{
515 u8 i; 608 u8 i, j;
516#ifdef PM8001_READ_VPD 609#ifdef PM8001_READ_VPD
610 /* For new SPC controllers WWN is stored in flash vpd
611 * For SPC/SPCve controllers WWN is stored in EEPROM
612 * For Older SPC WWN is stored in NVMD
613 */
517 DECLARE_COMPLETION_ONSTACK(completion); 614 DECLARE_COMPLETION_ONSTACK(completion);
518 struct pm8001_ioctl_payload payload; 615 struct pm8001_ioctl_payload payload;
616 u16 deviceid;
617 pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
519 pm8001_ha->nvmd_completion = &completion; 618 pm8001_ha->nvmd_completion = &completion;
520 payload.minor_function = 0; 619
521 payload.length = 128; 620 if (pm8001_ha->chip_id == chip_8001) {
522 payload.func_specific = kzalloc(128, GFP_KERNEL); 621 if (deviceid == 0x8081) {
622 payload.minor_function = 4;
623 payload.length = 4096;
624 } else {
625 payload.minor_function = 0;
626 payload.length = 128;
627 }
628 } else {
629 payload.minor_function = 1;
630 payload.length = 4096;
631 }
632 payload.offset = 0;
633 payload.func_specific = kzalloc(payload.length, GFP_KERNEL);
523 PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); 634 PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
524 wait_for_completion(&completion); 635 wait_for_completion(&completion);
636
637 for (i = 0, j = 0; i <= 7; i++, j++) {
638 if (pm8001_ha->chip_id == chip_8001) {
639 if (deviceid == 0x8081)
640 pm8001_ha->sas_addr[j] =
641 payload.func_specific[0x704 + i];
642 } else
643 pm8001_ha->sas_addr[j] =
644 payload.func_specific[0x804 + i];
645 }
646
525 for (i = 0; i < pm8001_ha->chip->n_phy; i++) { 647 for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
526 memcpy(&pm8001_ha->phy[i].dev_sas_addr, pm8001_ha->sas_addr, 648 memcpy(&pm8001_ha->phy[i].dev_sas_addr,
527 SAS_ADDR_SIZE); 649 pm8001_ha->sas_addr, SAS_ADDR_SIZE);
528 PM8001_INIT_DBG(pm8001_ha, 650 PM8001_INIT_DBG(pm8001_ha,
529 pm8001_printk("phy %d sas_addr = %016llx \n", i, 651 pm8001_printk("phy %d sas_addr = %016llx\n", i,
530 pm8001_ha->phy[i].dev_sas_addr)); 652 pm8001_ha->phy[i].dev_sas_addr));
531 } 653 }
532#else 654#else
@@ -547,31 +669,50 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
547 * @chip_info: our ha struct. 669 * @chip_info: our ha struct.
548 * @irq_handler: irq_handler 670 * @irq_handler: irq_handler
549 */ 671 */
550static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha, 672static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
551 irq_handler_t irq_handler)
552{ 673{
553 u32 i = 0, j = 0; 674 u32 i = 0, j = 0;
554 u32 number_of_intr = 1; 675 u32 number_of_intr;
555 int flag = 0; 676 int flag = 0;
556 u32 max_entry; 677 u32 max_entry;
557 int rc; 678 int rc;
679 static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3];
680
681 /* SPCv controllers supports 64 msi-x */
682 if (pm8001_ha->chip_id == chip_8001) {
683 number_of_intr = 1;
684 flag |= IRQF_DISABLED;
685 } else {
686 number_of_intr = PM8001_MAX_MSIX_VEC;
687 flag &= ~IRQF_SHARED;
688 flag |= IRQF_DISABLED;
689 }
690
558 max_entry = sizeof(pm8001_ha->msix_entries) / 691 max_entry = sizeof(pm8001_ha->msix_entries) /
559 sizeof(pm8001_ha->msix_entries[0]); 692 sizeof(pm8001_ha->msix_entries[0]);
560 flag |= IRQF_DISABLED;
561 for (i = 0; i < max_entry ; i++) 693 for (i = 0; i < max_entry ; i++)
562 pm8001_ha->msix_entries[i].entry = i; 694 pm8001_ha->msix_entries[i].entry = i;
563 rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries, 695 rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries,
564 number_of_intr); 696 number_of_intr);
565 pm8001_ha->number_of_intr = number_of_intr; 697 pm8001_ha->number_of_intr = number_of_intr;
566 if (!rc) { 698 if (!rc) {
699 PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
700 "pci_enable_msix request ret:%d no of intr %d\n",
701 rc, pm8001_ha->number_of_intr));
702
703 for (i = 0; i < number_of_intr; i++)
704 pm8001_ha->outq[i] = i;
705
567 for (i = 0; i < number_of_intr; i++) { 706 for (i = 0; i < number_of_intr; i++) {
707 snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
708 DRV_NAME"%d", i);
568 if (request_irq(pm8001_ha->msix_entries[i].vector, 709 if (request_irq(pm8001_ha->msix_entries[i].vector,
569 irq_handler, flag, DRV_NAME, 710 pm8001_interrupt_handler_msix, flag,
570 SHOST_TO_SAS_HA(pm8001_ha->shost))) { 711 intr_drvname[i], &pm8001_ha->outq[i])) {
571 for (j = 0; j < i; j++) 712 for (j = 0; j < i; j++)
572 free_irq( 713 free_irq(
573 pm8001_ha->msix_entries[j].vector, 714 pm8001_ha->msix_entries[j].vector,
574 SHOST_TO_SAS_HA(pm8001_ha->shost)); 715 &pm8001_ha->outq[j]);
575 pci_disable_msix(pm8001_ha->pdev); 716 pci_disable_msix(pm8001_ha->pdev);
576 break; 717 break;
577 } 718 }
@@ -588,22 +729,24 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha,
588static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) 729static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
589{ 730{
590 struct pci_dev *pdev; 731 struct pci_dev *pdev;
591 irq_handler_t irq_handler = pm8001_interrupt;
592 int rc; 732 int rc;
593 733
594 pdev = pm8001_ha->pdev; 734 pdev = pm8001_ha->pdev;
595 735
596#ifdef PM8001_USE_MSIX 736#ifdef PM8001_USE_MSIX
597 if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) 737 if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
598 return pm8001_setup_msix(pm8001_ha, irq_handler); 738 return pm8001_setup_msix(pm8001_ha);
599 else 739 else {
740 PM8001_INIT_DBG(pm8001_ha,
741 pm8001_printk("MSIX not supported!!!\n"));
600 goto intx; 742 goto intx;
743 }
601#endif 744#endif
602 745
603intx: 746intx:
604 /* initialize the INT-X interrupt */ 747 /* initialize the INT-X interrupt */
605 rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, DRV_NAME, 748 rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
606 SHOST_TO_SAS_HA(pm8001_ha->shost)); 749 DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost));
607 return rc; 750 return rc;
608} 751}
609 752
@@ -621,12 +764,13 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
621{ 764{
622 unsigned int rc; 765 unsigned int rc;
623 u32 pci_reg; 766 u32 pci_reg;
767 u8 i = 0;
624 struct pm8001_hba_info *pm8001_ha; 768 struct pm8001_hba_info *pm8001_ha;
625 struct Scsi_Host *shost = NULL; 769 struct Scsi_Host *shost = NULL;
626 const struct pm8001_chip_info *chip; 770 const struct pm8001_chip_info *chip;
627 771
628 dev_printk(KERN_INFO, &pdev->dev, 772 dev_printk(KERN_INFO, &pdev->dev,
629 "pm8001: driver version %s\n", DRV_VERSION); 773 "pm80xx: driver version %s\n", DRV_VERSION);
630 rc = pci_enable_device(pdev); 774 rc = pci_enable_device(pdev);
631 if (rc) 775 if (rc)
632 goto err_out_enable; 776 goto err_out_enable;
@@ -665,25 +809,39 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
665 goto err_out_free; 809 goto err_out_free;
666 } 810 }
667 pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost)); 811 pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost));
668 pm8001_ha = pm8001_pci_alloc(pdev, chip_8001, shost); 812 /* ent->driver variable is used to differentiate between controllers */
813 pm8001_ha = pm8001_pci_alloc(pdev, ent, shost);
669 if (!pm8001_ha) { 814 if (!pm8001_ha) {
670 rc = -ENOMEM; 815 rc = -ENOMEM;
671 goto err_out_free; 816 goto err_out_free;
672 } 817 }
673 list_add_tail(&pm8001_ha->list, &hba_list); 818 list_add_tail(&pm8001_ha->list, &hba_list);
674 PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); 819 PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
675 rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); 820 rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
676 if (rc) 821 if (rc) {
822 PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
823 "chip_init failed [ret: %d]\n", rc));
677 goto err_out_ha_free; 824 goto err_out_ha_free;
825 }
678 826
679 rc = scsi_add_host(shost, &pdev->dev); 827 rc = scsi_add_host(shost, &pdev->dev);
680 if (rc) 828 if (rc)
681 goto err_out_ha_free; 829 goto err_out_ha_free;
682 rc = pm8001_request_irq(pm8001_ha); 830 rc = pm8001_request_irq(pm8001_ha);
683 if (rc) 831 if (rc) {
832 PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
833 "pm8001_request_irq failed [ret: %d]\n", rc));
684 goto err_out_shost; 834 goto err_out_shost;
835 }
836
837 PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
838 if (pm8001_ha->chip_id != chip_8001) {
839 for (i = 1; i < pm8001_ha->number_of_intr; i++)
840 PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
841 /* setup thermal configuration. */
842 pm80xx_set_thermal_config(pm8001_ha);
843 }
685 844
686 PM8001_CHIP_DISP->interrupt_enable(pm8001_ha);
687 pm8001_init_sas_add(pm8001_ha); 845 pm8001_init_sas_add(pm8001_ha);
688 pm8001_post_sas_ha_init(shost, chip); 846 pm8001_post_sas_ha_init(shost, chip);
689 rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); 847 rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
@@ -719,14 +877,15 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
719 sas_remove_host(pm8001_ha->shost); 877 sas_remove_host(pm8001_ha->shost);
720 list_del(&pm8001_ha->list); 878 list_del(&pm8001_ha->list);
721 scsi_remove_host(pm8001_ha->shost); 879 scsi_remove_host(pm8001_ha->shost);
722 PM8001_CHIP_DISP->interrupt_disable(pm8001_ha); 880 PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
723 PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); 881 PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
724 882
725#ifdef PM8001_USE_MSIX 883#ifdef PM8001_USE_MSIX
726 for (i = 0; i < pm8001_ha->number_of_intr; i++) 884 for (i = 0; i < pm8001_ha->number_of_intr; i++)
727 synchronize_irq(pm8001_ha->msix_entries[i].vector); 885 synchronize_irq(pm8001_ha->msix_entries[i].vector);
728 for (i = 0; i < pm8001_ha->number_of_intr; i++) 886 for (i = 0; i < pm8001_ha->number_of_intr; i++)
729 free_irq(pm8001_ha->msix_entries[i].vector, sha); 887 free_irq(pm8001_ha->msix_entries[i].vector,
888 &pm8001_ha->outq[i]);
730 pci_disable_msix(pdev); 889 pci_disable_msix(pdev);
731#else 890#else
732 free_irq(pm8001_ha->irq, sha); 891 free_irq(pm8001_ha->irq, sha);
@@ -763,13 +922,14 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
763 printk(KERN_ERR " PCI PM not supported\n"); 922 printk(KERN_ERR " PCI PM not supported\n");
764 return -ENODEV; 923 return -ENODEV;
765 } 924 }
766 PM8001_CHIP_DISP->interrupt_disable(pm8001_ha); 925 PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
767 PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); 926 PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
768#ifdef PM8001_USE_MSIX 927#ifdef PM8001_USE_MSIX
769 for (i = 0; i < pm8001_ha->number_of_intr; i++) 928 for (i = 0; i < pm8001_ha->number_of_intr; i++)
770 synchronize_irq(pm8001_ha->msix_entries[i].vector); 929 synchronize_irq(pm8001_ha->msix_entries[i].vector);
771 for (i = 0; i < pm8001_ha->number_of_intr; i++) 930 for (i = 0; i < pm8001_ha->number_of_intr; i++)
772 free_irq(pm8001_ha->msix_entries[i].vector, sha); 931 free_irq(pm8001_ha->msix_entries[i].vector,
932 &pm8001_ha->outq[i]);
773 pci_disable_msix(pdev); 933 pci_disable_msix(pdev);
774#else 934#else
775 free_irq(pm8001_ha->irq, sha); 935 free_irq(pm8001_ha->irq, sha);
@@ -798,6 +958,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
798 struct sas_ha_struct *sha = pci_get_drvdata(pdev); 958 struct sas_ha_struct *sha = pci_get_drvdata(pdev);
799 struct pm8001_hba_info *pm8001_ha; 959 struct pm8001_hba_info *pm8001_ha;
800 int rc; 960 int rc;
961 u8 i = 0;
801 u32 device_state; 962 u32 device_state;
802 pm8001_ha = sha->lldd_ha; 963 pm8001_ha = sha->lldd_ha;
803 device_state = pdev->current_state; 964 device_state = pdev->current_state;
@@ -820,19 +981,33 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
820 if (rc) 981 if (rc)
821 goto err_out_disable; 982 goto err_out_disable;
822 983
823 PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); 984 /* chip soft rst only for spc */
985 if (pm8001_ha->chip_id == chip_8001) {
986 PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
987 PM8001_INIT_DBG(pm8001_ha,
988 pm8001_printk("chip soft reset successful\n"));
989 }
824 rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); 990 rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
825 if (rc) 991 if (rc)
826 goto err_out_disable; 992 goto err_out_disable;
827 PM8001_CHIP_DISP->interrupt_disable(pm8001_ha); 993
994 /* disable all the interrupt bits */
995 PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
996
828 rc = pm8001_request_irq(pm8001_ha); 997 rc = pm8001_request_irq(pm8001_ha);
829 if (rc) 998 if (rc)
830 goto err_out_disable; 999 goto err_out_disable;
831 #ifdef PM8001_USE_TASKLET 1000#ifdef PM8001_USE_TASKLET
1001 /* default tasklet for non msi-x interrupt handler/first msi-x
1002 * interrupt handler */
832 tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, 1003 tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
833 (unsigned long)pm8001_ha); 1004 (unsigned long)pm8001_ha);
834 #endif 1005#endif
835 PM8001_CHIP_DISP->interrupt_enable(pm8001_ha); 1006 PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
1007 if (pm8001_ha->chip_id != chip_8001) {
1008 for (i = 1; i < pm8001_ha->number_of_intr; i++)
1009 PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
1010 }
836 scsi_unblock_requests(pm8001_ha->shost); 1011 scsi_unblock_requests(pm8001_ha->shost);
837 return 0; 1012 return 0;
838 1013
@@ -843,14 +1018,45 @@ err_out_enable:
843 return rc; 1018 return rc;
844} 1019}
845 1020
1021/* update of pci device, vendor id and driver data with
1022 * unique value for each of the controller
1023 */
846static struct pci_device_id pm8001_pci_table[] = { 1024static struct pci_device_id pm8001_pci_table[] = {
847 { 1025 { PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 },
848 PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001
849 },
850 { 1026 {
851 PCI_DEVICE(0x117c, 0x0042), 1027 PCI_DEVICE(0x117c, 0x0042),
852 .driver_data = chip_8001 1028 .driver_data = chip_8001
853 }, 1029 },
1030 /* Support for SPC/SPCv/SPCve controllers */
1031 { PCI_VDEVICE(ADAPTEC2, 0x8001), chip_8001 },
1032 { PCI_VDEVICE(PMC_Sierra, 0x8008), chip_8008 },
1033 { PCI_VDEVICE(ADAPTEC2, 0x8008), chip_8008 },
1034 { PCI_VDEVICE(PMC_Sierra, 0x8018), chip_8018 },
1035 { PCI_VDEVICE(ADAPTEC2, 0x8018), chip_8018 },
1036 { PCI_VDEVICE(PMC_Sierra, 0x8009), chip_8009 },
1037 { PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 },
1038 { PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 },
1039 { PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 },
1040 { PCI_VENDOR_ID_ADAPTEC2, 0x8081,
1041 PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 },
1042 { PCI_VENDOR_ID_ADAPTEC2, 0x8081,
1043 PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8001 },
1044 { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
1045 PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8008 },
1046 { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
1047 PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8008 },
1048 { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
1049 PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8009 },
1050 { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
1051 PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8009 },
1052 { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
1053 PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8018 },
1054 { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
1055 PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8018 },
1056 { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
1057 PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 },
1058 { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
1059 PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 },
854 {} /* terminate list */ 1060 {} /* terminate list */
855}; 1061};
856 1062
@@ -870,7 +1076,7 @@ static int __init pm8001_init(void)
870{ 1076{
871 int rc = -ENOMEM; 1077 int rc = -ENOMEM;
872 1078
873 pm8001_wq = alloc_workqueue("pm8001", 0, 0); 1079 pm8001_wq = alloc_workqueue("pm80xx", 0, 0);
874 if (!pm8001_wq) 1080 if (!pm8001_wq)
875 goto err; 1081 goto err;
876 1082
@@ -902,7 +1108,8 @@ module_init(pm8001_init);
902module_exit(pm8001_exit); 1108module_exit(pm8001_exit);
903 1109
904MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>"); 1110MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>");
905MODULE_DESCRIPTION("PMC-Sierra PM8001 SAS/SATA controller driver"); 1111MODULE_DESCRIPTION(
1112 "PMC-Sierra PM8001/8081/8088/8089 SAS/SATA controller driver");
906MODULE_VERSION(DRV_VERSION); 1113MODULE_VERSION(DRV_VERSION);
907MODULE_LICENSE("GPL"); 1114MODULE_LICENSE("GPL");
908MODULE_DEVICE_TABLE(pci, pm8001_pci_table); 1115MODULE_DEVICE_TABLE(pci, pm8001_pci_table);