diff options
Diffstat (limited to 'drivers/message')
-rw-r--r-- | drivers/message/fusion/Makefile | 2 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.c | 184 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 16 | ||||
-rw-r--r-- | drivers/message/fusion/mptfc.c | 203 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 241 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 116 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.h | 1 | ||||
-rw-r--r-- | drivers/message/fusion/mptspi.c | 10 | ||||
-rw-r--r-- | drivers/message/i2o/core.h | 3 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_scsi.c | 2 | ||||
-rw-r--r-- | drivers/message/i2o/pci.c | 47 |
11 files changed, 672 insertions, 153 deletions
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 8a2e2657f4c2..33ace373241c 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 d890b2b8a93e..9a2c7605d49c 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 | */ |
84 | static int mpt_msi_enable; | ||
85 | module_param(mpt_msi_enable, int, 0); | ||
86 | MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)"); | ||
87 | |||
84 | #ifdef MFCNT | 88 | #ifdef MFCNT |
85 | static int mfcounter = 0; | 89 | static 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); | |||
174 | static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); | 178 | static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); |
175 | static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); | 179 | static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); |
176 | static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); | 180 | static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); |
177 | static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); | 181 | static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); |
178 | static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); | 182 | static 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 | |||
4411 | static void | ||
4412 | mptbase_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 | */ |
6056 | static void | 6220 | static void |
6057 | mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) | 6221 | mpt_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 47053ac65068..ea2649ecad1f 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 b102c7666d0e..c3a3499bce2a 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
@@ -93,10 +93,11 @@ static int mptfcDoneCtx = -1; | |||
93 | static int mptfcTaskCtx = -1; | 93 | static int mptfcTaskCtx = -1; |
94 | static int mptfcInternalCtx = -1; /* Used only for internal commands */ | 94 | static int mptfcInternalCtx = -1; /* Used only for internal commands */ |
95 | 95 | ||
96 | int mptfc_slave_alloc(struct scsi_device *device); | 96 | static int mptfc_target_alloc(struct scsi_target *starget); |
97 | static int mptfc_slave_alloc(struct scsi_device *sdev); | ||
97 | static int mptfc_qcmd(struct scsi_cmnd *SCpnt, | 98 | static int mptfc_qcmd(struct scsi_cmnd *SCpnt, |
98 | void (*done)(struct scsi_cmnd *)); | 99 | void (*done)(struct scsi_cmnd *)); |
99 | 100 | static void mptfc_target_destroy(struct scsi_target *starget); | |
100 | static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); | 101 | static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); |
101 | static void __devexit mptfc_remove(struct pci_dev *pdev); | 102 | static 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 | ||
350 | static void | 351 | static void |
352 | mptfc_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 | |||
369 | static void | ||
351 | mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | 370 | mptfc_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 | */ | ||
456 | static void | ||
457 | mptfc_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 | */ | ||
478 | static int | ||
479 | mptfc_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) | |||
507 | static int | 577 | static int |
508 | mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | 578 | mptfc_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 | */ |
888 | static void __devexit mptfc_remove(struct pci_dev *pdev) | 966 | static void __devexit |
967 | mptfc_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 5a06d8d8694e..2512d0e6155e 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
@@ -89,6 +89,8 @@ static int mptsasMgmtCtx = -1; | |||
89 | enum mptsas_hotplug_action { | 89 | enum 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 | ||
94 | struct mptsas_hotplug_event { | 96 | struct mptsas_hotplug_event { |
@@ -114,6 +116,7 @@ struct mptsas_hotplug_event { | |||
114 | 116 | ||
115 | struct mptsas_devinfo { | 117 | struct 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 | */ | ||
894 | static inline int | ||
895 | mptsas_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 | |||
866 | static void | 911 | static void |
867 | mptsas_parse_device_info(struct sas_identify *identify, | 912 | mptsas_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 | ||
1229 | static struct mptsas_phyinfo * | 1274 | static struct mptsas_phyinfo * |
1230 | mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) | 1275 | mptsas_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 | ||
1489 | static void | ||
1490 | mptscsih_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 */ | ||
1538 | static void | ||
1539 | mptscsih_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 | |||
1375 | static int | 1546 | static int |
1376 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | 1547 | mptsas_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 | ||
1394 | static int | 1579 | static int |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index cdac5578fdf2..05789e505464 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); | |||
144 | static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); | 144 | static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); |
145 | static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); | 145 | static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); |
146 | 146 | ||
147 | static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); | ||
148 | static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); | 147 | static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); |
149 | 148 | ||
150 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | 149 | int 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); | |||
159 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); | 158 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); |
160 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); | 159 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); |
161 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); | 160 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); |
162 | static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget); | 161 | static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice); |
163 | static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); | 162 | static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); |
164 | 163 | ||
165 | static struct work_struct mptscsih_persistTask; | ||
166 | |||
167 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | 164 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION |
168 | static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); | 165 | static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); |
169 | static void mptscsih_domainValidation(void *hd); | 166 | static 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 | */ |
1533 | static int | 1544 | int |
1534 | mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) | 1545 | mptscsih_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 | ||
1735 | static int | ||
1736 | mptscsih_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 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
2044 | static void | ||
2045 | mptscsih_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 */ | ||
2589 | static void | ||
2590 | mptscsih_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 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
2598 | int | 2654 | int |
2599 | mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | 2655 | mptscsih_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 | */ |
3865 | static void | 3914 | static void |
3866 | mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget) | 3915 | mptscsih_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); | |||
5620 | EXPORT_SYMBOL(mptscsih_ioc_reset); | 5671 | EXPORT_SYMBOL(mptscsih_ioc_reset); |
5621 | EXPORT_SYMBOL(mptscsih_change_queue_depth); | 5672 | EXPORT_SYMBOL(mptscsih_change_queue_depth); |
5622 | EXPORT_SYMBOL(mptscsih_timer_expired); | 5673 | EXPORT_SYMBOL(mptscsih_timer_expired); |
5674 | EXPORT_SYMBOL(mptscsih_TMHandler); | ||
5623 | 5675 | ||
5624 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 5676 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index d3cba12f4bd9..44b248d51ea3 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 | |||
108 | extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | 108 | extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); |
109 | extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); | 109 | extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); |
110 | extern void mptscsih_timer_expired(unsigned long data); | 110 | extern void mptscsih_timer_expired(unsigned long data); |
111 | extern 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 7dce29277cb7..f148dfa39117 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 | |||
445 | mptspi_exit(void) | 453 | mptspi_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")); |
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h index 90628562851e..184974cc734d 100644 --- a/drivers/message/i2o/core.h +++ b/drivers/message/i2o/core.h | |||
@@ -60,4 +60,7 @@ extern void i2o_iop_remove(struct i2o_controller *); | |||
60 | #define I2O_IN_PORT 0x40 | 60 | #define I2O_IN_PORT 0x40 |
61 | #define I2O_OUT_PORT 0x44 | 61 | #define I2O_OUT_PORT 0x44 |
62 | 62 | ||
63 | /* Motorola/Freescale specific register offset */ | ||
64 | #define I2O_MOTOROLA_PORT_OFFSET 0x10400 | ||
65 | |||
63 | #define I2O_IRQ_OUTBOUND_POST 0x00000008 | 66 | #define I2O_IRQ_OUTBOUND_POST 0x00000008 |
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index f9e5a23697a1..c08ddac3717d 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c | |||
@@ -732,7 +732,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) | |||
732 | cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); | 732 | cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); |
733 | msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); | 733 | msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); |
734 | 734 | ||
735 | if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) | 735 | if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) |
736 | status = SUCCESS; | 736 | status = SUCCESS; |
737 | 737 | ||
738 | return status; | 738 | return status; |
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index d698d7709c31..4f1515cae5dc 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c | |||
@@ -88,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
88 | struct device *dev = &pdev->dev; | 88 | struct device *dev = &pdev->dev; |
89 | int i; | 89 | int i; |
90 | 90 | ||
91 | if (pci_request_regions(pdev, OSM_DESCRIPTION)) { | ||
92 | printk(KERN_ERR "%s: device already claimed\n", c->name); | ||
93 | return -ENODEV; | ||
94 | } | ||
95 | |||
91 | for (i = 0; i < 6; i++) { | 96 | for (i = 0; i < 6; i++) { |
92 | /* Skip I/O spaces */ | 97 | /* Skip I/O spaces */ |
93 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { | 98 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { |
@@ -163,6 +168,24 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
163 | c->in_port = c->base.virt + I2O_IN_PORT; | 168 | c->in_port = c->base.virt + I2O_IN_PORT; |
164 | c->out_port = c->base.virt + I2O_OUT_PORT; | 169 | c->out_port = c->base.virt + I2O_OUT_PORT; |
165 | 170 | ||
171 | /* Motorola/Freescale chip does not follow spec */ | ||
172 | if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) { | ||
173 | /* Check if CPU is enabled */ | ||
174 | if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) { | ||
175 | printk(KERN_INFO "%s: MPC82XX needs CPU running to " | ||
176 | "service I2O.\n", c->name); | ||
177 | i2o_pci_free(c); | ||
178 | return -ENODEV; | ||
179 | } else { | ||
180 | c->irq_status += I2O_MOTOROLA_PORT_OFFSET; | ||
181 | c->irq_mask += I2O_MOTOROLA_PORT_OFFSET; | ||
182 | c->in_port += I2O_MOTOROLA_PORT_OFFSET; | ||
183 | c->out_port += I2O_MOTOROLA_PORT_OFFSET; | ||
184 | printk(KERN_INFO "%s: MPC82XX workarounds activated.\n", | ||
185 | c->name); | ||
186 | } | ||
187 | } | ||
188 | |||
166 | if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { | 189 | if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { |
167 | i2o_pci_free(c); | 190 | i2o_pci_free(c); |
168 | return -ENOMEM; | 191 | return -ENOMEM; |
@@ -298,7 +321,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
298 | struct i2o_controller *c; | 321 | struct i2o_controller *c; |
299 | int rc; | 322 | int rc; |
300 | struct pci_dev *i960 = NULL; | 323 | struct pci_dev *i960 = NULL; |
301 | int pci_dev_busy = 0; | 324 | int enabled = pdev->is_enabled; |
302 | 325 | ||
303 | printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); | 326 | printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); |
304 | 327 | ||
@@ -308,16 +331,12 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
308 | return -ENODEV; | 331 | return -ENODEV; |
309 | } | 332 | } |
310 | 333 | ||
311 | if ((rc = pci_enable_device(pdev))) { | 334 | if (!enabled) |
312 | printk(KERN_WARNING "i2o: couldn't enable device %s\n", | 335 | if ((rc = pci_enable_device(pdev))) { |
313 | pci_name(pdev)); | 336 | printk(KERN_WARNING "i2o: couldn't enable device %s\n", |
314 | return rc; | 337 | pci_name(pdev)); |
315 | } | 338 | return rc; |
316 | 339 | } | |
317 | if (pci_request_regions(pdev, OSM_DESCRIPTION)) { | ||
318 | printk(KERN_ERR "i2o: device already claimed\n"); | ||
319 | return -ENODEV; | ||
320 | } | ||
321 | 340 | ||
322 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | 341 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { |
323 | printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", | 342 | printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", |
@@ -395,9 +414,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
395 | 414 | ||
396 | if ((rc = i2o_pci_alloc(c))) { | 415 | if ((rc = i2o_pci_alloc(c))) { |
397 | printk(KERN_ERR "%s: DMA / IO allocation for I2O controller " | 416 | printk(KERN_ERR "%s: DMA / IO allocation for I2O controller " |
398 | " failed\n", c->name); | 417 | "failed\n", c->name); |
399 | if (rc == -ENODEV) | ||
400 | pci_dev_busy = 1; | ||
401 | goto free_controller; | 418 | goto free_controller; |
402 | } | 419 | } |
403 | 420 | ||
@@ -425,7 +442,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
425 | i2o_iop_free(c); | 442 | i2o_iop_free(c); |
426 | 443 | ||
427 | disable: | 444 | disable: |
428 | if (!pci_dev_busy) | 445 | if (!enabled) |
429 | pci_disable_device(pdev); | 446 | pci_disable_device(pdev); |
430 | 447 | ||
431 | return rc; | 448 | return rc; |