aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r--drivers/message/fusion/Makefile2
-rw-r--r--drivers/message/fusion/mptbase.c184
-rw-r--r--drivers/message/fusion/mptbase.h16
-rw-r--r--drivers/message/fusion/mptfc.c203
-rw-r--r--drivers/message/fusion/mptsas.c241
-rw-r--r--drivers/message/fusion/mptscsih.c116
-rw-r--r--drivers/message/fusion/mptscsih.h1
-rw-r--r--drivers/message/fusion/mptspi.c10
8 files changed, 636 insertions, 137 deletions
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index 8a2e2657f4c..33ace373241 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -29,6 +29,8 @@
29# For mptctl: 29# For mptctl:
30#CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL 30#CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
31# 31#
32# For mptfc:
33#CFLAGS_mptfc.o += -DMPT_DEBUG_FC
32 34
33#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC 35#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
34 36
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index d890b2b8a93..9a2c7605d49 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -81,6 +81,10 @@ MODULE_LICENSE("GPL");
81/* 81/*
82 * cmd line parameters 82 * cmd line parameters
83 */ 83 */
84static int mpt_msi_enable;
85module_param(mpt_msi_enable, int, 0);
86MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
87
84#ifdef MFCNT 88#ifdef MFCNT
85static int mfcounter = 0; 89static int mfcounter = 0;
86#define PRINT_MF_COUNT 20000 90#define PRINT_MF_COUNT 20000
@@ -174,7 +178,7 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
174static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); 178static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
175static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); 179static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
176static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); 180static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
177static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); 181static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
178static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); 182static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
179 183
180/* module entry point */ 184/* module entry point */
@@ -313,7 +317,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
313 if (ioc->bus_type == FC) 317 if (ioc->bus_type == FC)
314 mpt_fc_log_info(ioc, log_info); 318 mpt_fc_log_info(ioc, log_info);
315 else if (ioc->bus_type == SPI) 319 else if (ioc->bus_type == SPI)
316 mpt_sp_log_info(ioc, log_info); 320 mpt_spi_log_info(ioc, log_info);
317 else if (ioc->bus_type == SAS) 321 else if (ioc->bus_type == SAS)
318 mpt_sas_log_info(ioc, log_info); 322 mpt_sas_log_info(ioc, log_info);
319 } 323 }
@@ -1444,6 +1448,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1444 1448
1445 ioc->pci_irq = -1; 1449 ioc->pci_irq = -1;
1446 if (pdev->irq) { 1450 if (pdev->irq) {
1451 if (mpt_msi_enable && !pci_enable_msi(pdev))
1452 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name);
1453
1447 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); 1454 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1448 1455
1449 if (r < 0) { 1456 if (r < 0) {
@@ -1483,6 +1490,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1483 1490
1484 list_del(&ioc->list); 1491 list_del(&ioc->list);
1485 free_irq(ioc->pci_irq, ioc); 1492 free_irq(ioc->pci_irq, ioc);
1493 if (mpt_msi_enable)
1494 pci_disable_msi(pdev);
1495 if (ioc->alt_ioc)
1496 ioc->alt_ioc->alt_ioc = NULL;
1486 iounmap(mem); 1497 iounmap(mem);
1487 kfree(ioc); 1498 kfree(ioc);
1488 pci_set_drvdata(pdev, NULL); 1499 pci_set_drvdata(pdev, NULL);
@@ -2136,6 +2147,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
2136 2147
2137 if (ioc->pci_irq != -1) { 2148 if (ioc->pci_irq != -1) {
2138 free_irq(ioc->pci_irq, ioc); 2149 free_irq(ioc->pci_irq, ioc);
2150 if (mpt_msi_enable)
2151 pci_disable_msi(ioc->pcidev);
2139 ioc->pci_irq = -1; 2152 ioc->pci_irq = -1;
2140 } 2153 }
2141 2154
@@ -2157,6 +2170,10 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
2157 sz_last = ioc->alloc_total; 2170 sz_last = ioc->alloc_total;
2158 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", 2171 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2159 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); 2172 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2173
2174 if (ioc->alt_ioc)
2175 ioc->alt_ioc->alt_ioc = NULL;
2176
2160 kfree(ioc); 2177 kfree(ioc);
2161} 2178}
2162 2179
@@ -2770,13 +2787,16 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2770 2787
2771 /* RAID FW may take a long time to enable 2788 /* RAID FW may take a long time to enable
2772 */ 2789 */
2773 if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) 2790 if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2774 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) { 2791 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2775 rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, 2792 (ioc->bus_type == SAS)) {
2776 reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); 2793 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2794 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2795 300 /*seconds*/, sleepFlag);
2777 } else { 2796 } else {
2778 rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, 2797 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2779 reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag); 2798 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2799 30 /*seconds*/, sleepFlag);
2780 } 2800 }
2781 return rc; 2801 return rc;
2782} 2802}
@@ -4387,6 +4407,138 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4387} 4407}
4388 4408
4389/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 4409/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4410
4411static void
4412mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4413 MpiEventDataRaid_t * pRaidEventData)
4414{
4415 int volume;
4416 int reason;
4417 int disk;
4418 int status;
4419 int flags;
4420 int state;
4421
4422 volume = pRaidEventData->VolumeID;
4423 reason = pRaidEventData->ReasonCode;
4424 disk = pRaidEventData->PhysDiskNum;
4425 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4426 flags = (status >> 0) & 0xff;
4427 state = (status >> 8) & 0xff;
4428
4429 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4430 return;
4431 }
4432
4433 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4434 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4435 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4436 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4437 ioc->name, disk);
4438 } else {
4439 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4440 ioc->name, volume);
4441 }
4442
4443 switch(reason) {
4444 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4445 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4446 ioc->name);
4447 break;
4448
4449 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4450
4451 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4452 ioc->name);
4453 break;
4454
4455 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4456 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4457 ioc->name);
4458 break;
4459
4460 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4461 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4462 ioc->name,
4463 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4464 ? "optimal"
4465 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4466 ? "degraded"
4467 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4468 ? "failed"
4469 : "state unknown",
4470 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4471 ? ", enabled" : "",
4472 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4473 ? ", quiesced" : "",
4474 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4475 ? ", resync in progress" : "" );
4476 break;
4477
4478 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4479 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4480 ioc->name, disk);
4481 break;
4482
4483 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4484 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4485 ioc->name);
4486 break;
4487
4488 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4489 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4490 ioc->name);
4491 break;
4492
4493 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4494 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4495 ioc->name);
4496 break;
4497
4498 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4499 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4500 ioc->name,
4501 state == MPI_PHYSDISK0_STATUS_ONLINE
4502 ? "online"
4503 : state == MPI_PHYSDISK0_STATUS_MISSING
4504 ? "missing"
4505 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4506 ? "not compatible"
4507 : state == MPI_PHYSDISK0_STATUS_FAILED
4508 ? "failed"
4509 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4510 ? "initializing"
4511 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4512 ? "offline requested"
4513 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4514 ? "failed requested"
4515 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4516 ? "offline"
4517 : "state unknown",
4518 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4519 ? ", out of sync" : "",
4520 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4521 ? ", quiesced" : "" );
4522 break;
4523
4524 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4525 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4526 ioc->name, disk);
4527 break;
4528
4529 case MPI_EVENT_RAID_RC_SMART_DATA:
4530 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4531 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4532 break;
4533
4534 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4535 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4536 ioc->name, disk);
4537 break;
4538 }
4539}
4540
4541/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4390/* 4542/*
4391 * GetIoUnitPage2 - Retrieve BIOS version and boot order information. 4543 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4392 * @ioc: Pointer to MPT_ADAPTER structure 4544 * @ioc: Pointer to MPT_ADAPTER structure
@@ -4598,6 +4750,14 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4598 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf; 4750 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4599 MpiDeviceInfo_t *pdevice = NULL; 4751 MpiDeviceInfo_t *pdevice = NULL;
4600 4752
4753 /*
4754 * Save "Set to Avoid SCSI Bus Resets" flag
4755 */
4756 ioc->spi_data.bus_reset =
4757 (le32_to_cpu(pPP2->PortFlags) &
4758 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4759 0 : 1 ;
4760
4601 /* Save the Port Page 2 data 4761 /* Save the Port Page 2 data
4602 * (reformat into a 32bit quantity) 4762 * (reformat into a 32bit quantity)
4603 */ 4763 */
@@ -5967,6 +6127,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
5967 } 6127 }
5968 } 6128 }
5969 break; 6129 break;
6130 case MPI_EVENT_INTEGRATED_RAID:
6131 mptbase_raid_process_event_data(ioc,
6132 (MpiEventDataRaid_t *)pEventReply->Data);
6133 break;
5970 default: 6134 default:
5971 break; 6135 break;
5972 } 6136 }
@@ -6046,7 +6210,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6046 6210
6047/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 6211/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6048/* 6212/*
6049 * mpt_sp_log_info - Log information returned from SCSI Parallel IOC. 6213 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6050 * @ioc: Pointer to MPT_ADAPTER structure 6214 * @ioc: Pointer to MPT_ADAPTER structure
6051 * @mr: Pointer to MPT reply frame 6215 * @mr: Pointer to MPT reply frame
6052 * @log_info: U32 LogInfo word from the IOC 6216 * @log_info: U32 LogInfo word from the IOC
@@ -6054,7 +6218,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6054 * Refer to lsi/sp_log.h. 6218 * Refer to lsi/sp_log.h.
6055 */ 6219 */
6056static void 6220static void
6057mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) 6221mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6058{ 6222{
6059 u32 info = log_info & 0x00FF0000; 6223 u32 info = log_info & 0x00FF0000;
6060 char *desc = "unknown"; 6224 char *desc = "unknown";
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 47053ac6506..ea2649ecad1 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.06" 79#define MPT_LINUX_VERSION_COMMON "3.03.07"
80#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06" 80#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.07"
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) \
@@ -123,7 +123,7 @@
123#define MPT_MAX_FRAME_SIZE 128 123#define MPT_MAX_FRAME_SIZE 128
124#define MPT_DEFAULT_FRAME_SIZE 128 124#define MPT_DEFAULT_FRAME_SIZE 128
125 125
126#define MPT_REPLY_FRAME_SIZE 0x40 /* Must be a multiple of 8 */ 126#define MPT_REPLY_FRAME_SIZE 0x50 /* Must be a multiple of 8 */
127 127
128#define MPT_SG_REQ_128_SCALE 1 128#define MPT_SG_REQ_128_SCALE 1
129#define MPT_SG_REQ_96_SCALE 2 129#define MPT_SG_REQ_96_SCALE 2
@@ -510,9 +510,10 @@ struct mptfc_rport_info
510{ 510{
511 struct list_head list; 511 struct list_head list;
512 struct fc_rport *rport; 512 struct fc_rport *rport;
513 VirtDevice *vdev; 513 struct scsi_target *starget;
514 FCDevicePage0_t pg0; 514 FCDevicePage0_t pg0;
515 u8 flags; 515 u8 flags;
516 u8 remap_needed;
516}; 517};
517 518
518/* 519/*
@@ -631,6 +632,7 @@ typedef struct _MPT_ADAPTER
631 struct mutex sas_topology_mutex; 632 struct mutex sas_topology_mutex;
632 MPT_SAS_MGMT sas_mgmt; 633 MPT_SAS_MGMT sas_mgmt;
633 int num_ports; 634 int num_ports;
635 struct work_struct mptscsih_persistTask;
634 636
635 struct list_head fc_rports; 637 struct list_head fc_rports;
636 spinlock_t fc_rport_lock; /* list and ri flags */ 638 spinlock_t fc_rport_lock; /* list and ri flags */
@@ -803,6 +805,12 @@ typedef struct _mpt_sge {
803#define dreplyprintk(x) 805#define dreplyprintk(x)
804#endif 806#endif
805 807
808#ifdef DMPT_DEBUG_FC
809#define dfcprintk(x) printk x
810#else
811#define dfcprintk(x)
812#endif
813
806#ifdef MPT_DEBUG_TM 814#ifdef MPT_DEBUG_TM
807#define dtmprintk(x) printk x 815#define dtmprintk(x) printk x
808#define DBG_DUMP_TM_REQUEST_FRAME(mfp) \ 816#define DBG_DUMP_TM_REQUEST_FRAME(mfp) \
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index b102c7666d0..c3a3499bce2 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -93,10 +93,11 @@ static int mptfcDoneCtx = -1;
93static int mptfcTaskCtx = -1; 93static int mptfcTaskCtx = -1;
94static int mptfcInternalCtx = -1; /* Used only for internal commands */ 94static int mptfcInternalCtx = -1; /* Used only for internal commands */
95 95
96int mptfc_slave_alloc(struct scsi_device *device); 96static int mptfc_target_alloc(struct scsi_target *starget);
97static int mptfc_slave_alloc(struct scsi_device *sdev);
97static int mptfc_qcmd(struct scsi_cmnd *SCpnt, 98static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
98 void (*done)(struct scsi_cmnd *)); 99 void (*done)(struct scsi_cmnd *));
99 100static void mptfc_target_destroy(struct scsi_target *starget);
100static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); 101static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
101static void __devexit mptfc_remove(struct pci_dev *pdev); 102static void __devexit mptfc_remove(struct pci_dev *pdev);
102 103
@@ -107,10 +108,10 @@ static struct scsi_host_template mptfc_driver_template = {
107 .name = "MPT FC Host", 108 .name = "MPT FC Host",
108 .info = mptscsih_info, 109 .info = mptscsih_info,
109 .queuecommand = mptfc_qcmd, 110 .queuecommand = mptfc_qcmd,
110 .target_alloc = mptscsih_target_alloc, 111 .target_alloc = mptfc_target_alloc,
111 .slave_alloc = mptfc_slave_alloc, 112 .slave_alloc = mptfc_slave_alloc,
112 .slave_configure = mptscsih_slave_configure, 113 .slave_configure = mptscsih_slave_configure,
113 .target_destroy = mptscsih_target_destroy, 114 .target_destroy = mptfc_target_destroy,
114 .slave_destroy = mptscsih_slave_destroy, 115 .slave_destroy = mptscsih_slave_destroy,
115 .change_queue_depth = mptscsih_change_queue_depth, 116 .change_queue_depth = mptscsih_change_queue_depth,
116 .eh_abort_handler = mptscsih_abort, 117 .eh_abort_handler = mptscsih_abort,
@@ -348,14 +349,33 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
348} 349}
349 350
350static void 351static void
352mptfc_remap_sdev(struct scsi_device *sdev, void *arg)
353{
354 VirtDevice *vdev;
355 VirtTarget *vtarget;
356 struct scsi_target *starget;
357
358 starget = scsi_target(sdev);
359 if (starget->hostdata == arg) {
360 vtarget = arg;
361 vdev = sdev->hostdata;
362 if (vdev) {
363 vdev->bus_id = vtarget->bus_id;
364 vdev->target_id = vtarget->target_id;
365 }
366 }
367}
368
369static void
351mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) 370mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
352{ 371{
353 struct fc_rport_identifiers rport_ids; 372 struct fc_rport_identifiers rport_ids;
354 struct fc_rport *rport; 373 struct fc_rport *rport;
355 struct mptfc_rport_info *ri; 374 struct mptfc_rport_info *ri;
356 int match = 0; 375 int new_ri = 1;
357 u64 port_name; 376 u64 pn;
358 unsigned long flags; 377 unsigned long flags;
378 VirtTarget *vtarget;
359 379
360 if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0) 380 if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
361 return; 381 return;
@@ -363,14 +383,14 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
363 /* scan list looking for a match */ 383 /* scan list looking for a match */
364 spin_lock_irqsave(&ioc->fc_rport_lock, flags); 384 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
365 list_for_each_entry(ri, &ioc->fc_rports, list) { 385 list_for_each_entry(ri, &ioc->fc_rports, list) {
366 port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; 386 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
367 if (port_name == rport_ids.port_name) { /* match */ 387 if (pn == rport_ids.port_name) { /* match */
368 list_move_tail(&ri->list, &ioc->fc_rports); 388 list_move_tail(&ri->list, &ioc->fc_rports);
369 match = 1; 389 new_ri = 0;
370 break; 390 break;
371 } 391 }
372 } 392 }
373 if (!match) { /* allocate one */ 393 if (new_ri) { /* allocate one */
374 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); 394 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
375 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL); 395 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
376 if (!ri) 396 if (!ri)
@@ -382,40 +402,43 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
382 ri->pg0 = *pg0; /* add/update pg0 data */ 402 ri->pg0 = *pg0; /* add/update pg0 data */
383 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING; 403 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
384 404
405 /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
385 if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) { 406 if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
386 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED; 407 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
387 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); 408 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
388 rport = fc_remote_port_add(ioc->sh,channel, &rport_ids); 409 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
389 spin_lock_irqsave(&ioc->fc_rport_lock, flags); 410 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
390 if (rport) { 411 if (rport) {
391 if (*((struct mptfc_rport_info **)rport->dd_data) != ri) { 412 ri->rport = rport;
392 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV; 413 if (new_ri) /* may have been reset by user */
393 ri->vdev = NULL; 414 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
394 ri->rport = rport; 415 *((struct mptfc_rport_info **)rport->dd_data) = ri;
395 *((struct mptfc_rport_info **)rport->dd_data) = ri;
396 }
397 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
398 /* 416 /*
399 * if already mapped, remap here. If not mapped, 417 * if already mapped, remap here. If not mapped,
400 * slave_alloc will allocate vdev and map 418 * target_alloc will allocate vtarget and map,
419 * slave_alloc will fill in vdev from vtarget.
401 */ 420 */
402 if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) { 421 if (ri->starget) {
403 ri->vdev->target_id = ri->pg0.CurrentTargetID; 422 vtarget = ri->starget->hostdata;
404 ri->vdev->bus_id = ri->pg0.CurrentBus; 423 if (vtarget) {
405 ri->vdev->vtarget->target_id = ri->vdev->target_id; 424 vtarget->target_id = pg0->CurrentTargetID;
406 ri->vdev->vtarget->bus_id = ri->vdev->bus_id; 425 vtarget->bus_id = pg0->CurrentBus;
426 starget_for_each_device(ri->starget,
427 vtarget,mptfc_remap_sdev);
428 }
429 ri->remap_needed = 0;
407 } 430 }
408 #ifdef MPT_DEBUG 431 dfcprintk ((MYIOC_s_INFO_FMT
409 printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " 432 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
410 "rport tid %d, tmo %d\n", 433 "rport tid %d, tmo %d\n",
411 ioc->sh->host_no, 434 ioc->name,
435 oc->sh->host_no,
412 pg0->PortIdentifier, 436 pg0->PortIdentifier,
413 pg0->WWNN, 437 pg0->WWNN,
414 pg0->WWPN, 438 pg0->WWPN,
415 pg0->CurrentTargetID, 439 pg0->CurrentTargetID,
416 ri->rport->scsi_target_id, 440 ri->rport->scsi_target_id,
417 ri->rport->dev_loss_tmo); 441 ri->rport->dev_loss_tmo));
418 #endif
419 } else { 442 } else {
420 list_del(&ri->list); 443 list_del(&ri->list);
421 kfree(ri); 444 kfree(ri);
@@ -427,6 +450,65 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
427} 450}
428 451
429/* 452/*
453 * OS entry point to allow for host driver to free allocated memory
454 * Called if no device present or device being unloaded
455 */
456static void
457mptfc_target_destroy(struct scsi_target *starget)
458{
459 struct fc_rport *rport;
460 struct mptfc_rport_info *ri;
461
462 rport = starget_to_rport(starget);
463 if (rport) {
464 ri = *((struct mptfc_rport_info **)rport->dd_data);
465 if (ri) /* better be! */
466 ri->starget = NULL;
467 }
468 if (starget->hostdata)
469 kfree(starget->hostdata);
470 starget->hostdata = NULL;
471}
472
473/*
474 * OS entry point to allow host driver to alloc memory
475 * for each scsi target. Called once per device the bus scan.
476 * Return non-zero if allocation fails.
477 */
478static int
479mptfc_target_alloc(struct scsi_target *starget)
480{
481 VirtTarget *vtarget;
482 struct fc_rport *rport;
483 struct mptfc_rport_info *ri;
484 int rc;
485
486 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
487 if (!vtarget)
488 return -ENOMEM;
489 starget->hostdata = vtarget;
490
491 rc = -ENODEV;
492 rport = starget_to_rport(starget);
493 if (rport) {
494 ri = *((struct mptfc_rport_info **)rport->dd_data);
495 if (ri) { /* better be! */
496 vtarget->target_id = ri->pg0.CurrentTargetID;
497 vtarget->bus_id = ri->pg0.CurrentBus;
498 ri->starget = starget;
499 ri->remap_needed = 0;
500 rc = 0;
501 }
502 }
503 if (rc != 0) {
504 kfree(vtarget);
505 starget->hostdata = NULL;
506 }
507
508 return rc;
509}
510
511/*
430 * OS entry point to allow host driver to alloc memory 512 * OS entry point to allow host driver to alloc memory
431 * for each scsi device. Called once per device the bus scan. 513 * for each scsi device. Called once per device the bus scan.
432 * Return non-zero if allocation fails. 514 * Return non-zero if allocation fails.
@@ -440,7 +522,6 @@ mptfc_slave_alloc(struct scsi_device *sdev)
440 VirtDevice *vdev; 522 VirtDevice *vdev;
441 struct scsi_target *starget; 523 struct scsi_target *starget;
442 struct fc_rport *rport; 524 struct fc_rport *rport;
443 struct mptfc_rport_info *ri;
444 unsigned long flags; 525 unsigned long flags;
445 526
446 527
@@ -451,55 +532,44 @@ mptfc_slave_alloc(struct scsi_device *sdev)
451 532
452 hd = (MPT_SCSI_HOST *)sdev->host->hostdata; 533 hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
453 534
454 vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); 535 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
455 if (!vdev) { 536 if (!vdev) {
456 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", 537 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
457 hd->ioc->name, sizeof(VirtDevice)); 538 hd->ioc->name, sizeof(VirtDevice));
458 return -ENOMEM; 539 return -ENOMEM;
459 } 540 }
460 memset(vdev, 0, sizeof(VirtDevice));
461 541
462 spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags); 542 spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
463 543
464 if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
465 spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
466 kfree(vdev);
467 return -ENODEV;
468 }
469
470 sdev->hostdata = vdev; 544 sdev->hostdata = vdev;
471 starget = scsi_target(sdev); 545 starget = scsi_target(sdev);
472 vtarget = starget->hostdata; 546 vtarget = starget->hostdata;
547
473 if (vtarget->num_luns == 0) { 548 if (vtarget->num_luns == 0) {
549 vtarget->ioc_id = hd->ioc->id;
474 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES | 550 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
475 MPT_TARGET_FLAGS_VALID_INQUIRY; 551 MPT_TARGET_FLAGS_VALID_INQUIRY;
476 hd->Targets[sdev->id] = vtarget; 552 hd->Targets[sdev->id] = vtarget;
477 } 553 }
478 554
479 vtarget->target_id = vdev->target_id;
480 vtarget->bus_id = vdev->bus_id;
481
482 vdev->vtarget = vtarget; 555 vdev->vtarget = vtarget;
483 vdev->ioc_id = hd->ioc->id; 556 vdev->ioc_id = hd->ioc->id;
484 vdev->lun = sdev->lun; 557 vdev->lun = sdev->lun;
485 vdev->target_id = ri->pg0.CurrentTargetID; 558 vdev->target_id = vtarget->target_id;
486 vdev->bus_id = ri->pg0.CurrentBus; 559 vdev->bus_id = vtarget->bus_id;
487
488 ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
489 ri->vdev = vdev;
490 560
491 spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); 561 spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
492 562
493 vtarget->num_luns++; 563 vtarget->num_luns++;
494 564
495#ifdef MPT_DEBUG 565 dfcprintk ((MYIOC_s_INFO_FMT
496 printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " 566 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
497 "CurrentTargetID %d, %x %llx %llx\n", 567 "CurrentTargetID %d, %x %llx %llx\n",
498 sdev->host->host_no, 568 ioc->name,
499 vtarget->num_luns, 569 sdev->host->host_no,
500 sdev->id, ri->pg0.CurrentTargetID, 570 vtarget->num_luns,
501 ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN); 571 sdev->id, ri->pg0.CurrentTargetID,
502#endif 572 ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
503 573
504 return 0; 574 return 0;
505} 575}
@@ -507,6 +577,7 @@ mptfc_slave_alloc(struct scsi_device *sdev)
507static int 577static int
508mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) 578mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
509{ 579{
580 struct mptfc_rport_info *ri;
510 struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); 581 struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
511 int err; 582 int err;
512 583
@@ -516,6 +587,10 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
516 done(SCpnt); 587 done(SCpnt);
517 return 0; 588 return 0;
518 } 589 }
590 ri = *((struct mptfc_rport_info **)rport->dd_data);
591 if (unlikely(ri->remap_needed))
592 return SCSI_MLQUEUE_HOST_BUSY;
593
519 return mptscsih_qcmd(SCpnt,done); 594 return mptscsih_qcmd(SCpnt,done);
520} 595}
521 596
@@ -591,16 +666,20 @@ mptfc_rescan_devices(void *arg)
591 666
592 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| 667 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
593 MPT_RPORT_INFO_FLAGS_MISSING); 668 MPT_RPORT_INFO_FLAGS_MISSING);
669 ri->remap_needed = 1;
594 fc_remote_port_delete(ri->rport); 670 fc_remote_port_delete(ri->rport);
595 /* 671 /*
596 * remote port not really deleted 'cause 672 * remote port not really deleted 'cause
597 * binding is by WWPN and driver only 673 * binding is by WWPN and driver only
598 * registers FCP_TARGETs 674 * registers FCP_TARGETs but cannot trust
675 * data structures.
599 */ 676 */
600 #ifdef MPT_DEBUG 677 ri->rport = NULL;
601 printk ("mptfc_rescan.%d: %llx deleted\n", 678 dfcprintk ((MYIOC_s_INFO_FMT
602 ioc->sh->host_no, ri->pg0.WWPN); 679 "mptfc_rescan.%d: %llx deleted\n",
603 #endif 680 ioc->name,
681 ioc->sh->host_no,
682 ri->pg0.WWPN));
604 } 683 }
605 } 684 }
606 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); 685 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
@@ -872,9 +951,8 @@ mptfc_init(void)
872 } 951 }
873 952
874 error = pci_register_driver(&mptfc_driver); 953 error = pci_register_driver(&mptfc_driver);
875 if (error) { 954 if (error)
876 fc_release_transport(mptfc_transport_template); 955 fc_release_transport(mptfc_transport_template);
877 }
878 956
879 return error; 957 return error;
880} 958}
@@ -885,7 +963,8 @@ mptfc_init(void)
885 * @pdev: Pointer to pci_dev structure 963 * @pdev: Pointer to pci_dev structure
886 * 964 *
887 */ 965 */
888static void __devexit mptfc_remove(struct pci_dev *pdev) 966static void __devexit
967mptfc_remove(struct pci_dev *pdev)
889{ 968{
890 MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 969 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
891 struct mptfc_rport_info *p, *n; 970 struct mptfc_rport_info *p, *n;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 5a06d8d8694..2512d0e6155 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -89,6 +89,8 @@ static int mptsasMgmtCtx = -1;
89enum mptsas_hotplug_action { 89enum mptsas_hotplug_action {
90 MPTSAS_ADD_DEVICE, 90 MPTSAS_ADD_DEVICE,
91 MPTSAS_DEL_DEVICE, 91 MPTSAS_DEL_DEVICE,
92 MPTSAS_ADD_RAID,
93 MPTSAS_DEL_RAID,
92}; 94};
93 95
94struct mptsas_hotplug_event { 96struct mptsas_hotplug_event {
@@ -114,6 +116,7 @@ struct mptsas_hotplug_event {
114 116
115struct mptsas_devinfo { 117struct mptsas_devinfo {
116 u16 handle; /* unique id to address this device */ 118 u16 handle; /* unique id to address this device */
119 u16 handle_parent; /* unique id to address parent device */
117 u8 phy_id; /* phy number of parent device */ 120 u8 phy_id; /* phy number of parent device */
118 u8 port_id; /* sas physical port this device 121 u8 port_id; /* sas physical port this device
119 is assoc'd with */ 122 is assoc'd with */
@@ -301,9 +304,8 @@ mptsas_slave_alloc(struct scsi_device *sdev)
301 } 304 }
302 mutex_unlock(&hd->ioc->sas_topology_mutex); 305 mutex_unlock(&hd->ioc->sas_topology_mutex);
303 306
304 printk("No matching SAS device found!!\n");
305 kfree(vdev); 307 kfree(vdev);
306 return -ENODEV; 308 return -ENXIO;
307 309
308 out: 310 out:
309 vtarget->ioc_id = vdev->ioc_id; 311 vtarget->ioc_id = vdev->ioc_id;
@@ -321,6 +323,7 @@ mptsas_slave_destroy(struct scsi_device *sdev)
321 struct sas_rphy *rphy; 323 struct sas_rphy *rphy;
322 struct mptsas_portinfo *p; 324 struct mptsas_portinfo *p;
323 int i; 325 int i;
326 VirtDevice *vdev;
324 327
325 /* 328 /*
326 * Handle hotplug removal case. 329 * Handle hotplug removal case.
@@ -344,8 +347,29 @@ mptsas_slave_destroy(struct scsi_device *sdev)
344 out: 347 out:
345 mutex_unlock(&hd->ioc->sas_topology_mutex); 348 mutex_unlock(&hd->ioc->sas_topology_mutex);
346 /* 349 /*
347 * TODO: Issue target reset to flush firmware outstanding commands. 350 * Issue target reset to flush firmware outstanding commands.
348 */ 351 */
352 vdev = sdev->hostdata;
353 if (vdev->configured_lun){
354 if (mptscsih_TMHandler(hd,
355 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
356 vdev->bus_id,
357 vdev->target_id,
358 0, 0, 5 /* 5 second timeout */)
359 < 0){
360
361 /* The TM request failed!
362 * Fatal error case.
363 */
364 printk(MYIOC_s_WARN_FMT
365 "Error processing TaskMgmt id=%d TARGET_RESET\n",
366 hd->ioc->name,
367 vdev->target_id);
368
369 hd->tmPending = 0;
370 hd->tmState = TM_STATE_NONE;
371 }
372 }
349 mptscsih_slave_destroy(sdev); 373 mptscsih_slave_destroy(sdev);
350} 374}
351 375
@@ -714,6 +738,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
714 mptsas_print_device_pg0(buffer); 738 mptsas_print_device_pg0(buffer);
715 739
716 device_info->handle = le16_to_cpu(buffer->DevHandle); 740 device_info->handle = le16_to_cpu(buffer->DevHandle);
741 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
717 device_info->phy_id = buffer->PhyNum; 742 device_info->phy_id = buffer->PhyNum;
718 device_info->port_id = buffer->PhysicalPort; 743 device_info->port_id = buffer->PhysicalPort;
719 device_info->id = buffer->TargetID; 744 device_info->id = buffer->TargetID;
@@ -863,6 +888,26 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
863 return error; 888 return error;
864} 889}
865 890
891/*
892 * Returns true if there is a scsi end device
893 */
894static inline int
895mptsas_is_end_device(struct mptsas_devinfo * attached)
896{
897 if ((attached->handle) &&
898 (attached->device_info &
899 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
900 ((attached->device_info &
901 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
902 (attached->device_info &
903 MPI_SAS_DEVICE_INFO_STP_TARGET) |
904 (attached->device_info &
905 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
906 return 1;
907 else
908 return 0;
909}
910
866static void 911static void
867mptsas_parse_device_info(struct sas_identify *identify, 912mptsas_parse_device_info(struct sas_identify *identify,
868 struct mptsas_devinfo *device_info) 913 struct mptsas_devinfo *device_info)
@@ -1227,7 +1272,7 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1227} 1272}
1228 1273
1229static struct mptsas_phyinfo * 1274static struct mptsas_phyinfo *
1230mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) 1275mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
1231{ 1276{
1232 struct mptsas_portinfo *port_info; 1277 struct mptsas_portinfo *port_info;
1233 struct mptsas_phyinfo *phy_info = NULL; 1278 struct mptsas_phyinfo *phy_info = NULL;
@@ -1239,12 +1284,12 @@ mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
1239 */ 1284 */
1240 mutex_lock(&ioc->sas_topology_mutex); 1285 mutex_lock(&ioc->sas_topology_mutex);
1241 list_for_each_entry(port_info, &ioc->sas_topology, list) { 1286 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1242 for (i = 0; i < port_info->num_phys; i++) { 1287 for (i = 0; i < port_info->num_phys; i++)
1243 if (port_info->phy_info[i].attached.handle == handle) { 1288 if (mptsas_is_end_device(&port_info->phy_info[i].attached))
1244 phy_info = &port_info->phy_info[i]; 1289 if (port_info->phy_info[i].attached.id == id) {
1245 break; 1290 phy_info = &port_info->phy_info[i];
1246 } 1291 break;
1247 } 1292 }
1248 } 1293 }
1249 mutex_unlock(&ioc->sas_topology_mutex); 1294 mutex_unlock(&ioc->sas_topology_mutex);
1250 1295
@@ -1258,36 +1303,58 @@ mptsas_hotplug_work(void *arg)
1258 MPT_ADAPTER *ioc = ev->ioc; 1303 MPT_ADAPTER *ioc = ev->ioc;
1259 struct mptsas_phyinfo *phy_info; 1304 struct mptsas_phyinfo *phy_info;
1260 struct sas_rphy *rphy; 1305 struct sas_rphy *rphy;
1306 struct scsi_device *sdev;
1261 char *ds = NULL; 1307 char *ds = NULL;
1262 1308 struct mptsas_devinfo sas_device;
1263 if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1264 ds = "ssp";
1265 if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1266 ds = "stp";
1267 if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1268 ds = "sata";
1269 1309
1270 switch (ev->event_type) { 1310 switch (ev->event_type) {
1271 case MPTSAS_DEL_DEVICE: 1311 case MPTSAS_DEL_DEVICE:
1272 printk(MYIOC_s_INFO_FMT
1273 "removing %s device, channel %d, id %d, phy %d\n",
1274 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1275 1312
1276 phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle); 1313 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
1277 if (!phy_info) { 1314 if (!phy_info) {
1278 printk("mptsas: remove event for non-existant PHY.\n"); 1315 printk("mptsas: remove event for non-existant PHY.\n");
1279 break; 1316 break;
1280 } 1317 }
1281 1318
1319 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1320 ds = "ssp";
1321 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1322 ds = "stp";
1323 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1324 ds = "sata";
1325
1326 printk(MYIOC_s_INFO_FMT
1327 "removing %s device, channel %d, id %d, phy %d\n",
1328 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
1329
1282 if (phy_info->rphy) { 1330 if (phy_info->rphy) {
1283 sas_rphy_delete(phy_info->rphy); 1331 sas_rphy_delete(phy_info->rphy);
1284 phy_info->rphy = NULL; 1332 phy_info->rphy = NULL;
1285 } 1333 }
1286 break; 1334 break;
1287 case MPTSAS_ADD_DEVICE: 1335 case MPTSAS_ADD_DEVICE:
1288 printk(MYIOC_s_INFO_FMT 1336
1289 "attaching %s device, channel %d, id %d, phy %d\n", 1337 /*
1290 ioc->name, ds, ev->channel, ev->id, ev->phy_id); 1338 * When there is no sas address,
1339 * RAID volumes are being deleted,
1340 * and hidden phy disk are being added.
1341 * We don't know the SAS data yet,
1342 * so lookup sas device page to get
1343 * pertaining info
1344 */
1345 if (!ev->sas_address) {
1346 if (mptsas_sas_device_pg0(ioc,
1347 &sas_device, ev->id,
1348 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1349 MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))
1350 break;
1351 ev->handle = sas_device.handle;
1352 ev->parent_handle = sas_device.handle_parent;
1353 ev->channel = sas_device.channel;
1354 ev->phy_id = sas_device.phy_id;
1355 ev->sas_address = sas_device.sas_address;
1356 ev->device_info = sas_device.device_info;
1357 }
1291 1358
1292 phy_info = mptsas_find_phyinfo_by_parent(ioc, 1359 phy_info = mptsas_find_phyinfo_by_parent(ioc,
1293 ev->parent_handle, ev->phy_id); 1360 ev->parent_handle, ev->phy_id);
@@ -1310,10 +1377,23 @@ mptsas_hotplug_work(void *arg)
1310 phy_info->attached.sas_address = ev->sas_address; 1377 phy_info->attached.sas_address = ev->sas_address;
1311 phy_info->attached.device_info = ev->device_info; 1378 phy_info->attached.device_info = ev->device_info;
1312 1379
1380 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1381 ds = "ssp";
1382 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1383 ds = "stp";
1384 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1385 ds = "sata";
1386
1387 printk(MYIOC_s_INFO_FMT
1388 "attaching %s device, channel %d, id %d, phy %d\n",
1389 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1390
1391
1313 rphy = sas_rphy_alloc(phy_info->phy); 1392 rphy = sas_rphy_alloc(phy_info->phy);
1314 if (!rphy) 1393 if (!rphy)
1315 break; /* non-fatal: an rphy can be added later */ 1394 break; /* non-fatal: an rphy can be added later */
1316 1395
1396 rphy->scsi_target_id = phy_info->attached.id;
1317 mptsas_parse_device_info(&rphy->identify, &phy_info->attached); 1397 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1318 if (sas_rphy_add(rphy)) { 1398 if (sas_rphy_add(rphy)) {
1319 sas_rphy_free(rphy); 1399 sas_rphy_free(rphy);
@@ -1322,6 +1402,40 @@ mptsas_hotplug_work(void *arg)
1322 1402
1323 phy_info->rphy = rphy; 1403 phy_info->rphy = rphy;
1324 break; 1404 break;
1405 case MPTSAS_ADD_RAID:
1406 sdev = scsi_device_lookup(
1407 ioc->sh,
1408 ioc->num_ports,
1409 ev->id,
1410 0);
1411 if (sdev) {
1412 scsi_device_put(sdev);
1413 break;
1414 }
1415 printk(MYIOC_s_INFO_FMT
1416 "attaching device, channel %d, id %d\n",
1417 ioc->name, ioc->num_ports, ev->id);
1418 scsi_add_device(ioc->sh,
1419 ioc->num_ports,
1420 ev->id,
1421 0);
1422 mpt_findImVolumes(ioc);
1423 break;
1424 case MPTSAS_DEL_RAID:
1425 sdev = scsi_device_lookup(
1426 ioc->sh,
1427 ioc->num_ports,
1428 ev->id,
1429 0);
1430 if (!sdev)
1431 break;
1432 printk(MYIOC_s_INFO_FMT
1433 "removing device, channel %d, id %d\n",
1434 ioc->name, ioc->num_ports, ev->id);
1435 scsi_remove_device(sdev);
1436 scsi_device_put(sdev);
1437 mpt_findImVolumes(ioc);
1438 break;
1325 } 1439 }
1326 1440
1327 kfree(ev); 1441 kfree(ev);
@@ -1372,23 +1486,94 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1372 schedule_work(&ev->work); 1486 schedule_work(&ev->work);
1373} 1487}
1374 1488
1489static void
1490mptscsih_send_raid_event(MPT_ADAPTER *ioc,
1491 EVENT_DATA_RAID *raid_event_data)
1492{
1493 struct mptsas_hotplug_event *ev;
1494 RAID_VOL0_STATUS * volumeStatus;
1495
1496 if (ioc->bus_type != SAS)
1497 return;
1498
1499 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1500 if (!ev) {
1501 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1502 return;
1503 }
1504
1505 memset(ev,0,sizeof(struct mptsas_hotplug_event));
1506 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1507 ev->ioc = ioc;
1508 ev->id = raid_event_data->VolumeID;
1509
1510 switch (raid_event_data->ReasonCode) {
1511 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
1512 ev->event_type = MPTSAS_ADD_DEVICE;
1513 break;
1514 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
1515 ev->event_type = MPTSAS_DEL_DEVICE;
1516 break;
1517 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
1518 ev->event_type = MPTSAS_DEL_RAID;
1519 break;
1520 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
1521 ev->event_type = MPTSAS_ADD_RAID;
1522 break;
1523 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
1524 volumeStatus = (RAID_VOL0_STATUS *) &
1525 raid_event_data->SettingsStatus;
1526 ev->event_type = (volumeStatus->State ==
1527 MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
1528 MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
1529 break;
1530 default:
1531 break;
1532 }
1533 schedule_work(&ev->work);
1534}
1535
1536/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1537/* work queue thread to clear the persitency table */
1538static void
1539mptscsih_sas_persist_clear_table(void * arg)
1540{
1541 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
1542
1543 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
1544}
1545
1375static int 1546static int
1376mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) 1547mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1377{ 1548{
1549 int rc=1;
1378 u8 event = le32_to_cpu(reply->Event) & 0xFF; 1550 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1379 1551
1380 if (!ioc->sh) 1552 if (!ioc->sh)
1381 return 1; 1553 goto out;
1382 1554
1383 switch (event) { 1555 switch (event) {
1384 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: 1556 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1385 mptscsih_send_sas_event(ioc, 1557 mptscsih_send_sas_event(ioc,
1386 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); 1558 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
1387 return 1; /* currently means nothing really */ 1559 break;
1388 1560 case MPI_EVENT_INTEGRATED_RAID:
1561 mptscsih_send_raid_event(ioc,
1562 (EVENT_DATA_RAID *)reply->Data);
1563 break;
1564 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1565 INIT_WORK(&ioc->mptscsih_persistTask,
1566 mptscsih_sas_persist_clear_table,
1567 (void *)ioc);
1568 schedule_work(&ioc->mptscsih_persistTask);
1569 break;
1389 default: 1570 default:
1390 return mptscsih_event_process(ioc, reply); 1571 rc = mptscsih_event_process(ioc, reply);
1572 break;
1391 } 1573 }
1574 out:
1575
1576 return rc;
1392} 1577}
1393 1578
1394static int 1579static int
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index cdac5578fdf..05789e50546 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -144,7 +144,6 @@ static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
144static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); 144static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
145static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); 145static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
146 146
147static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
148static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); 147static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
149 148
150int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); 149int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
@@ -159,11 +158,9 @@ static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
159int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); 158int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
160static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); 159static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
161static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); 160static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
162static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget); 161static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
163static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); 162static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
164 163
165static struct work_struct mptscsih_persistTask;
166
167#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION 164#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
168static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); 165static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
169static void mptscsih_domainValidation(void *hd); 166static void mptscsih_domainValidation(void *hd);
@@ -563,11 +560,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
563 MPT_SCSI_HOST *hd; 560 MPT_SCSI_HOST *hd;
564 SCSIIORequest_t *pScsiReq; 561 SCSIIORequest_t *pScsiReq;
565 SCSIIOReply_t *pScsiReply; 562 SCSIIOReply_t *pScsiReply;
566 u16 req_idx; 563 u16 req_idx, req_idx_MR;
567 564
568 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; 565 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
569 566
570 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); 567 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
568 req_idx_MR = (mr != NULL) ?
569 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
570 if ((req_idx != req_idx_MR) ||
571 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
572 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
573 ioc->name);
574 printk (MYIOC_s_ERR_FMT
575 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
576 ioc->name, req_idx, req_idx_MR, mf, mr,
577 hd->ScsiLookup[req_idx_MR]);
578 return 0;
579 }
580
571 sc = hd->ScsiLookup[req_idx]; 581 sc = hd->ScsiLookup[req_idx];
572 if (sc == NULL) { 582 if (sc == NULL) {
573 MPIHeader_t *hdr = (MPIHeader_t *)mf; 583 MPIHeader_t *hdr = (MPIHeader_t *)mf;
@@ -730,6 +740,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
730 740
731 break; 741 break;
732 742
743 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
744 sc->resid=0;
733 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ 745 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
734 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ 746 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
735 if (scsi_status == MPI_SCSI_STATUS_BUSY) 747 if (scsi_status == MPI_SCSI_STATUS_BUSY)
@@ -789,7 +801,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
789 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ 801 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
790 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ 802 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
791 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ 803 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
792 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
793 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ 804 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
794 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ 805 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
795 default: 806 default:
@@ -1530,7 +1541,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1530 * 1541 *
1531 * Returns 0 for SUCCESS or -1 if FAILED. 1542 * Returns 0 for SUCCESS or -1 if FAILED.
1532 */ 1543 */
1533static int 1544int
1534mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) 1545mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1535{ 1546{
1536 MPT_ADAPTER *ioc; 1547 MPT_ADAPTER *ioc;
@@ -1721,6 +1732,20 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
1721 return retval; 1732 return retval;
1722} 1733}
1723 1734
1735static int
1736mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1737{
1738 switch (ioc->bus_type) {
1739 case FC:
1740 return 40;
1741 case SAS:
1742 return 10;
1743 case SPI:
1744 default:
1745 return 2;
1746 }
1747}
1748
1724/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1749/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1725/** 1750/**
1726 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant 1751 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
@@ -1792,7 +1817,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1792 vdev = SCpnt->device->hostdata; 1817 vdev = SCpnt->device->hostdata;
1793 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, 1818 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1794 vdev->bus_id, vdev->target_id, vdev->lun, 1819 vdev->bus_id, vdev->target_id, vdev->lun,
1795 ctx2abort, 2 /* 2 second timeout */); 1820 ctx2abort, mptscsih_get_tm_timeout(ioc));
1796 1821
1797 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", 1822 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1798 hd->ioc->name, 1823 hd->ioc->name,
@@ -1843,7 +1868,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1843 vdev = SCpnt->device->hostdata; 1868 vdev = SCpnt->device->hostdata;
1844 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 1869 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1845 vdev->bus_id, vdev->target_id, 1870 vdev->bus_id, vdev->target_id,
1846 0, 0, 5 /* 5 second timeout */); 1871 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1847 1872
1848 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", 1873 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1849 hd->ioc->name, 1874 hd->ioc->name,
@@ -1893,7 +1918,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1893 1918
1894 vdev = SCpnt->device->hostdata; 1919 vdev = SCpnt->device->hostdata;
1895 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, 1920 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1896 vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */); 1921 vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1897 1922
1898 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", 1923 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1899 hd->ioc->name, 1924 hd->ioc->name,
@@ -2016,6 +2041,42 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2016} 2041}
2017 2042
2018/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 2043/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2044static void
2045mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2046{
2047 char *desc;
2048
2049 switch (response_code) {
2050 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2051 desc = "The task completed.";
2052 break;
2053 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2054 desc = "The IOC received an invalid frame status.";
2055 break;
2056 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2057 desc = "The task type is not supported.";
2058 break;
2059 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2060 desc = "The requested task failed.";
2061 break;
2062 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2063 desc = "The task completed successfully.";
2064 break;
2065 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2066 desc = "The LUN request is invalid.";
2067 break;
2068 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2069 desc = "The task is in the IOC queue and has not been sent to target.";
2070 break;
2071 default:
2072 desc = "unknown";
2073 break;
2074 }
2075 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2076 ioc->name, response_code, desc);
2077}
2078
2079/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2019/** 2080/**
2020 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver 2081 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2021 * @ioc: Pointer to MPT_ADAPTER structure 2082 * @ioc: Pointer to MPT_ADAPTER structure
@@ -2064,6 +2125,11 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
2064 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */ 2125 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2065 tmType = pScsiTmReq->TaskType; 2126 tmType = pScsiTmReq->TaskType;
2066 2127
2128 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2129 pScsiTmReply->ResponseCode)
2130 mptscsih_taskmgmt_response_code(ioc,
2131 pScsiTmReply->ResponseCode);
2132
2067 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n", 2133 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2068 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); 2134 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2069 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); 2135 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
@@ -2255,7 +2321,7 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
2255 vtarget->luns[0] &= ~(1 << vdevice->lun); 2321 vtarget->luns[0] &= ~(1 << vdevice->lun);
2256 vtarget->num_luns--; 2322 vtarget->num_luns--;
2257 if (vtarget->num_luns == 0) { 2323 if (vtarget->num_luns == 0) {
2258 mptscsih_negotiate_to_asyn_narrow(hd, vtarget); 2324 mptscsih_negotiate_to_asyn_narrow(hd, vdevice);
2259 if (hd->ioc->bus_type == SPI) { 2325 if (hd->ioc->bus_type == SPI) {
2260 if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) { 2326 if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) {
2261 hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; 2327 hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
@@ -2585,16 +2651,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2585} 2651}
2586 2652
2587/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 2653/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2588/* work queue thread to clear the persitency table */
2589static void
2590mptscsih_sas_persist_clear_table(void * arg)
2591{
2592 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
2593
2594 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2595}
2596
2597/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2598int 2654int
2599mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) 2655mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2600{ 2656{
@@ -2656,13 +2712,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2656 break; 2712 break;
2657 } 2713 }
2658 2714
2659 /* Persistent table is full. */
2660 case MPI_EVENT_PERSISTENT_TABLE_FULL:
2661 INIT_WORK(&mptscsih_persistTask,
2662 mptscsih_sas_persist_clear_table,(void *)ioc);
2663 schedule_work(&mptscsih_persistTask);
2664 break;
2665
2666 case MPI_EVENT_NONE: /* 00 */ 2715 case MPI_EVENT_NONE: /* 00 */
2667 case MPI_EVENT_LOG_DATA: /* 01 */ 2716 case MPI_EVENT_LOG_DATA: /* 01 */
2668 case MPI_EVENT_STATE_CHANGE: /* 02 */ 2717 case MPI_EVENT_STATE_CHANGE: /* 02 */
@@ -3863,8 +3912,9 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3863 * 3912 *
3864 */ 3913 */
3865static void 3914static void
3866mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget) 3915mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3867{ 3916{
3917 VirtTarget *vtarget = vdevice->vtarget;
3868 MPT_ADAPTER *ioc= hd->ioc; 3918 MPT_ADAPTER *ioc= hd->ioc;
3869 SCSIDevicePage1_t *pcfg1Data; 3919 SCSIDevicePage1_t *pcfg1Data;
3870 CONFIGPARMS cfg; 3920 CONFIGPARMS cfg;
@@ -3874,7 +3924,8 @@ mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
3874 int requested, configuration, data,i; 3924 int requested, configuration, data,i;
3875 u8 flags, factor; 3925 u8 flags, factor;
3876 3926
3877 if (ioc->bus_type != SPI) 3927 if ((ioc->bus_type != SPI) ||
3928 (!vdevice->configured_lun))
3878 return; 3929 return;
3879 3930
3880 if (!ioc->spi_data.sdp1length) 3931 if (!ioc->spi_data.sdp1length)
@@ -3910,7 +3961,7 @@ mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
3910 } 3961 }
3911 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, 3962 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
3912 &configuration, flags); 3963 &configuration, flags);
3913 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC " 3964 dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC "
3914 "offset=0 negoFlags=%x request=%x config=%x\n", 3965 "offset=0 negoFlags=%x request=%x config=%x\n",
3915 id, flags, requested, configuration)); 3966 id, flags, requested, configuration));
3916 pcfg1Data->RequestedParameters = cpu_to_le32(requested); 3967 pcfg1Data->RequestedParameters = cpu_to_le32(requested);
@@ -3923,7 +3974,7 @@ mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
3923 flags = vtarget->negoFlags; 3974 flags = vtarget->negoFlags;
3924 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, 3975 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
3925 &configuration, flags); 3976 &configuration, flags);
3926 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC " 3977 dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC "
3927 "offset=0 negoFlags=%x request=%x config=%x\n", 3978 "offset=0 negoFlags=%x request=%x config=%x\n",
3928 vtarget->target_id, flags, requested, configuration)); 3979 vtarget->target_id, flags, requested, configuration));
3929 pcfg1Data->RequestedParameters = cpu_to_le32(requested); 3980 pcfg1Data->RequestedParameters = cpu_to_le32(requested);
@@ -5620,5 +5671,6 @@ EXPORT_SYMBOL(mptscsih_event_process);
5620EXPORT_SYMBOL(mptscsih_ioc_reset); 5671EXPORT_SYMBOL(mptscsih_ioc_reset);
5621EXPORT_SYMBOL(mptscsih_change_queue_depth); 5672EXPORT_SYMBOL(mptscsih_change_queue_depth);
5622EXPORT_SYMBOL(mptscsih_timer_expired); 5673EXPORT_SYMBOL(mptscsih_timer_expired);
5674EXPORT_SYMBOL(mptscsih_TMHandler);
5623 5675
5624/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 5676/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index d3cba12f4bd..44b248d51ea 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -108,3 +108,4 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE
108extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); 108extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
109extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); 109extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
110extern void mptscsih_timer_expired(unsigned long data); 110extern void mptscsih_timer_expired(unsigned long data);
111extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 7dce29277cb..f148dfa3911 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -384,6 +384,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
384 goto out_mptspi_probe; 384 goto out_mptspi_probe;
385 } 385 }
386 386
387 /*
388 * issue internal bus reset
389 */
390 if (ioc->spi_data.bus_reset)
391 mptscsih_TMHandler(hd,
392 MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
393 0, 0, 0, 0, 5);
394
387 scsi_scan_host(sh); 395 scsi_scan_host(sh);
388 return 0; 396 return 0;
389 397
@@ -445,7 +453,7 @@ static void __exit
445mptspi_exit(void) 453mptspi_exit(void)
446{ 454{
447 pci_unregister_driver(&mptspi_driver); 455 pci_unregister_driver(&mptspi_driver);
448 456
449 mpt_reset_deregister(mptspiDoneCtx); 457 mpt_reset_deregister(mptspiDoneCtx);
450 dprintk((KERN_INFO MYNAM 458 dprintk((KERN_INFO MYNAM
451 ": Deregistered for IOC reset notifications\n")); 459 ": Deregistered for IOC reset notifications\n"));