aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion
diff options
context:
space:
mode:
authorMoore, Eric <Eric.Moore@lsil.com>2006-04-21 18:14:35 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-04-25 19:07:32 -0400
commit65207fedcf57dcb854a3ebb9da43c745106fe8d5 (patch)
treefce7ca7526448abd0be4ae59423d11fb842611e5 /drivers/message/fusion
parentbd23e94cd70f18700fc366451a8f1427e56ed137 (diff)
[SCSI] - fusion - mptfc bug fix's to prevent deadlock situations
mptbase.h bump version number to 3.03.09 remove unneeded flags define workq and remove old fc specific locks mptbase.c initialize new lock and don't initialize two removed locks mptscsih.c when firmware reports target is no longer there, return DID_REQUEUE for fc hosts so that i/o doesn't get killed until the transport has an opportunity to manage the loss via its dev loss timer when the "eh_abort" routine is called, check to see if the driver has the command or not before looking to see if a reset is pending. James Smart and I talked about this and believe that the API for this routine is: if driver doesn't have command, return SUCCESS. This change helps prevent a target from being taken offline. SUCCESS is returned because it's likely that the command completed after error recovery timed it out but before it could be aborted. provide a routine to queue work to newly created workq, and use it. remove "ioc" from mptscsih_abort() it was only used one time. the other references were via hd->ioc, so I just moved it.... net change in references to ioc via hd->ioc is zero move hd->resetPending test and hd->timeouts increment to after the test for whether the command to be aborted remains known to the driver Make certain that the workq exists before queuing work to it. mptfc.c no longer need to lock rport data structures as I was able to single thread the code! I fixed up the debug code to eliminate compilation messages due to type mismatch in the printk. Got rid of some no longer needed rport flags. Initialize and destroy the workq used for the rescan work. simplify the logic regarding the increment of fc_rescan_work_count. use post increment and test for zero vs. pre increment and test for one; eliminate work_count variable: queue_work can be called with the work_lock held as it doesn't sleep Signed-off-by: Michael Reed <mdr@sgi.com> Signed-off-by: Eric Moore <Eric.Moore@lsil.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r--drivers/message/fusion/mptbase.c1
-rw-r--r--drivers/message/fusion/mptbase.h10
-rw-r--r--drivers/message/fusion/mptfc.c125
-rw-r--r--drivers/message/fusion/mptscsih.c48
4 files changed, 107 insertions, 77 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index ac66a658aa11..5fe6e8df50ab 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1189,7 +1189,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1189 ioc->diagPending = 0; 1189 ioc->diagPending = 0;
1190 spin_lock_init(&ioc->diagLock); 1190 spin_lock_init(&ioc->diagLock);
1191 spin_lock_init(&ioc->fc_rescan_work_lock); 1191 spin_lock_init(&ioc->fc_rescan_work_lock);
1192 spin_lock_init(&ioc->fc_rport_lock);
1193 spin_lock_init(&ioc->initializing_hba_lock); 1192 spin_lock_init(&ioc->initializing_hba_lock);
1194 1193
1195 /* Initialize the event logging. 1194 /* Initialize the event logging.
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index be7e8501b53c..f673cca507e1 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
76#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR 76#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
77#endif 77#endif
78 78
79#define MPT_LINUX_VERSION_COMMON "3.03.08" 79#define MPT_LINUX_VERSION_COMMON "3.03.09"
80#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.08" 80#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.09"
81#define WHAT_MAGIC_STRING "@" "(" "#" ")" 81#define WHAT_MAGIC_STRING "@" "(" "#" ")"
82 82
83#define show_mptmod_ver(s,ver) \ 83#define show_mptmod_ver(s,ver) \
@@ -489,7 +489,6 @@ typedef struct _RaidCfgData {
489 489
490#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */ 490#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */
491#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */ 491#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */
492#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04 /* target mapped in vdev */
493 492
494/* 493/*
495 * data allocated for each fc rport device 494 * data allocated for each fc rport device
@@ -501,7 +500,6 @@ struct mptfc_rport_info
501 struct scsi_target *starget; 500 struct scsi_target *starget;
502 FCDevicePage0_t pg0; 501 FCDevicePage0_t pg0;
503 u8 flags; 502 u8 flags;
504 u8 remap_needed;
505}; 503};
506 504
507/* 505/*
@@ -628,11 +626,11 @@ typedef struct _MPT_ADAPTER
628 struct work_struct mptscsih_persistTask; 626 struct work_struct mptscsih_persistTask;
629 627
630 struct list_head fc_rports; 628 struct list_head fc_rports;
631 spinlock_t fc_rport_lock; /* list and ri flags */
632 spinlock_t fc_rescan_work_lock; 629 spinlock_t fc_rescan_work_lock;
633 int fc_rescan_work_count; 630 int fc_rescan_work_count;
634 struct work_struct fc_rescan_work; 631 struct work_struct fc_rescan_work;
635 632 char fc_rescan_work_q_name[KOBJ_NAME_LEN];
633 struct workqueue_struct *fc_rescan_work_q;
636} MPT_ADAPTER; 634} MPT_ADAPTER;
637 635
638/* 636/*
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index b343f2a68b1c..e1fb5a166366 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -355,15 +355,13 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
355 struct fc_rport *rport; 355 struct fc_rport *rport;
356 struct mptfc_rport_info *ri; 356 struct mptfc_rport_info *ri;
357 int new_ri = 1; 357 int new_ri = 1;
358 u64 pn; 358 u64 pn, nn;
359 unsigned long flags;
360 VirtTarget *vtarget; 359 VirtTarget *vtarget;
361 360
362 if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0) 361 if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
363 return; 362 return;
364 363
365 /* scan list looking for a match */ 364 /* scan list looking for a match */
366 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
367 list_for_each_entry(ri, &ioc->fc_rports, list) { 365 list_for_each_entry(ri, &ioc->fc_rports, list) {
368 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; 366 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
369 if (pn == rport_ids.port_name) { /* match */ 367 if (pn == rport_ids.port_name) { /* match */
@@ -373,11 +371,9 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
373 } 371 }
374 } 372 }
375 if (new_ri) { /* allocate one */ 373 if (new_ri) { /* allocate one */
376 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
377 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL); 374 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
378 if (!ri) 375 if (!ri)
379 return; 376 return;
380 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
381 list_add_tail(&ri->list, &ioc->fc_rports); 377 list_add_tail(&ri->list, &ioc->fc_rports);
382 } 378 }
383 379
@@ -387,14 +383,11 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
387 /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */ 383 /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
388 if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) { 384 if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
389 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED; 385 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
390 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
391 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids); 386 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
392 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
393 if (rport) { 387 if (rport) {
394 ri->rport = rport; 388 ri->rport = rport;
395 if (new_ri) /* may have been reset by user */ 389 if (new_ri) /* may have been reset by user */
396 rport->dev_loss_tmo = mptfc_dev_loss_tmo; 390 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
397 *((struct mptfc_rport_info **)rport->dd_data) = ri;
398 /* 391 /*
399 * if already mapped, remap here. If not mapped, 392 * if already mapped, remap here. If not mapped,
400 * target_alloc will allocate vtarget and map, 393 * target_alloc will allocate vtarget and map,
@@ -406,16 +399,20 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
406 vtarget->target_id = pg0->CurrentTargetID; 399 vtarget->target_id = pg0->CurrentTargetID;
407 vtarget->bus_id = pg0->CurrentBus; 400 vtarget->bus_id = pg0->CurrentBus;
408 } 401 }
409 ri->remap_needed = 0;
410 } 402 }
403 /* once dd_data is filled in, commands will issue to hardware */
404 *((struct mptfc_rport_info **)rport->dd_data) = ri;
405
406 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
407 nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
411 dfcprintk ((MYIOC_s_INFO_FMT 408 dfcprintk ((MYIOC_s_INFO_FMT
412 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " 409 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
413 "rport tid %d, tmo %d\n", 410 "rport tid %d, tmo %d\n",
414 ioc->name, 411 ioc->name,
415 ioc->sh->host_no, 412 ioc->sh->host_no,
416 pg0->PortIdentifier, 413 pg0->PortIdentifier,
417 pg0->WWNN, 414 (unsigned long long)nn,
418 pg0->WWPN, 415 (unsigned long long)pn,
419 pg0->CurrentTargetID, 416 pg0->CurrentTargetID,
420 ri->rport->scsi_target_id, 417 ri->rport->scsi_target_id,
421 ri->rport->dev_loss_tmo)); 418 ri->rport->dev_loss_tmo));
@@ -425,8 +422,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
425 ri = NULL; 422 ri = NULL;
426 } 423 }
427 } 424 }
428 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
429
430} 425}
431 426
432/* 427/*
@@ -476,7 +471,6 @@ mptfc_target_alloc(struct scsi_target *starget)
476 vtarget->target_id = ri->pg0.CurrentTargetID; 471 vtarget->target_id = ri->pg0.CurrentTargetID;
477 vtarget->bus_id = ri->pg0.CurrentBus; 472 vtarget->bus_id = ri->pg0.CurrentBus;
478 ri->starget = starget; 473 ri->starget = starget;
479 ri->remap_needed = 0;
480 rc = 0; 474 rc = 0;
481 } 475 }
482 } 476 }
@@ -502,10 +496,10 @@ mptfc_slave_alloc(struct scsi_device *sdev)
502 VirtDevice *vdev; 496 VirtDevice *vdev;
503 struct scsi_target *starget; 497 struct scsi_target *starget;
504 struct fc_rport *rport; 498 struct fc_rport *rport;
505 unsigned long flags;
506 499
507 500
508 rport = starget_to_rport(scsi_target(sdev)); 501 starget = scsi_target(sdev);
502 rport = starget_to_rport(starget);
509 503
510 if (!rport || fc_remote_port_chkready(rport)) 504 if (!rport || fc_remote_port_chkready(rport))
511 return -ENXIO; 505 return -ENXIO;
@@ -519,10 +513,8 @@ mptfc_slave_alloc(struct scsi_device *sdev)
519 return -ENOMEM; 513 return -ENOMEM;
520 } 514 }
521 515
522 spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
523 516
524 sdev->hostdata = vdev; 517 sdev->hostdata = vdev;
525 starget = scsi_target(sdev);
526 vtarget = starget->hostdata; 518 vtarget = starget->hostdata;
527 519
528 if (vtarget->num_luns == 0) { 520 if (vtarget->num_luns == 0) {
@@ -535,14 +527,16 @@ mptfc_slave_alloc(struct scsi_device *sdev)
535 vdev->vtarget = vtarget; 527 vdev->vtarget = vtarget;
536 vdev->lun = sdev->lun; 528 vdev->lun = sdev->lun;
537 529
538 spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
539
540 vtarget->num_luns++; 530 vtarget->num_luns++;
541 531
532
542#ifdef DMPT_DEBUG_FC 533#ifdef DMPT_DEBUG_FC
543 { 534 {
535 u64 nn, pn;
544 struct mptfc_rport_info *ri; 536 struct mptfc_rport_info *ri;
545 ri = *((struct mptfc_rport_info **)rport->dd_data); 537 ri = *((struct mptfc_rport_info **)rport->dd_data);
538 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
539 nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
546 dfcprintk ((MYIOC_s_INFO_FMT 540 dfcprintk ((MYIOC_s_INFO_FMT
547 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " 541 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
548 "CurrentTargetID %d, %x %llx %llx\n", 542 "CurrentTargetID %d, %x %llx %llx\n",
@@ -550,7 +544,9 @@ mptfc_slave_alloc(struct scsi_device *sdev)
550 sdev->host->host_no, 544 sdev->host->host_no,
551 vtarget->num_luns, 545 vtarget->num_luns,
552 sdev->id, ri->pg0.CurrentTargetID, 546 sdev->id, ri->pg0.CurrentTargetID,
553 ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN)); 547 ri->pg0.PortIdentifier,
548 (unsigned long long)pn,
549 (unsigned long long)nn));
554 } 550 }
555#endif 551#endif
556 552
@@ -570,11 +566,31 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
570 done(SCpnt); 566 done(SCpnt);
571 return 0; 567 return 0;
572 } 568 }
569
570 /* dd_data is null until finished adding target */
573 ri = *((struct mptfc_rport_info **)rport->dd_data); 571 ri = *((struct mptfc_rport_info **)rport->dd_data);
574 if (unlikely(ri->remap_needed)) 572 if (unlikely(!ri)) {
575 return SCSI_MLQUEUE_HOST_BUSY; 573 dfcprintk ((MYIOC_s_INFO_FMT
574 "mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
575 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
576 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
577 SCpnt->device->id,SCpnt->device->lun));
578 SCpnt->result = DID_IMM_RETRY << 16;
579 done(SCpnt);
580 return 0;
581 }
576 582
577 return mptscsih_qcmd(SCpnt,done); 583 err = mptscsih_qcmd(SCpnt,done);
584#ifdef DMPT_DEBUG_FC
585 if (unlikely(err)) {
586 dfcprintk ((MYIOC_s_INFO_FMT
587 "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n",
588 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
589 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
590 SCpnt->device->id,SCpnt->device->lun));
591 }
592#endif
593 return err;
578} 594}
579 595
580static void 596static void
@@ -615,18 +631,17 @@ mptfc_rescan_devices(void *arg)
615 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; 631 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
616 int ii; 632 int ii;
617 int work_to_do; 633 int work_to_do;
634 u64 pn;
618 unsigned long flags; 635 unsigned long flags;
619 struct mptfc_rport_info *ri; 636 struct mptfc_rport_info *ri;
620 637
621 do { 638 do {
622 /* start by tagging all ports as missing */ 639 /* start by tagging all ports as missing */
623 spin_lock_irqsave(&ioc->fc_rport_lock,flags);
624 list_for_each_entry(ri, &ioc->fc_rports, list) { 640 list_for_each_entry(ri, &ioc->fc_rports, list) {
625 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { 641 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
626 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING; 642 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
627 } 643 }
628 } 644 }
629 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
630 645
631 /* 646 /*
632 * now rescan devices known to adapter, 647 * now rescan devices known to adapter,
@@ -639,33 +654,24 @@ mptfc_rescan_devices(void *arg)
639 } 654 }
640 655
641 /* delete devices still missing */ 656 /* delete devices still missing */
642 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
643 list_for_each_entry(ri, &ioc->fc_rports, list) { 657 list_for_each_entry(ri, &ioc->fc_rports, list) {
644 /* if newly missing, delete it */ 658 /* if newly missing, delete it */
645 if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED | 659 if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
646 MPT_RPORT_INFO_FLAGS_MISSING))
647 == (MPT_RPORT_INFO_FLAGS_REGISTERED |
648 MPT_RPORT_INFO_FLAGS_MISSING)) {
649 660
650 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| 661 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
651 MPT_RPORT_INFO_FLAGS_MISSING); 662 MPT_RPORT_INFO_FLAGS_MISSING);
652 ri->remap_needed = 1; 663 fc_remote_port_delete(ri->rport); /* won't sleep */
653 fc_remote_port_delete(ri->rport);
654 /*
655 * remote port not really deleted 'cause
656 * binding is by WWPN and driver only
657 * registers FCP_TARGETs but cannot trust
658 * data structures.
659 */
660 ri->rport = NULL; 664 ri->rport = NULL;
665
666 pn = (u64)ri->pg0.WWPN.High << 32 |
667 (u64)ri->pg0.WWPN.Low;
661 dfcprintk ((MYIOC_s_INFO_FMT 668 dfcprintk ((MYIOC_s_INFO_FMT
662 "mptfc_rescan.%d: %llx deleted\n", 669 "mptfc_rescan.%d: %llx deleted\n",
663 ioc->name, 670 ioc->name,
664 ioc->sh->host_no, 671 ioc->sh->host_no,
665 ri->pg0.WWPN)); 672 (unsigned long long)pn));
666 } 673 }
667 } 674 }
668 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
669 675
670 /* 676 /*
671 * allow multiple passes as target state 677 * allow multiple passes as target state
@@ -870,10 +876,23 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
870 goto out_mptfc_probe; 876 goto out_mptfc_probe;
871 } 877 }
872 878
873 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { 879 /* initialize workqueue */
874 mptfc_init_host_attr(ioc,ii); 880
875 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); 881 snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
876 } 882 sh->host_no);
883 ioc->fc_rescan_work_q =
884 create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
885 if (!ioc->fc_rescan_work_q)
886 goto out_mptfc_probe;
887
888 /*
889 * scan for rports -
890 * by doing it via the workqueue, some locking is eliminated
891 */
892
893 ioc->fc_rescan_work_count = 1;
894 queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
895 flush_workqueue(ioc->fc_rescan_work_q);
877 896
878 return 0; 897 return 0;
879 898
@@ -949,8 +968,18 @@ mptfc_init(void)
949static void __devexit 968static void __devexit
950mptfc_remove(struct pci_dev *pdev) 969mptfc_remove(struct pci_dev *pdev)
951{ 970{
952 MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 971 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
953 struct mptfc_rport_info *p, *n; 972 struct mptfc_rport_info *p, *n;
973 struct workqueue_struct *work_q;
974 unsigned long flags;
975
976 /* destroy workqueue */
977 if ((work_q=ioc->fc_rescan_work_q)) {
978 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
979 ioc->fc_rescan_work_q = NULL;
980 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
981 destroy_workqueue(work_q);
982 }
954 983
955 fc_remove_host(ioc->sh); 984 fc_remove_host(ioc->sh);
956 985
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 6a71b066bd21..84fa271eb8f4 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -632,7 +632,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
632 632
633 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ 633 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
634 /* Spoof to SCSI Selection Timeout! */ 634 /* Spoof to SCSI Selection Timeout! */
635 sc->result = DID_NO_CONNECT << 16; 635 if (ioc->bus_type != FC)
636 sc->result = DID_NO_CONNECT << 16;
637 /* else fibre, just stall until rescan event */
638 else
639 sc->result = DID_REQUEUE << 16;
636 640
637 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF) 641 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
638 hd->sel_timeout[pScsiReq->TargetID]++; 642 hd->sel_timeout[pScsiReq->TargetID]++;
@@ -1645,7 +1649,6 @@ int
1645mptscsih_abort(struct scsi_cmnd * SCpnt) 1649mptscsih_abort(struct scsi_cmnd * SCpnt)
1646{ 1650{
1647 MPT_SCSI_HOST *hd; 1651 MPT_SCSI_HOST *hd;
1648 MPT_ADAPTER *ioc;
1649 MPT_FRAME_HDR *mf; 1652 MPT_FRAME_HDR *mf;
1650 u32 ctx2abort; 1653 u32 ctx2abort;
1651 int scpnt_idx; 1654 int scpnt_idx;
@@ -1663,14 +1666,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1663 return FAILED; 1666 return FAILED;
1664 } 1667 }
1665 1668
1666 ioc = hd->ioc;
1667 if (hd->resetPending) {
1668 return FAILED;
1669 }
1670
1671 if (hd->timeouts < -1)
1672 hd->timeouts++;
1673
1674 /* Find this command 1669 /* Find this command
1675 */ 1670 */
1676 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { 1671 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
@@ -1684,6 +1679,13 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1684 return SUCCESS; 1679 return SUCCESS;
1685 } 1680 }
1686 1681
1682 if (hd->resetPending) {
1683 return FAILED;
1684 }
1685
1686 if (hd->timeouts < -1)
1687 hd->timeouts++;
1688
1687 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n", 1689 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1688 hd->ioc->name, SCpnt); 1690 hd->ioc->name, SCpnt);
1689 scsi_print_command(SCpnt); 1691 scsi_print_command(SCpnt);
@@ -1703,7 +1705,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1703 vdev = SCpnt->device->hostdata; 1705 vdev = SCpnt->device->hostdata;
1704 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, 1706 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1705 vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, 1707 vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
1706 ctx2abort, mptscsih_get_tm_timeout(ioc)); 1708 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1707 1709
1708 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", 1710 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1709 hd->ioc->name, 1711 hd->ioc->name,
@@ -2521,15 +2523,15 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2521 2523
2522 /* 7. FC: Rescan for blocked rports which might have returned. 2524 /* 7. FC: Rescan for blocked rports which might have returned.
2523 */ 2525 */
2524 else if (ioc->bus_type == FC) { 2526 if (ioc->bus_type == FC) {
2525 int work_count;
2526 unsigned long flags;
2527
2528 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); 2527 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2529 work_count = ++ioc->fc_rescan_work_count; 2528 if (ioc->fc_rescan_work_q) {
2529 if (ioc->fc_rescan_work_count++ == 0) {
2530 queue_work(ioc->fc_rescan_work_q,
2531 &ioc->fc_rescan_work);
2532 }
2533 }
2530 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); 2534 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2531 if (work_count == 1)
2532 schedule_work(&ioc->fc_rescan_work);
2533 } 2535 }
2534 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); 2536 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2535 2537
@@ -2544,7 +2546,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2544{ 2546{
2545 MPT_SCSI_HOST *hd; 2547 MPT_SCSI_HOST *hd;
2546 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; 2548 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2547 int work_count;
2548 unsigned long flags; 2549 unsigned long flags;
2549 2550
2550 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", 2551 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
@@ -2569,10 +2570,13 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2569 2570
2570 case MPI_EVENT_RESCAN: /* 06 */ 2571 case MPI_EVENT_RESCAN: /* 06 */
2571 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); 2572 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2572 work_count = ++ioc->fc_rescan_work_count; 2573 if (ioc->fc_rescan_work_q) {
2574 if (ioc->fc_rescan_work_count++ == 0) {
2575 queue_work(ioc->fc_rescan_work_q,
2576 &ioc->fc_rescan_work);
2577 }
2578 }
2573 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); 2579 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2574 if (work_count == 1)
2575 schedule_work(&ioc->fc_rescan_work);
2576 break; 2580 break;
2577 2581
2578 /* 2582 /*