diff options
author | James Bottomley <James.Bottomley@steeleye.com> | 2006-03-01 10:02:49 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-03-01 10:44:04 -0500 |
commit | c92f222e1f14588171e63b550ca8c85fa9130061 (patch) | |
tree | 83db58755951518865324ac880fc321e516755b9 /drivers/message/fusion | |
parent | 3ef0b47ee498ea183bffd9b3b4a1eef757fef4ba (diff) |
[SCSI] mptspi: Add transport class Domain Validation
This is the first half of a patch to add the generic domain validation
to mptspi. It also creates a secondary "virtual" channel for raid
component devices since these are now exported with no_uld_attach.
What Eric and I would have really liked is to export all physical
components on channel 0 and all raid components on channel 1.
Unfortunately, this would result in device renumbering on platforms with
mixed RAID/Physical devices which was considered unacceptable for
userland stability reasons.
Still to be done is to plug back the extra parameter setting and DV
pieces on reset and hotplug.
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r-- | drivers/message/fusion/Kconfig | 1 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.c | 72 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 14 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 2402 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.h | 11 | ||||
-rw-r--r-- | drivers/message/fusion/mptspi.c | 733 |
6 files changed, 774 insertions, 2459 deletions
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index e67cf15e9c39..bbc229852881 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig | |||
@@ -9,6 +9,7 @@ config FUSION_SPI | |||
9 | tristate "Fusion MPT ScsiHost drivers for SPI" | 9 | tristate "Fusion MPT ScsiHost drivers for SPI" |
10 | depends on PCI && SCSI | 10 | depends on PCI && SCSI |
11 | select FUSION | 11 | select FUSION |
12 | select SCSI_SPI_ATTRS | ||
12 | ---help--- | 13 | ---help--- |
13 | SCSI HOST support for a parallel SCSI host adapters. | 14 | SCSI HOST support for a parallel SCSI host adapters. |
14 | 15 | ||
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 642a61b6d0a4..f2721ea30aa7 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -1120,65 +1120,6 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) | |||
1120 | return -1; | 1120 | return -1; |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | int | ||
1124 | mpt_alt_ioc_wait(MPT_ADAPTER *ioc) | ||
1125 | { | ||
1126 | int loop_count = 30 * 4; /* Wait 30 seconds */ | ||
1127 | int status = -1; /* -1 means failed to get board READY */ | ||
1128 | |||
1129 | do { | ||
1130 | spin_lock(&ioc->initializing_hba_lock); | ||
1131 | if (ioc->initializing_hba_lock_flag == 0) { | ||
1132 | ioc->initializing_hba_lock_flag=1; | ||
1133 | spin_unlock(&ioc->initializing_hba_lock); | ||
1134 | status = 0; | ||
1135 | break; | ||
1136 | } | ||
1137 | spin_unlock(&ioc->initializing_hba_lock); | ||
1138 | set_current_state(TASK_INTERRUPTIBLE); | ||
1139 | schedule_timeout(HZ/4); | ||
1140 | } while (--loop_count); | ||
1141 | |||
1142 | return status; | ||
1143 | } | ||
1144 | |||
1145 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1146 | /* | ||
1147 | * mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery | ||
1148 | * @ioc: Pointer to MPT adapter structure | ||
1149 | * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. | ||
1150 | * | ||
1151 | * This routine performs all the steps necessary to bring the IOC | ||
1152 | * to a OPERATIONAL state. | ||
1153 | * | ||
1154 | * Special Note: This function was added with spin lock's so as to allow | ||
1155 | * the dv(domain validation) work thread to succeed on the other channel | ||
1156 | * that maybe occuring at the same time when this function is called. | ||
1157 | * Without this lock, the dv would fail when message frames were | ||
1158 | * requested during hba bringup on the alternate ioc. | ||
1159 | */ | ||
1160 | static int | ||
1161 | mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag) | ||
1162 | { | ||
1163 | int r; | ||
1164 | |||
1165 | if(ioc->alt_ioc) { | ||
1166 | if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0)) | ||
1167 | return r; | ||
1168 | } | ||
1169 | |||
1170 | r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, | ||
1171 | CAN_SLEEP); | ||
1172 | |||
1173 | if(ioc->alt_ioc) { | ||
1174 | spin_lock(&ioc->alt_ioc->initializing_hba_lock); | ||
1175 | ioc->alt_ioc->initializing_hba_lock_flag=0; | ||
1176 | spin_unlock(&ioc->alt_ioc->initializing_hba_lock); | ||
1177 | } | ||
1178 | |||
1179 | return r; | ||
1180 | } | ||
1181 | |||
1182 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1123 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
1183 | /* | 1124 | /* |
1184 | * mpt_attach - Install a PCI intelligent MPT adapter. | 1125 | * mpt_attach - Install a PCI intelligent MPT adapter. |
@@ -1482,7 +1423,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1482 | */ | 1423 | */ |
1483 | mpt_detect_bound_ports(ioc, pdev); | 1424 | mpt_detect_bound_ports(ioc, pdev); |
1484 | 1425 | ||
1485 | if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){ | 1426 | if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, |
1427 | CAN_SLEEP)) != 0){ | ||
1486 | printk(KERN_WARNING MYNAM | 1428 | printk(KERN_WARNING MYNAM |
1487 | ": WARNING - %s did not initialize properly! (%d)\n", | 1429 | ": WARNING - %s did not initialize properly! (%d)\n", |
1488 | ioc->name, r); | 1430 | ioc->name, r); |
@@ -1629,7 +1571,6 @@ mpt_resume(struct pci_dev *pdev) | |||
1629 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 1571 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); |
1630 | u32 device_state = pdev->current_state; | 1572 | u32 device_state = pdev->current_state; |
1631 | int recovery_state; | 1573 | int recovery_state; |
1632 | int ii; | ||
1633 | 1574 | ||
1634 | printk(MYIOC_s_INFO_FMT | 1575 | printk(MYIOC_s_INFO_FMT |
1635 | "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", | 1576 | "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", |
@@ -1643,14 +1584,6 @@ mpt_resume(struct pci_dev *pdev) | |||
1643 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); | 1584 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); |
1644 | ioc->active = 1; | 1585 | ioc->active = 1; |
1645 | 1586 | ||
1646 | /* F/W not running */ | ||
1647 | if(!CHIPREG_READ32(&ioc->chip->Doorbell)) { | ||
1648 | /* enable domain validation flags */ | ||
1649 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | ||
1650 | ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV; | ||
1651 | } | ||
1652 | } | ||
1653 | |||
1654 | printk(MYIOC_s_INFO_FMT | 1587 | printk(MYIOC_s_INFO_FMT |
1655 | "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", | 1588 | "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", |
1656 | ioc->name, | 1589 | ioc->name, |
@@ -6435,7 +6368,6 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3); | |||
6435 | EXPORT_SYMBOL(mpt_alloc_fw_memory); | 6368 | EXPORT_SYMBOL(mpt_alloc_fw_memory); |
6436 | EXPORT_SYMBOL(mpt_free_fw_memory); | 6369 | EXPORT_SYMBOL(mpt_free_fw_memory); |
6437 | EXPORT_SYMBOL(mptbase_sas_persist_operation); | 6370 | EXPORT_SYMBOL(mptbase_sas_persist_operation); |
6438 | EXPORT_SYMBOL(mpt_alt_ioc_wait); | ||
6439 | EXPORT_SYMBOL(mptbase_GetFcPortPage0); | 6371 | EXPORT_SYMBOL(mptbase_GetFcPortPage0); |
6440 | 6372 | ||
6441 | 6373 | ||
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 723d54300953..f4197a9962a3 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
@@ -331,6 +331,7 @@ typedef struct _SYSIF_REGS | |||
331 | * VirtDevice - FC LUN device or SCSI target device | 331 | * VirtDevice - FC LUN device or SCSI target device |
332 | */ | 332 | */ |
333 | typedef struct _VirtTarget { | 333 | typedef struct _VirtTarget { |
334 | struct scsi_target *starget; | ||
334 | u8 tflags; | 335 | u8 tflags; |
335 | u8 ioc_id; | 336 | u8 ioc_id; |
336 | u8 target_id; | 337 | u8 target_id; |
@@ -343,7 +344,6 @@ typedef struct _VirtTarget { | |||
343 | u8 type; /* byte 0 of Inquiry data */ | 344 | u8 type; /* byte 0 of Inquiry data */ |
344 | u32 num_luns; | 345 | u32 num_luns; |
345 | u32 luns[8]; /* Max LUNs is 256 */ | 346 | u32 luns[8]; /* Max LUNs is 256 */ |
346 | u8 inq_data[8]; | ||
347 | } VirtTarget; | 347 | } VirtTarget; |
348 | 348 | ||
349 | typedef struct _VirtDevice { | 349 | typedef struct _VirtDevice { |
@@ -364,6 +364,7 @@ typedef struct _VirtDevice { | |||
364 | #define MPT_TARGET_FLAGS_Q_YES 0x08 | 364 | #define MPT_TARGET_FLAGS_Q_YES 0x08 |
365 | #define MPT_TARGET_FLAGS_VALID_56 0x10 | 365 | #define MPT_TARGET_FLAGS_VALID_56 0x10 |
366 | #define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20 | 366 | #define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20 |
367 | #define MPT_TARGET_FLAGS_RAID_COMPONENT 0x40 | ||
367 | 368 | ||
368 | /* | 369 | /* |
369 | * /proc/mpt interface | 370 | * /proc/mpt interface |
@@ -447,13 +448,6 @@ typedef struct _mpt_ioctl_events { | |||
447 | * Substructure to store SCSI specific configuration page data | 448 | * Substructure to store SCSI specific configuration page data |
448 | */ | 449 | */ |
449 | /* dvStatus defines: */ | 450 | /* dvStatus defines: */ |
450 | #define MPT_SCSICFG_NEGOTIATE 0x01 /* Negotiate on next IO */ | ||
451 | #define MPT_SCSICFG_NEED_DV 0x02 /* Schedule DV */ | ||
452 | #define MPT_SCSICFG_DV_PENDING 0x04 /* DV on this physical id pending */ | ||
453 | #define MPT_SCSICFG_DV_NOT_DONE 0x08 /* DV has not been performed */ | ||
454 | #define MPT_SCSICFG_BLK_NEGO 0x10 /* WriteSDP1 with WDTR and SDTR disabled */ | ||
455 | #define MPT_SCSICFG_RELOAD_IOC_PG3 0x20 /* IOC Pg 3 data is obsolete */ | ||
456 | /* Args passed to writeSDP1: */ | ||
457 | #define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */ | 451 | #define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */ |
458 | #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ | 452 | #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ |
459 | /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ | 453 | /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ |
@@ -464,7 +458,6 @@ typedef struct _SpiCfgData { | |||
464 | IOCPage4_t *pIocPg4; /* SEP devices addressing */ | 458 | IOCPage4_t *pIocPg4; /* SEP devices addressing */ |
465 | dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ | 459 | dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ |
466 | int IocPg4Sz; /* IOCPage4 size */ | 460 | int IocPg4Sz; /* IOCPage4 size */ |
467 | u8 dvStatus[MPT_MAX_SCSI_DEVICES]; | ||
468 | u8 minSyncFactor; /* 0xFF if async */ | 461 | u8 minSyncFactor; /* 0xFF if async */ |
469 | u8 maxSyncOffset; /* 0 if async */ | 462 | u8 maxSyncOffset; /* 0 if async */ |
470 | u8 maxBusWidth; /* 0 if narrow, 1 if wide */ | 463 | u8 maxBusWidth; /* 0 if narrow, 1 if wide */ |
@@ -474,13 +467,11 @@ typedef struct _SpiCfgData { | |||
474 | u8 sdp0version; /* SDP0 version */ | 467 | u8 sdp0version; /* SDP0 version */ |
475 | u8 sdp0length; /* SDP0 length */ | 468 | u8 sdp0length; /* SDP0 length */ |
476 | u8 dvScheduled; /* 1 if scheduled */ | 469 | u8 dvScheduled; /* 1 if scheduled */ |
477 | u8 forceDv; /* 1 to force DV scheduling */ | ||
478 | u8 noQas; /* Disable QAS for this adapter */ | 470 | u8 noQas; /* Disable QAS for this adapter */ |
479 | u8 Saf_Te; /* 1 to force all Processors as | 471 | u8 Saf_Te; /* 1 to force all Processors as |
480 | * SAF-TE if Inquiry data length | 472 | * SAF-TE if Inquiry data length |
481 | * is too short to check for SAF-TE | 473 | * is too short to check for SAF-TE |
482 | */ | 474 | */ |
483 | u8 mpt_dv; /* command line option: enhanced=1, basic=0 */ | ||
484 | u8 bus_reset; /* 1 to allow bus reset */ | 475 | u8 bus_reset; /* 1 to allow bus reset */ |
485 | u8 rsvd[1]; | 476 | u8 rsvd[1]; |
486 | }SpiCfgData; | 477 | }SpiCfgData; |
@@ -1033,7 +1024,6 @@ extern int mpt_findImVolumes(MPT_ADAPTER *ioc); | |||
1033 | extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); | 1024 | extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); |
1034 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | 1025 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); |
1035 | extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); | 1026 | extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); |
1036 | extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc); | ||
1037 | 1027 | ||
1038 | /* | 1028 | /* |
1039 | * Public data decl's... | 1029 | * Public data decl's... |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 4fee6befc93d..ff83e21e1000 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -114,21 +114,6 @@ typedef struct _internal_cmd { | |||
114 | u8 rsvd; | 114 | u8 rsvd; |
115 | } INTERNAL_CMD; | 115 | } INTERNAL_CMD; |
116 | 116 | ||
117 | typedef struct _negoparms { | ||
118 | u8 width; | ||
119 | u8 offset; | ||
120 | u8 factor; | ||
121 | u8 flags; | ||
122 | } NEGOPARMS; | ||
123 | |||
124 | typedef struct _dv_parameters { | ||
125 | NEGOPARMS max; | ||
126 | NEGOPARMS now; | ||
127 | u8 cmd; | ||
128 | u8 id; | ||
129 | u16 pad1; | ||
130 | } DVPARAMETERS; | ||
131 | |||
132 | /* | 117 | /* |
133 | * Other private/forward protos... | 118 | * Other private/forward protos... |
134 | */ | 119 | */ |
@@ -149,28 +134,12 @@ static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 tar | |||
149 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | 134 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); |
150 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); | 135 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); |
151 | 136 | ||
152 | static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen); | 137 | static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); |
153 | static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, char byte56); | 138 | static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); |
154 | static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags); | ||
155 | static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc); | ||
156 | static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags); | ||
157 | static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); | 139 | static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); |
158 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); | 140 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); |
159 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); | 141 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); |
160 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); | 142 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); |
161 | static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice); | ||
162 | static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); | ||
163 | |||
164 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
165 | static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); | ||
166 | static void mptscsih_domainValidation(void *hd); | ||
167 | static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); | ||
168 | static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); | ||
169 | static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); | ||
170 | static void mptscsih_fillbuf(char *buffer, int size, int index, int width); | ||
171 | static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id); | ||
172 | static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc); | ||
173 | #endif | ||
174 | 143 | ||
175 | void mptscsih_remove(struct pci_dev *); | 144 | void mptscsih_remove(struct pci_dev *); |
176 | void mptscsih_shutdown(struct pci_dev *); | 145 | void mptscsih_shutdown(struct pci_dev *); |
@@ -181,16 +150,6 @@ int mptscsih_resume(struct pci_dev *pdev); | |||
181 | 150 | ||
182 | #define SNS_LEN(scp) sizeof((scp)->sense_buffer) | 151 | #define SNS_LEN(scp) sizeof((scp)->sense_buffer) |
183 | 152 | ||
184 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
185 | /* | ||
186 | * Domain Validation task structure | ||
187 | */ | ||
188 | static DEFINE_SPINLOCK(dvtaskQ_lock); | ||
189 | static int dvtaskQ_active = 0; | ||
190 | static int dvtaskQ_release = 0; | ||
191 | static struct work_struct dvTaskQ_task; | ||
192 | #endif | ||
193 | |||
194 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 153 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
195 | /** | 154 | /** |
196 | * mptscsih_add_sge - Place a simple SGE at address pAddr. | 155 | * mptscsih_add_sge - Place a simple SGE at address pAddr. |
@@ -687,9 +646,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
687 | */ | 646 | */ |
688 | sc->result = DID_RESET << 16; | 647 | sc->result = DID_RESET << 16; |
689 | 648 | ||
690 | /* GEM Workaround. */ | ||
691 | if (ioc->bus_type == SPI) | ||
692 | mptscsih_no_negotiate(hd, sc); | ||
693 | break; | 649 | break; |
694 | 650 | ||
695 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ | 651 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ |
@@ -1005,10 +961,6 @@ mptscsih_remove(struct pci_dev *pdev) | |||
1005 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 961 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); |
1006 | struct Scsi_Host *host = ioc->sh; | 962 | struct Scsi_Host *host = ioc->sh; |
1007 | MPT_SCSI_HOST *hd; | 963 | MPT_SCSI_HOST *hd; |
1008 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
1009 | int count; | ||
1010 | unsigned long flags; | ||
1011 | #endif | ||
1012 | int sz1; | 964 | int sz1; |
1013 | 965 | ||
1014 | if(!host) { | 966 | if(!host) { |
@@ -1021,25 +973,6 @@ mptscsih_remove(struct pci_dev *pdev) | |||
1021 | if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL) | 973 | if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL) |
1022 | return; | 974 | return; |
1023 | 975 | ||
1024 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
1025 | /* Check DV thread active */ | ||
1026 | count = 10 * HZ; | ||
1027 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
1028 | if (dvtaskQ_active) { | ||
1029 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
1030 | while(dvtaskQ_active && --count) | ||
1031 | schedule_timeout_interruptible(1); | ||
1032 | } else { | ||
1033 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
1034 | } | ||
1035 | if (!count) | ||
1036 | printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n"); | ||
1037 | #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) | ||
1038 | else | ||
1039 | printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count); | ||
1040 | #endif | ||
1041 | #endif | ||
1042 | |||
1043 | mptscsih_shutdown(pdev); | 976 | mptscsih_shutdown(pdev); |
1044 | 977 | ||
1045 | sz1=0; | 978 | sz1=0; |
@@ -1127,21 +1060,6 @@ mptscsih_resume(struct pci_dev *pdev) | |||
1127 | if(!hd) | 1060 | if(!hd) |
1128 | return 0; | 1061 | return 0; |
1129 | 1062 | ||
1130 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
1131 | { | ||
1132 | unsigned long lflags; | ||
1133 | spin_lock_irqsave(&dvtaskQ_lock, lflags); | ||
1134 | if (!dvtaskQ_active) { | ||
1135 | dvtaskQ_active = 1; | ||
1136 | spin_unlock_irqrestore(&dvtaskQ_lock, lflags); | ||
1137 | INIT_WORK(&dvTaskQ_task, | ||
1138 | mptscsih_domainValidation, (void *) hd); | ||
1139 | schedule_work(&dvTaskQ_task); | ||
1140 | } else { | ||
1141 | spin_unlock_irqrestore(&dvtaskQ_lock, lflags); | ||
1142 | } | ||
1143 | } | ||
1144 | #endif | ||
1145 | return 0; | 1063 | return 0; |
1146 | } | 1064 | } |
1147 | 1065 | ||
@@ -1317,6 +1235,13 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1317 | return SCSI_MLQUEUE_HOST_BUSY; | 1235 | return SCSI_MLQUEUE_HOST_BUSY; |
1318 | } | 1236 | } |
1319 | 1237 | ||
1238 | if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && | ||
1239 | mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { | ||
1240 | SCpnt->result = DID_NO_CONNECT << 16; | ||
1241 | done(SCpnt); | ||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1320 | /* | 1245 | /* |
1321 | * Put together a MPT SCSI request... | 1246 | * Put together a MPT SCSI request... |
1322 | */ | 1247 | */ |
@@ -1363,7 +1288,10 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1363 | pScsiReq->TargetID = (u8) vdev->target_id; | 1288 | pScsiReq->TargetID = (u8) vdev->target_id; |
1364 | pScsiReq->Bus = vdev->bus_id; | 1289 | pScsiReq->Bus = vdev->bus_id; |
1365 | pScsiReq->ChainOffset = 0; | 1290 | pScsiReq->ChainOffset = 0; |
1366 | pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; | 1291 | if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) |
1292 | pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; | ||
1293 | else | ||
1294 | pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; | ||
1367 | pScsiReq->CDBLength = SCpnt->cmd_len; | 1295 | pScsiReq->CDBLength = SCpnt->cmd_len; |
1368 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; | 1296 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; |
1369 | pScsiReq->Reserved = 0; | 1297 | pScsiReq->Reserved = 0; |
@@ -1411,49 +1339,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1411 | hd->ScsiLookup[my_idx] = SCpnt; | 1339 | hd->ScsiLookup[my_idx] = SCpnt; |
1412 | SCpnt->host_scribble = NULL; | 1340 | SCpnt->host_scribble = NULL; |
1413 | 1341 | ||
1414 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
1415 | if (hd->ioc->bus_type == SPI) { | ||
1416 | int dvStatus = hd->ioc->spi_data.dvStatus[vdev->target_id]; | ||
1417 | int issueCmd = 1; | ||
1418 | |||
1419 | if (dvStatus || hd->ioc->spi_data.forceDv) { | ||
1420 | |||
1421 | if ((dvStatus & MPT_SCSICFG_NEED_DV) || | ||
1422 | (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { | ||
1423 | unsigned long lflags; | ||
1424 | /* Schedule DV if necessary */ | ||
1425 | spin_lock_irqsave(&dvtaskQ_lock, lflags); | ||
1426 | if (!dvtaskQ_active) { | ||
1427 | dvtaskQ_active = 1; | ||
1428 | spin_unlock_irqrestore(&dvtaskQ_lock, lflags); | ||
1429 | INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd); | ||
1430 | |||
1431 | schedule_work(&dvTaskQ_task); | ||
1432 | } else { | ||
1433 | spin_unlock_irqrestore(&dvtaskQ_lock, lflags); | ||
1434 | } | ||
1435 | hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV; | ||
1436 | } | ||
1437 | |||
1438 | /* Trying to do DV to this target, extend timeout. | ||
1439 | * Wait to issue until flag is clear | ||
1440 | */ | ||
1441 | if (dvStatus & MPT_SCSICFG_DV_PENDING) { | ||
1442 | mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); | ||
1443 | issueCmd = 0; | ||
1444 | } | ||
1445 | |||
1446 | /* Set the DV flags. | ||
1447 | */ | ||
1448 | if (dvStatus & MPT_SCSICFG_DV_NOT_DONE) | ||
1449 | mptscsih_set_dvflags(hd, SCpnt); | ||
1450 | |||
1451 | if (!issueCmd) | ||
1452 | goto fail; | ||
1453 | } | ||
1454 | } | ||
1455 | #endif | ||
1456 | |||
1457 | mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); | 1342 | mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); |
1458 | dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", | 1343 | dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", |
1459 | hd->ioc->name, SCpnt, mf, my_idx)); | 1344 | hd->ioc->name, SCpnt, mf, my_idx)); |
@@ -2218,6 +2103,24 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, | |||
2218 | return 0; | 2103 | return 0; |
2219 | } | 2104 | } |
2220 | 2105 | ||
2106 | int | ||
2107 | mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) | ||
2108 | { | ||
2109 | int i; | ||
2110 | |||
2111 | if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3) | ||
2112 | return -ENXIO; | ||
2113 | |||
2114 | for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
2115 | if (physdiskid == | ||
2116 | hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) | ||
2117 | return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; | ||
2118 | } | ||
2119 | |||
2120 | return -ENXIO; | ||
2121 | } | ||
2122 | EXPORT_SYMBOL(mptscsih_raid_id_to_num); | ||
2123 | |||
2221 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2124 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
2222 | /* | 2125 | /* |
2223 | * OS entry point to allow host driver to alloc memory | 2126 | * OS entry point to allow host driver to alloc memory |
@@ -2233,6 +2136,7 @@ mptscsih_target_alloc(struct scsi_target *starget) | |||
2233 | if (!vtarget) | 2136 | if (!vtarget) |
2234 | return -ENOMEM; | 2137 | return -ENOMEM; |
2235 | starget->hostdata = vtarget; | 2138 | starget->hostdata = vtarget; |
2139 | vtarget->starget = starget; | ||
2236 | return 0; | 2140 | return 0; |
2237 | } | 2141 | } |
2238 | 2142 | ||
@@ -2266,6 +2170,7 @@ mptscsih_slave_alloc(struct scsi_device *sdev) | |||
2266 | 2170 | ||
2267 | starget = scsi_target(sdev); | 2171 | starget = scsi_target(sdev); |
2268 | vtarget = starget->hostdata; | 2172 | vtarget = starget->hostdata; |
2173 | |||
2269 | vdev->vtarget = vtarget; | 2174 | vdev->vtarget = vtarget; |
2270 | 2175 | ||
2271 | if (vtarget->num_luns == 0) { | 2176 | if (vtarget->num_luns == 0) { |
@@ -2274,14 +2179,11 @@ mptscsih_slave_alloc(struct scsi_device *sdev) | |||
2274 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; | 2179 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; |
2275 | vtarget->target_id = sdev->id; | 2180 | vtarget->target_id = sdev->id; |
2276 | vtarget->bus_id = sdev->channel; | 2181 | vtarget->bus_id = sdev->channel; |
2277 | if (hd->ioc->bus_type == SPI) { | 2182 | if (hd->ioc->bus_type == SPI && sdev->channel == 0 && |
2278 | if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) { | 2183 | hd->ioc->raid_data.isRaid & (1 << sdev->id)) { |
2279 | vtarget->raidVolume = 1; | 2184 | vtarget->raidVolume = 1; |
2280 | ddvtprintk((KERN_INFO | 2185 | ddvtprintk((KERN_INFO |
2281 | "RAID Volume @ id %d\n", sdev->id)); | 2186 | "RAID Volume @ id %d\n", sdev->id)); |
2282 | } | ||
2283 | } else { | ||
2284 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; | ||
2285 | } | 2187 | } |
2286 | } | 2188 | } |
2287 | vtarget->num_luns++; | 2189 | vtarget->num_luns++; |
@@ -2321,19 +2223,6 @@ mptscsih_slave_destroy(struct scsi_device *sdev) | |||
2321 | vtarget->luns[0] &= ~(1 << vdevice->lun); | 2223 | vtarget->luns[0] &= ~(1 << vdevice->lun); |
2322 | vtarget->num_luns--; | 2224 | vtarget->num_luns--; |
2323 | if (vtarget->num_luns == 0) { | 2225 | if (vtarget->num_luns == 0) { |
2324 | mptscsih_negotiate_to_asyn_narrow(hd, vdevice); | ||
2325 | if (hd->ioc->bus_type == SPI) { | ||
2326 | if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) { | ||
2327 | hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; | ||
2328 | } else { | ||
2329 | hd->ioc->spi_data.dvStatus[vtarget->target_id] = | ||
2330 | MPT_SCSICFG_NEGOTIATE; | ||
2331 | if (!hd->negoNvram) { | ||
2332 | hd->ioc->spi_data.dvStatus[vtarget->target_id] |= | ||
2333 | MPT_SCSICFG_DV_NOT_DONE; | ||
2334 | } | ||
2335 | } | ||
2336 | } | ||
2337 | hd->Targets[sdev->id] = NULL; | 2226 | hd->Targets[sdev->id] = NULL; |
2338 | } | 2227 | } |
2339 | mptscsih_synchronize_cache(hd, vdevice); | 2228 | mptscsih_synchronize_cache(hd, vdevice); |
@@ -2362,18 +2251,13 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
2362 | vtarget = starget->hostdata; | 2251 | vtarget = starget->hostdata; |
2363 | 2252 | ||
2364 | if (hd->ioc->bus_type == SPI) { | 2253 | if (hd->ioc->bus_type == SPI) { |
2365 | if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { | 2254 | if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) |
2366 | if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) | ||
2367 | max_depth = 1; | ||
2368 | else if (((vtarget->inq_data[0] & 0x1f) == 0x00) && | ||
2369 | (vtarget->minSyncFactor <= MPT_ULTRA160 )) | ||
2370 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; | ||
2371 | else | ||
2372 | max_depth = MPT_SCSI_CMD_PER_DEV_LOW; | ||
2373 | } else { | ||
2374 | /* error case - No Inq. Data */ | ||
2375 | max_depth = 1; | 2255 | max_depth = 1; |
2376 | } | 2256 | else if (sdev->type == TYPE_DISK && |
2257 | vtarget->minSyncFactor <= MPT_ULTRA160) | ||
2258 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; | ||
2259 | else | ||
2260 | max_depth = MPT_SCSI_CMD_PER_DEV_LOW; | ||
2377 | } else | 2261 | } else |
2378 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; | 2262 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; |
2379 | 2263 | ||
@@ -2427,8 +2311,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) | |||
2427 | lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ | 2311 | lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ |
2428 | indexed_lun = (vdevice->lun % 32); | 2312 | indexed_lun = (vdevice->lun % 32); |
2429 | vtarget->luns[lun_index] |= (1 << indexed_lun); | 2313 | vtarget->luns[lun_index] |= (1 << indexed_lun); |
2430 | mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry, | 2314 | mptscsih_initTarget(hd, vtarget, sdev); |
2431 | sdev->inquiry_len ); | ||
2432 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); | 2315 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); |
2433 | 2316 | ||
2434 | dsprintk((MYIOC_s_INFO_FMT | 2317 | dsprintk((MYIOC_s_INFO_FMT |
@@ -2597,10 +2480,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
2597 | 2480 | ||
2598 | /* 4. Renegotiate to all devices, if SPI | 2481 | /* 4. Renegotiate to all devices, if SPI |
2599 | */ | 2482 | */ |
2600 | if (ioc->bus_type == SPI) { | ||
2601 | dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n")); | ||
2602 | mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM); | ||
2603 | } | ||
2604 | 2483 | ||
2605 | /* 5. Enable new commands to be posted | 2484 | /* 5. Enable new commands to be posted |
2606 | */ | 2485 | */ |
@@ -2624,13 +2503,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
2624 | hd->cmdPtr = NULL; | 2503 | hd->cmdPtr = NULL; |
2625 | } | 2504 | } |
2626 | 2505 | ||
2627 | /* 7. SPI: Set flag to force DV and re-read IOC Page 3 | ||
2628 | */ | ||
2629 | if (ioc->bus_type == SPI) { | ||
2630 | ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; | ||
2631 | ddvtprintk(("Set reload IOC Pg3 Flag\n")); | ||
2632 | } | ||
2633 | |||
2634 | /* 7. FC: Rescan for blocked rports which might have returned. | 2506 | /* 7. FC: Rescan for blocked rports which might have returned. |
2635 | */ | 2507 | */ |
2636 | else if (ioc->bus_type == FC) { | 2508 | else if (ioc->bus_type == FC) { |
@@ -2699,18 +2571,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2699 | break; | 2571 | break; |
2700 | 2572 | ||
2701 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ | 2573 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ |
2702 | { | ||
2703 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
2704 | pMpiEventDataRaid_t pRaidEventData = | ||
2705 | (pMpiEventDataRaid_t) pEvReply->Data; | ||
2706 | /* Domain Validation Needed */ | ||
2707 | if (ioc->bus_type == SPI && | ||
2708 | pRaidEventData->ReasonCode == | ||
2709 | MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) | ||
2710 | mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum); | ||
2711 | #endif | ||
2712 | break; | 2574 | break; |
2713 | } | ||
2714 | 2575 | ||
2715 | case MPI_EVENT_NONE: /* 00 */ | 2576 | case MPI_EVENT_NONE: /* 00 */ |
2716 | case MPI_EVENT_LOG_DATA: /* 01 */ | 2577 | case MPI_EVENT_LOG_DATA: /* 01 */ |
@@ -2729,9 +2590,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2729 | * mptscsih_initTarget - Target, LUN alloc/free functionality. | 2590 | * mptscsih_initTarget - Target, LUN alloc/free functionality. |
2730 | * @hd: Pointer to MPT_SCSI_HOST structure | 2591 | * @hd: Pointer to MPT_SCSI_HOST structure |
2731 | * @vtarget: per target private data | 2592 | * @vtarget: per target private data |
2732 | * @lun: SCSI LUN id | 2593 | * @sdev: SCSI device |
2733 | * @data: Pointer to data | ||
2734 | * @dlen: Number of INQUIRY bytes | ||
2735 | * | 2594 | * |
2736 | * NOTE: It's only SAFE to call this routine if data points to | 2595 | * NOTE: It's only SAFE to call this routine if data points to |
2737 | * sane & valid STANDARD INQUIRY data! | 2596 | * sane & valid STANDARD INQUIRY data! |
@@ -2741,98 +2600,46 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2741 | * | 2600 | * |
2742 | */ | 2601 | */ |
2743 | static void | 2602 | static void |
2744 | mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen) | 2603 | mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, |
2604 | struct scsi_device *sdev) | ||
2745 | { | 2605 | { |
2746 | SpiCfgData *pSpi; | ||
2747 | char data_56; | ||
2748 | int inq_len; | ||
2749 | |||
2750 | dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", | 2606 | dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", |
2751 | hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd)); | 2607 | hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd)); |
2752 | 2608 | ||
2753 | /* | ||
2754 | * If the peripheral qualifier filter is enabled then if the target reports a 0x1 | ||
2755 | * (i.e. The targer is capable of supporting the specified peripheral device type | ||
2756 | * on this logical unit; however, the physical device is not currently connected | ||
2757 | * to this logical unit) it will be converted to a 0x3 (i.e. The target is not | ||
2758 | * capable of supporting a physical device on this logical unit). This is to work | ||
2759 | * around a bug in th emid-layer in some distributions in which the mid-layer will | ||
2760 | * continue to try to communicate to the LUN and evntually create a dummy LUN. | ||
2761 | */ | ||
2762 | if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0)) | ||
2763 | data[0] |= 0x40; | ||
2764 | |||
2765 | /* Is LUN supported? If so, upper 2 bits will be 0 | 2609 | /* Is LUN supported? If so, upper 2 bits will be 0 |
2766 | * in first byte of inquiry data. | 2610 | * in first byte of inquiry data. |
2767 | */ | 2611 | */ |
2768 | if (data[0] & 0xe0) | 2612 | if (sdev->inq_periph_qual != 0) |
2769 | return; | 2613 | return; |
2770 | 2614 | ||
2771 | if (vtarget == NULL) | 2615 | if (vtarget == NULL) |
2772 | return; | 2616 | return; |
2773 | 2617 | ||
2774 | if (data) | 2618 | vtarget->type = sdev->type; |
2775 | vtarget->type = data[0]; | ||
2776 | 2619 | ||
2777 | if (hd->ioc->bus_type != SPI) | 2620 | if (hd->ioc->bus_type != SPI) |
2778 | return; | 2621 | return; |
2779 | 2622 | ||
2780 | if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { | 2623 | if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { |
2781 | /* Treat all Processors as SAF-TE if | 2624 | /* Treat all Processors as SAF-TE if |
2782 | * command line option is set */ | 2625 | * command line option is set */ |
2783 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; | 2626 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; |
2784 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); | 2627 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); |
2785 | }else if ((data[0] == TYPE_PROCESSOR) && | 2628 | }else if ((sdev->type == TYPE_PROCESSOR) && |
2786 | !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { | 2629 | !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { |
2787 | if ( dlen > 49 ) { | 2630 | if (sdev->inquiry_len > 49 ) { |
2788 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; | 2631 | if (sdev->inquiry[44] == 'S' && |
2789 | if ( data[44] == 'S' && | 2632 | sdev->inquiry[45] == 'A' && |
2790 | data[45] == 'A' && | 2633 | sdev->inquiry[46] == 'F' && |
2791 | data[46] == 'F' && | 2634 | sdev->inquiry[47] == '-' && |
2792 | data[47] == '-' && | 2635 | sdev->inquiry[48] == 'T' && |
2793 | data[48] == 'T' && | 2636 | sdev->inquiry[49] == 'E' ) { |
2794 | data[49] == 'E' ) { | ||
2795 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; | 2637 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; |
2796 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); | 2638 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); |
2797 | } | 2639 | } |
2798 | } | 2640 | } |
2799 | } | 2641 | } |
2800 | if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { | 2642 | mptscsih_setTargetNegoParms(hd, vtarget, sdev); |
2801 | inq_len = dlen < 8 ? dlen : 8; | ||
2802 | memcpy (vtarget->inq_data, data, inq_len); | ||
2803 | /* If have not done DV, set the DV flag. | ||
2804 | */ | ||
2805 | pSpi = &hd->ioc->spi_data; | ||
2806 | if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) { | ||
2807 | if (pSpi->dvStatus[vtarget->target_id] & MPT_SCSICFG_DV_NOT_DONE) | ||
2808 | pSpi->dvStatus[vtarget->target_id] |= MPT_SCSICFG_NEED_DV; | ||
2809 | } | ||
2810 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; | ||
2811 | |||
2812 | data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */ | ||
2813 | if (dlen > 56) { | ||
2814 | if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) { | ||
2815 | /* Update the target capabilities | ||
2816 | */ | ||
2817 | data_56 = data[56]; | ||
2818 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56; | ||
2819 | } | ||
2820 | } | ||
2821 | mptscsih_setTargetNegoParms(hd, vtarget, data_56); | ||
2822 | } else { | ||
2823 | /* Initial Inquiry may not request enough data bytes to | ||
2824 | * obtain byte 57. DV will; if target doesn't return | ||
2825 | * at least 57 bytes, data[56] will be zero. */ | ||
2826 | if (dlen > 56) { | ||
2827 | if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) { | ||
2828 | /* Update the target capabilities | ||
2829 | */ | ||
2830 | data_56 = data[56]; | ||
2831 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56; | ||
2832 | mptscsih_setTargetNegoParms(hd, vtarget, data_56); | ||
2833 | } | ||
2834 | } | ||
2835 | } | ||
2836 | } | 2643 | } |
2837 | 2644 | ||
2838 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2645 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -2842,66 +2649,51 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, | |||
2842 | * | 2649 | * |
2843 | */ | 2650 | */ |
2844 | static void | 2651 | static void |
2845 | mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) | 2652 | mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, |
2653 | struct scsi_device *sdev) | ||
2846 | { | 2654 | { |
2847 | SpiCfgData *pspi_data = &hd->ioc->spi_data; | 2655 | SpiCfgData *pspi_data = &hd->ioc->spi_data; |
2848 | int id = (int) target->target_id; | 2656 | int id = (int) target->target_id; |
2849 | int nvram; | 2657 | int nvram; |
2850 | VirtTarget *vtarget; | ||
2851 | int ii; | ||
2852 | u8 width = MPT_NARROW; | 2658 | u8 width = MPT_NARROW; |
2853 | u8 factor = MPT_ASYNC; | 2659 | u8 factor = MPT_ASYNC; |
2854 | u8 offset = 0; | 2660 | u8 offset = 0; |
2855 | u8 version, nfactor; | 2661 | u8 nfactor; |
2856 | u8 noQas = 1; | 2662 | u8 noQas = 1; |
2857 | 2663 | ||
2858 | target->negoFlags = pspi_data->noQas; | 2664 | target->negoFlags = pspi_data->noQas; |
2859 | 2665 | ||
2860 | /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine | 2666 | /* noQas == 0 => device supports QAS. */ |
2861 | * support. If available, default QAS to off and allow enabling. | ||
2862 | * If not available, default QAS to on, turn off for non-disks. | ||
2863 | */ | ||
2864 | 2667 | ||
2865 | /* Set flags based on Inquiry data | 2668 | if (sdev->scsi_level < SCSI_2) { |
2866 | */ | ||
2867 | version = target->inq_data[2] & 0x07; | ||
2868 | if (version < 2) { | ||
2869 | width = 0; | 2669 | width = 0; |
2870 | factor = MPT_ULTRA2; | 2670 | factor = MPT_ULTRA2; |
2871 | offset = pspi_data->maxSyncOffset; | 2671 | offset = pspi_data->maxSyncOffset; |
2872 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; | 2672 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; |
2873 | } else { | 2673 | } else { |
2874 | if (target->inq_data[7] & 0x20) { | 2674 | if (scsi_device_wide(sdev)) { |
2875 | width = 1; | 2675 | width = 1; |
2876 | } | 2676 | } |
2877 | 2677 | ||
2878 | if (target->inq_data[7] & 0x10) { | 2678 | if (scsi_device_sync(sdev)) { |
2879 | factor = pspi_data->minSyncFactor; | 2679 | factor = pspi_data->minSyncFactor; |
2880 | if (target->tflags & MPT_TARGET_FLAGS_VALID_56) { | 2680 | if (!scsi_device_dt(sdev)) |
2881 | /* bits 2 & 3 show Clocking support */ | ||
2882 | if ((byte56 & 0x0C) == 0) | ||
2883 | factor = MPT_ULTRA2; | 2681 | factor = MPT_ULTRA2; |
2682 | else { | ||
2683 | if (!scsi_device_ius(sdev) && | ||
2684 | !scsi_device_qas(sdev)) | ||
2685 | factor = MPT_ULTRA160; | ||
2884 | else { | 2686 | else { |
2885 | if ((byte56 & 0x03) == 0) | 2687 | factor = MPT_ULTRA320; |
2886 | factor = MPT_ULTRA160; | 2688 | if (scsi_device_qas(sdev)) { |
2887 | else { | 2689 | ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); |
2888 | factor = MPT_ULTRA320; | 2690 | noQas = 0; |
2889 | if (byte56 & 0x02) | ||
2890 | { | ||
2891 | ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); | ||
2892 | noQas = 0; | ||
2893 | } | ||
2894 | if (target->inq_data[0] == TYPE_TAPE) { | ||
2895 | if (byte56 & 0x01) | ||
2896 | target->negoFlags |= MPT_TAPE_NEGO_IDP; | ||
2897 | } | ||
2898 | } | 2691 | } |
2692 | if (sdev->type == TYPE_TAPE && | ||
2693 | scsi_device_ius(sdev)) | ||
2694 | target->negoFlags |= MPT_TAPE_NEGO_IDP; | ||
2899 | } | 2695 | } |
2900 | } else { | ||
2901 | ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id)); | ||
2902 | noQas = 0; | ||
2903 | } | 2696 | } |
2904 | |||
2905 | offset = pspi_data->maxSyncOffset; | 2697 | offset = pspi_data->maxSyncOffset; |
2906 | 2698 | ||
2907 | /* If RAID, never disable QAS | 2699 | /* If RAID, never disable QAS |
@@ -2919,7 +2711,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) | |||
2919 | } | 2711 | } |
2920 | } | 2712 | } |
2921 | 2713 | ||
2922 | if ( (target->inq_data[7] & 0x02) == 0) { | 2714 | if (!sdev->tagged_supported) { |
2923 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; | 2715 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; |
2924 | } | 2716 | } |
2925 | 2717 | ||
@@ -2977,55 +2769,18 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) | |||
2977 | if ( factor > MPT_ULTRA320 ) | 2769 | if ( factor > MPT_ULTRA320 ) |
2978 | noQas = 0; | 2770 | noQas = 0; |
2979 | 2771 | ||
2980 | /* GEM, processor WORKAROUND | 2772 | if (noQas && (pspi_data->noQas == 0)) { |
2981 | */ | 2773 | pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; |
2982 | if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) { | 2774 | target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; |
2983 | target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); | 2775 | |
2984 | pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; | 2776 | /* Disable QAS in a mixed configuration case |
2985 | } else { | 2777 | */ |
2986 | if (noQas && (pspi_data->noQas == 0)) { | ||
2987 | pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; | ||
2988 | target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; | ||
2989 | |||
2990 | /* Disable QAS in a mixed configuration case | ||
2991 | */ | ||
2992 | |||
2993 | ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); | ||
2994 | for (ii = 0; ii < id; ii++) { | ||
2995 | if ( (vtarget = hd->Targets[ii]) ) { | ||
2996 | vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; | ||
2997 | mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags); | ||
2998 | } | ||
2999 | } | ||
3000 | } | ||
3001 | } | ||
3002 | 2778 | ||
3003 | /* Write SDP1 on this I/O to this target */ | 2779 | ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); |
3004 | if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) { | ||
3005 | ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id)); | ||
3006 | mptscsih_writeSDP1(hd, 0, id, hd->negoNvram); | ||
3007 | pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE; | ||
3008 | } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) { | ||
3009 | ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id)); | ||
3010 | mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO); | ||
3011 | pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO; | ||
3012 | } | 2780 | } |
3013 | } | 2781 | } |
3014 | 2782 | ||
3015 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2783 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3016 | /* | ||
3017 | * If no Target, bus reset on 1st I/O. Set the flag to | ||
3018 | * prevent any future negotiations to this device. | ||
3019 | */ | ||
3020 | static void | ||
3021 | mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc) | ||
3022 | { | ||
3023 | VirtDevice *vdev; | ||
3024 | |||
3025 | if ((vdev = sc->device->hostdata) != NULL) | ||
3026 | hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO; | ||
3027 | return; | ||
3028 | } | ||
3029 | 2784 | ||
3030 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2785 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3031 | /* | 2786 | /* |
@@ -3077,207 +2832,6 @@ mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, | |||
3077 | } | 2832 | } |
3078 | 2833 | ||
3079 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2834 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3080 | /* mptscsih_writeSDP1 - write SCSI Device Page 1 | ||
3081 | * @hd: Pointer to a SCSI Host Strucutre | ||
3082 | * @portnum: IOC port number | ||
3083 | * @target_id: writeSDP1 for single ID | ||
3084 | * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO | ||
3085 | * | ||
3086 | * Return: -EFAULT if read of config page header fails | ||
3087 | * or 0 if success. | ||
3088 | * | ||
3089 | * Remark: If a target has been found, the settings from the | ||
3090 | * target structure are used, else the device is set | ||
3091 | * to async/narrow. | ||
3092 | * | ||
3093 | * Remark: Called during init and after a FW reload. | ||
3094 | * Remark: We do not wait for a return, write pages sequentially. | ||
3095 | */ | ||
3096 | static int | ||
3097 | mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) | ||
3098 | { | ||
3099 | MPT_ADAPTER *ioc = hd->ioc; | ||
3100 | Config_t *pReq; | ||
3101 | SCSIDevicePage1_t *pData; | ||
3102 | VirtTarget *vtarget=NULL; | ||
3103 | MPT_FRAME_HDR *mf; | ||
3104 | dma_addr_t dataDma; | ||
3105 | u16 req_idx; | ||
3106 | u32 frameOffset; | ||
3107 | u32 requested, configuration, flagsLength; | ||
3108 | int ii, nvram; | ||
3109 | int id = 0, maxid = 0; | ||
3110 | u8 width; | ||
3111 | u8 factor; | ||
3112 | u8 offset; | ||
3113 | u8 bus = 0; | ||
3114 | u8 negoFlags; | ||
3115 | u8 maxwidth, maxoffset, maxfactor; | ||
3116 | |||
3117 | if (ioc->spi_data.sdp1length == 0) | ||
3118 | return 0; | ||
3119 | |||
3120 | if (flags & MPT_SCSICFG_ALL_IDS) { | ||
3121 | id = 0; | ||
3122 | maxid = ioc->sh->max_id - 1; | ||
3123 | } else if (ioc->sh) { | ||
3124 | id = target_id; | ||
3125 | maxid = min_t(int, id, ioc->sh->max_id - 1); | ||
3126 | } | ||
3127 | |||
3128 | for (; id <= maxid; id++) { | ||
3129 | |||
3130 | if (id == ioc->pfacts[portnum].PortSCSIID) | ||
3131 | continue; | ||
3132 | |||
3133 | /* Use NVRAM to get adapter and target maximums | ||
3134 | * Data over-riden by target structure information, if present | ||
3135 | */ | ||
3136 | maxwidth = ioc->spi_data.maxBusWidth; | ||
3137 | maxoffset = ioc->spi_data.maxSyncOffset; | ||
3138 | maxfactor = ioc->spi_data.minSyncFactor; | ||
3139 | if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { | ||
3140 | nvram = ioc->spi_data.nvram[id]; | ||
3141 | |||
3142 | if (maxwidth) | ||
3143 | maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; | ||
3144 | |||
3145 | if (maxoffset > 0) { | ||
3146 | maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; | ||
3147 | if (maxfactor == 0) { | ||
3148 | /* Key for async */ | ||
3149 | maxfactor = MPT_ASYNC; | ||
3150 | maxoffset = 0; | ||
3151 | } else if (maxfactor < ioc->spi_data.minSyncFactor) { | ||
3152 | maxfactor = ioc->spi_data.minSyncFactor; | ||
3153 | } | ||
3154 | } else | ||
3155 | maxfactor = MPT_ASYNC; | ||
3156 | } | ||
3157 | |||
3158 | /* Set the negotiation flags. | ||
3159 | */ | ||
3160 | negoFlags = ioc->spi_data.noQas; | ||
3161 | if (!maxwidth) | ||
3162 | negoFlags |= MPT_TARGET_NO_NEGO_WIDE; | ||
3163 | |||
3164 | if (!maxoffset) | ||
3165 | negoFlags |= MPT_TARGET_NO_NEGO_SYNC; | ||
3166 | |||
3167 | if (flags & MPT_SCSICFG_USE_NVRAM) { | ||
3168 | width = maxwidth; | ||
3169 | factor = maxfactor; | ||
3170 | offset = maxoffset; | ||
3171 | } else { | ||
3172 | width = 0; | ||
3173 | factor = MPT_ASYNC; | ||
3174 | offset = 0; | ||
3175 | //negoFlags = 0; | ||
3176 | //negoFlags = MPT_TARGET_NO_NEGO_SYNC; | ||
3177 | } | ||
3178 | |||
3179 | /* If id is not a raid volume, get the updated | ||
3180 | * transmission settings from the target structure. | ||
3181 | */ | ||
3182 | if (hd->Targets && (vtarget = hd->Targets[id]) && !vtarget->raidVolume) { | ||
3183 | width = vtarget->maxWidth; | ||
3184 | factor = vtarget->minSyncFactor; | ||
3185 | offset = vtarget->maxOffset; | ||
3186 | negoFlags = vtarget->negoFlags; | ||
3187 | } | ||
3188 | |||
3189 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
3190 | /* Force to async and narrow if DV has not been executed | ||
3191 | * for this ID | ||
3192 | */ | ||
3193 | if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) { | ||
3194 | width = 0; | ||
3195 | factor = MPT_ASYNC; | ||
3196 | offset = 0; | ||
3197 | } | ||
3198 | #endif | ||
3199 | |||
3200 | if (flags & MPT_SCSICFG_BLK_NEGO) | ||
3201 | negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; | ||
3202 | |||
3203 | mptscsih_setDevicePage1Flags(width, factor, offset, | ||
3204 | &requested, &configuration, negoFlags); | ||
3205 | dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", | ||
3206 | target_id, width, factor, offset, negoFlags, requested, configuration)); | ||
3207 | |||
3208 | /* Get a MF for this command. | ||
3209 | */ | ||
3210 | if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { | ||
3211 | dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n", | ||
3212 | ioc->name)); | ||
3213 | return -EAGAIN; | ||
3214 | } | ||
3215 | |||
3216 | ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n", | ||
3217 | hd->ioc->name, mf, id, requested, configuration)); | ||
3218 | |||
3219 | |||
3220 | /* Set the request and the data pointers. | ||
3221 | * Request takes: 36 bytes (32 bit SGE) | ||
3222 | * SCSI Device Page 1 requires 16 bytes | ||
3223 | * 40 + 16 <= size of SCSI IO Request = 56 bytes | ||
3224 | * and MF size >= 64 bytes. | ||
3225 | * Place data at end of MF. | ||
3226 | */ | ||
3227 | pReq = (Config_t *)mf; | ||
3228 | |||
3229 | req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
3230 | frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t); | ||
3231 | |||
3232 | pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset); | ||
3233 | dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset; | ||
3234 | |||
3235 | /* Complete the request frame (same for all requests). | ||
3236 | */ | ||
3237 | pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
3238 | pReq->Reserved = 0; | ||
3239 | pReq->ChainOffset = 0; | ||
3240 | pReq->Function = MPI_FUNCTION_CONFIG; | ||
3241 | pReq->ExtPageLength = 0; | ||
3242 | pReq->ExtPageType = 0; | ||
3243 | pReq->MsgFlags = 0; | ||
3244 | for (ii=0; ii < 8; ii++) { | ||
3245 | pReq->Reserved2[ii] = 0; | ||
3246 | } | ||
3247 | pReq->Header.PageVersion = ioc->spi_data.sdp1version; | ||
3248 | pReq->Header.PageLength = ioc->spi_data.sdp1length; | ||
3249 | pReq->Header.PageNumber = 1; | ||
3250 | pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
3251 | pReq->PageAddress = cpu_to_le32(id | (bus << 8 )); | ||
3252 | |||
3253 | /* Add a SGE to the config request. | ||
3254 | */ | ||
3255 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4; | ||
3256 | |||
3257 | mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); | ||
3258 | |||
3259 | /* Set up the common data portion | ||
3260 | */ | ||
3261 | pData->Header.PageVersion = pReq->Header.PageVersion; | ||
3262 | pData->Header.PageLength = pReq->Header.PageLength; | ||
3263 | pData->Header.PageNumber = pReq->Header.PageNumber; | ||
3264 | pData->Header.PageType = pReq->Header.PageType; | ||
3265 | pData->RequestedParameters = cpu_to_le32(requested); | ||
3266 | pData->Reserved = 0; | ||
3267 | pData->Configuration = cpu_to_le32(configuration); | ||
3268 | |||
3269 | dprintk((MYIOC_s_INFO_FMT | ||
3270 | "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n", | ||
3271 | ioc->name, id, (id | (bus<<8)), | ||
3272 | requested, configuration)); | ||
3273 | |||
3274 | mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); | ||
3275 | } | ||
3276 | |||
3277 | return 0; | ||
3278 | } | ||
3279 | |||
3280 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
3281 | /* mptscsih_writeIOCPage4 - write IOC Page 4 | 2835 | /* mptscsih_writeIOCPage4 - write IOC Page 4 |
3282 | * @hd: Pointer to a SCSI Host Structure | 2836 | * @hd: Pointer to a SCSI Host Structure |
3283 | * @target_id: write IOC Page4 for this ID & Bus | 2837 | * @target_id: write IOC Page4 for this ID & Bus |
@@ -3465,6 +3019,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
3465 | completionCode = MPT_SCANDV_GOOD; | 3019 | completionCode = MPT_SCANDV_GOOD; |
3466 | else | 3020 | else |
3467 | completionCode = MPT_SCANDV_SOME_ERROR; | 3021 | completionCode = MPT_SCANDV_SOME_ERROR; |
3022 | memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense)); | ||
3468 | 3023 | ||
3469 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { | 3024 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { |
3470 | u8 *sense_data; | 3025 | u8 *sense_data; |
@@ -3578,78 +3133,6 @@ mptscsih_timer_expired(unsigned long data) | |||
3578 | return; | 3133 | return; |
3579 | } | 3134 | } |
3580 | 3135 | ||
3581 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
3582 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
3583 | /* mptscsih_do_raid - Format and Issue a RAID volume request message. | ||
3584 | * @hd: Pointer to scsi host structure | ||
3585 | * @action: What do be done. | ||
3586 | * @id: Logical target id. | ||
3587 | * @bus: Target locations bus. | ||
3588 | * | ||
3589 | * Returns: < 0 on a fatal error | ||
3590 | * 0 on success | ||
3591 | * | ||
3592 | * Remark: Wait to return until reply processed by the ISR. | ||
3593 | */ | ||
3594 | static int | ||
3595 | mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io) | ||
3596 | { | ||
3597 | MpiRaidActionRequest_t *pReq; | ||
3598 | MPT_FRAME_HDR *mf; | ||
3599 | int in_isr; | ||
3600 | |||
3601 | in_isr = in_interrupt(); | ||
3602 | if (in_isr) { | ||
3603 | dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n", | ||
3604 | hd->ioc->name)); | ||
3605 | return -EPERM; | ||
3606 | } | ||
3607 | |||
3608 | /* Get and Populate a free Frame | ||
3609 | */ | ||
3610 | if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { | ||
3611 | ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", | ||
3612 | hd->ioc->name)); | ||
3613 | return -EAGAIN; | ||
3614 | } | ||
3615 | pReq = (MpiRaidActionRequest_t *)mf; | ||
3616 | pReq->Action = action; | ||
3617 | pReq->Reserved1 = 0; | ||
3618 | pReq->ChainOffset = 0; | ||
3619 | pReq->Function = MPI_FUNCTION_RAID_ACTION; | ||
3620 | pReq->VolumeID = io->id; | ||
3621 | pReq->VolumeBus = io->bus; | ||
3622 | pReq->PhysDiskNum = io->physDiskNum; | ||
3623 | pReq->MsgFlags = 0; | ||
3624 | pReq->Reserved2 = 0; | ||
3625 | pReq->ActionDataWord = 0; /* Reserved for this action */ | ||
3626 | //pReq->ActionDataSGE = 0; | ||
3627 | |||
3628 | mpt_add_sge((char *)&pReq->ActionDataSGE, | ||
3629 | MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); | ||
3630 | |||
3631 | ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", | ||
3632 | hd->ioc->name, action, io->id)); | ||
3633 | |||
3634 | hd->pLocal = NULL; | ||
3635 | hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ | ||
3636 | hd->scandv_wait_done = 0; | ||
3637 | |||
3638 | /* Save cmd pointer, for resource free if timeout or | ||
3639 | * FW reload occurs | ||
3640 | */ | ||
3641 | hd->cmdPtr = mf; | ||
3642 | |||
3643 | add_timer(&hd->timer); | ||
3644 | mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); | ||
3645 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | ||
3646 | |||
3647 | if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD)) | ||
3648 | return -1; | ||
3649 | |||
3650 | return 0; | ||
3651 | } | ||
3652 | #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */ | ||
3653 | 3136 | ||
3654 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3137 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3655 | /** | 3138 | /** |
@@ -3903,93 +3386,6 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3903 | 3386 | ||
3904 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3387 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3905 | /** | 3388 | /** |
3906 | * mptscsih_negotiate_to_asyn_narrow - Restore devices to default state | ||
3907 | * @hd: Pointer to a SCSI HOST structure | ||
3908 | * @vtarget: per device private data | ||
3909 | * | ||
3910 | * Uses the ISR, but with special processing. | ||
3911 | * MUST be single-threaded. | ||
3912 | * | ||
3913 | */ | ||
3914 | static void | ||
3915 | mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | ||
3916 | { | ||
3917 | VirtTarget *vtarget = vdevice->vtarget; | ||
3918 | MPT_ADAPTER *ioc= hd->ioc; | ||
3919 | SCSIDevicePage1_t *pcfg1Data; | ||
3920 | CONFIGPARMS cfg; | ||
3921 | dma_addr_t cfg1_dma_addr; | ||
3922 | ConfigPageHeader_t header; | ||
3923 | int id; | ||
3924 | int requested, configuration, data,i; | ||
3925 | u8 flags, factor; | ||
3926 | |||
3927 | if ((ioc->bus_type != SPI) || | ||
3928 | (!vdevice->configured_lun)) | ||
3929 | return; | ||
3930 | |||
3931 | if (!ioc->spi_data.sdp1length) | ||
3932 | return; | ||
3933 | |||
3934 | pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev, | ||
3935 | ioc->spi_data.sdp1length * 4, &cfg1_dma_addr); | ||
3936 | |||
3937 | if (pcfg1Data == NULL) | ||
3938 | return; | ||
3939 | |||
3940 | header.PageVersion = ioc->spi_data.sdp1version; | ||
3941 | header.PageLength = ioc->spi_data.sdp1length; | ||
3942 | header.PageNumber = 1; | ||
3943 | header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
3944 | cfg.cfghdr.hdr = &header; | ||
3945 | cfg.physAddr = cfg1_dma_addr; | ||
3946 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
3947 | cfg.dir = 1; | ||
3948 | cfg.timeout = 0; | ||
3949 | |||
3950 | if (vtarget->raidVolume && ioc->raid_data.pIocPg3) { | ||
3951 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
3952 | id = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID; | ||
3953 | flags = hd->ioc->spi_data.noQas; | ||
3954 | if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { | ||
3955 | data = hd->ioc->spi_data.nvram[id]; | ||
3956 | if (data & MPT_NVRAM_WIDE_DISABLE) | ||
3957 | flags |= MPT_TARGET_NO_NEGO_WIDE; | ||
3958 | factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; | ||
3959 | if ((factor == 0) || (factor == MPT_ASYNC)) | ||
3960 | flags |= MPT_TARGET_NO_NEGO_SYNC; | ||
3961 | } | ||
3962 | mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, | ||
3963 | &configuration, flags); | ||
3964 | dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC " | ||
3965 | "offset=0 negoFlags=%x request=%x config=%x\n", | ||
3966 | id, flags, requested, configuration)); | ||
3967 | pcfg1Data->RequestedParameters = cpu_to_le32(requested); | ||
3968 | pcfg1Data->Reserved = 0; | ||
3969 | pcfg1Data->Configuration = cpu_to_le32(configuration); | ||
3970 | cfg.pageAddr = (vtarget->bus_id<<8) | id; | ||
3971 | mpt_config(hd->ioc, &cfg); | ||
3972 | } | ||
3973 | } else { | ||
3974 | flags = vtarget->negoFlags; | ||
3975 | mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, | ||
3976 | &configuration, flags); | ||
3977 | dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC " | ||
3978 | "offset=0 negoFlags=%x request=%x config=%x\n", | ||
3979 | vtarget->target_id, flags, requested, configuration)); | ||
3980 | pcfg1Data->RequestedParameters = cpu_to_le32(requested); | ||
3981 | pcfg1Data->Reserved = 0; | ||
3982 | pcfg1Data->Configuration = cpu_to_le32(configuration); | ||
3983 | cfg.pageAddr = (vtarget->bus_id<<8) | vtarget->target_id; | ||
3984 | mpt_config(hd->ioc, &cfg); | ||
3985 | } | ||
3986 | |||
3987 | if (pcfg1Data) | ||
3988 | pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr); | ||
3989 | } | ||
3990 | |||
3991 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
3992 | /** | ||
3993 | * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. | 3389 | * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. |
3994 | * @hd: Pointer to a SCSI HOST structure | 3390 | * @hd: Pointer to a SCSI HOST structure |
3995 | * @vtarget: per device private data | 3391 | * @vtarget: per device private data |
@@ -4018,1633 +3414,11 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | |||
4018 | iocmd.id = vdevice->target_id; | 3414 | iocmd.id = vdevice->target_id; |
4019 | iocmd.lun = (u8)vdevice->lun; | 3415 | iocmd.lun = (u8)vdevice->lun; |
4020 | 3416 | ||
4021 | if ((vdevice->vtarget->type & TYPE_DISK) && | 3417 | if ((vdevice->vtarget->type == TYPE_DISK) && |
4022 | (vdevice->configured_lun)) | 3418 | (vdevice->configured_lun)) |
4023 | mptscsih_do_cmd(hd, &iocmd); | 3419 | mptscsih_do_cmd(hd, &iocmd); |
4024 | } | 3420 | } |
4025 | 3421 | ||
4026 | /* Search IOC page 3 to determine if this is hidden physical disk | ||
4027 | */ | ||
4028 | static int | ||
4029 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) | ||
4030 | { | ||
4031 | int i; | ||
4032 | |||
4033 | if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) | ||
4034 | return 0; | ||
4035 | |||
4036 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
4037 | if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) | ||
4038 | return 1; | ||
4039 | } | ||
4040 | |||
4041 | return 0; | ||
4042 | } | ||
4043 | |||
4044 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
4045 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
4046 | /** | ||
4047 | * mptscsih_domainValidation - Top level handler for domain validation. | ||
4048 | * @hd: Pointer to MPT_SCSI_HOST structure. | ||
4049 | * | ||
4050 | * Uses the ISR, but with special processing. | ||
4051 | * Called from schedule, should not be in interrupt mode. | ||
4052 | * While thread alive, do dv for all devices needing dv | ||
4053 | * | ||
4054 | * Return: None. | ||
4055 | */ | ||
4056 | static void | ||
4057 | mptscsih_domainValidation(void *arg) | ||
4058 | { | ||
4059 | MPT_SCSI_HOST *hd; | ||
4060 | MPT_ADAPTER *ioc; | ||
4061 | unsigned long flags; | ||
4062 | int id, maxid, dvStatus, did; | ||
4063 | int ii, isPhysDisk; | ||
4064 | |||
4065 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
4066 | dvtaskQ_active = 1; | ||
4067 | if (dvtaskQ_release) { | ||
4068 | dvtaskQ_active = 0; | ||
4069 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4070 | return; | ||
4071 | } | ||
4072 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4073 | |||
4074 | /* For this ioc, loop through all devices and do dv to each device. | ||
4075 | * When complete with this ioc, search through the ioc list, and | ||
4076 | * for each scsi ioc found, do dv for all devices. Exit when no | ||
4077 | * device needs dv. | ||
4078 | */ | ||
4079 | did = 1; | ||
4080 | while (did) { | ||
4081 | did = 0; | ||
4082 | list_for_each_entry(ioc, &ioc_list, list) { | ||
4083 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
4084 | if (dvtaskQ_release) { | ||
4085 | dvtaskQ_active = 0; | ||
4086 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4087 | return; | ||
4088 | } | ||
4089 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4090 | |||
4091 | msleep(250); | ||
4092 | |||
4093 | /* DV only to SPI adapters */ | ||
4094 | if (ioc->bus_type != SPI) | ||
4095 | continue; | ||
4096 | |||
4097 | /* Make sure everything looks ok */ | ||
4098 | if (ioc->sh == NULL) | ||
4099 | continue; | ||
4100 | |||
4101 | hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; | ||
4102 | if (hd == NULL) | ||
4103 | continue; | ||
4104 | |||
4105 | if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { | ||
4106 | mpt_read_ioc_pg_3(ioc); | ||
4107 | if (ioc->raid_data.pIocPg3) { | ||
4108 | Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; | ||
4109 | int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; | ||
4110 | |||
4111 | while (numPDisk) { | ||
4112 | if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) | ||
4113 | ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; | ||
4114 | |||
4115 | pPDisk++; | ||
4116 | numPDisk--; | ||
4117 | } | ||
4118 | } | ||
4119 | ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3; | ||
4120 | } | ||
4121 | |||
4122 | maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES); | ||
4123 | |||
4124 | for (id = 0; id < maxid; id++) { | ||
4125 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
4126 | if (dvtaskQ_release) { | ||
4127 | dvtaskQ_active = 0; | ||
4128 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4129 | return; | ||
4130 | } | ||
4131 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4132 | dvStatus = hd->ioc->spi_data.dvStatus[id]; | ||
4133 | |||
4134 | if (dvStatus & MPT_SCSICFG_NEED_DV) { | ||
4135 | did++; | ||
4136 | hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING; | ||
4137 | hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV; | ||
4138 | |||
4139 | msleep(250); | ||
4140 | |||
4141 | /* If hidden phys disk, block IO's to all | ||
4142 | * raid volumes | ||
4143 | * else, process normally | ||
4144 | */ | ||
4145 | isPhysDisk = mptscsih_is_phys_disk(ioc, id); | ||
4146 | if (isPhysDisk) { | ||
4147 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | ||
4148 | if (hd->ioc->raid_data.isRaid & (1 << ii)) { | ||
4149 | hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING; | ||
4150 | } | ||
4151 | } | ||
4152 | } | ||
4153 | |||
4154 | if(mpt_alt_ioc_wait(hd->ioc)!=0) { | ||
4155 | ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n", | ||
4156 | hd->ioc->name)); | ||
4157 | continue; | ||
4158 | } | ||
4159 | |||
4160 | if (mptscsih_doDv(hd, 0, id) == 1) { | ||
4161 | /* Untagged device was busy, try again | ||
4162 | */ | ||
4163 | hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV; | ||
4164 | hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING; | ||
4165 | } else { | ||
4166 | /* DV is complete. Clear flags. | ||
4167 | */ | ||
4168 | hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING); | ||
4169 | } | ||
4170 | |||
4171 | spin_lock(&hd->ioc->initializing_hba_lock); | ||
4172 | hd->ioc->initializing_hba_lock_flag=0; | ||
4173 | spin_unlock(&hd->ioc->initializing_hba_lock); | ||
4174 | |||
4175 | if (isPhysDisk) { | ||
4176 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | ||
4177 | if (hd->ioc->raid_data.isRaid & (1 << ii)) { | ||
4178 | hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING; | ||
4179 | } | ||
4180 | } | ||
4181 | } | ||
4182 | |||
4183 | if (hd->ioc->spi_data.noQas) | ||
4184 | mptscsih_qas_check(hd, id); | ||
4185 | } | ||
4186 | } | ||
4187 | } | ||
4188 | } | ||
4189 | |||
4190 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
4191 | dvtaskQ_active = 0; | ||
4192 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4193 | |||
4194 | return; | ||
4195 | } | ||
4196 | |||
4197 | /* Write SDP1 if no QAS has been enabled | ||
4198 | */ | ||
4199 | static void | ||
4200 | mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) | ||
4201 | { | ||
4202 | VirtTarget *vtarget; | ||
4203 | int ii; | ||
4204 | |||
4205 | if (hd->Targets == NULL) | ||
4206 | return; | ||
4207 | |||
4208 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | ||
4209 | if (ii == id) | ||
4210 | continue; | ||
4211 | |||
4212 | if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0) | ||
4213 | continue; | ||
4214 | |||
4215 | vtarget = hd->Targets[ii]; | ||
4216 | |||
4217 | if ((vtarget != NULL) && (!vtarget->raidVolume)) { | ||
4218 | if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) { | ||
4219 | vtarget->negoFlags |= hd->ioc->spi_data.noQas; | ||
4220 | dnegoprintk(("writeSDP1: id=%d flags=0\n", id)); | ||
4221 | mptscsih_writeSDP1(hd, 0, ii, 0); | ||
4222 | } | ||
4223 | } else { | ||
4224 | if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) { | ||
4225 | dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id)); | ||
4226 | mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM); | ||
4227 | } | ||
4228 | } | ||
4229 | } | ||
4230 | return; | ||
4231 | } | ||
4232 | |||
4233 | |||
4234 | |||
4235 | #define MPT_GET_NVRAM_VALS 0x01 | ||
4236 | #define MPT_UPDATE_MAX 0x02 | ||
4237 | #define MPT_SET_MAX 0x04 | ||
4238 | #define MPT_SET_MIN 0x08 | ||
4239 | #define MPT_FALLBACK 0x10 | ||
4240 | #define MPT_SAVE 0x20 | ||
4241 | |||
4242 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
4243 | /** | ||
4244 | * mptscsih_doDv - Perform domain validation to a target. | ||
4245 | * @hd: Pointer to MPT_SCSI_HOST structure. | ||
4246 | * @portnum: IOC port number. | ||
4247 | * @target: Physical ID of this target | ||
4248 | * | ||
4249 | * Uses the ISR, but with special processing. | ||
4250 | * MUST be single-threaded. | ||
4251 | * Test will exit if target is at async & narrow. | ||
4252 | * | ||
4253 | * Return: None. | ||
4254 | */ | ||
4255 | static int | ||
4256 | mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) | ||
4257 | { | ||
4258 | MPT_ADAPTER *ioc = hd->ioc; | ||
4259 | VirtTarget *vtarget; | ||
4260 | SCSIDevicePage1_t *pcfg1Data; | ||
4261 | SCSIDevicePage0_t *pcfg0Data; | ||
4262 | u8 *pbuf1; | ||
4263 | u8 *pbuf2; | ||
4264 | u8 *pDvBuf; | ||
4265 | dma_addr_t dvbuf_dma = -1; | ||
4266 | dma_addr_t buf1_dma = -1; | ||
4267 | dma_addr_t buf2_dma = -1; | ||
4268 | dma_addr_t cfg1_dma_addr = -1; | ||
4269 | dma_addr_t cfg0_dma_addr = -1; | ||
4270 | ConfigPageHeader_t header1; | ||
4271 | ConfigPageHeader_t header0; | ||
4272 | DVPARAMETERS dv; | ||
4273 | INTERNAL_CMD iocmd; | ||
4274 | CONFIGPARMS cfg; | ||
4275 | int dv_alloc = 0; | ||
4276 | int rc, sz = 0; | ||
4277 | int bufsize = 0; | ||
4278 | int dataBufSize = 0; | ||
4279 | int echoBufSize = 0; | ||
4280 | int notDone; | ||
4281 | int patt; | ||
4282 | int repeat; | ||
4283 | int retcode = 0; | ||
4284 | int nfactor = MPT_ULTRA320; | ||
4285 | char firstPass = 1; | ||
4286 | char doFallback = 0; | ||
4287 | char readPage0; | ||
4288 | char bus, lun; | ||
4289 | char inq0 = 0; | ||
4290 | |||
4291 | if (ioc->spi_data.sdp1length == 0) | ||
4292 | return 0; | ||
4293 | |||
4294 | if (ioc->spi_data.sdp0length == 0) | ||
4295 | return 0; | ||
4296 | |||
4297 | /* If multiple buses are used, require that the initiator | ||
4298 | * id be the same on all buses. | ||
4299 | */ | ||
4300 | if (id == ioc->pfacts[0].PortSCSIID) | ||
4301 | return 0; | ||
4302 | |||
4303 | lun = 0; | ||
4304 | bus = (u8) bus_number; | ||
4305 | ddvtprintk((MYIOC_s_NOTE_FMT | ||
4306 | "DV started: bus=%d, id=%d dv @ %p\n", | ||
4307 | ioc->name, bus, id, &dv)); | ||
4308 | |||
4309 | /* Prep DV structure | ||
4310 | */ | ||
4311 | memset (&dv, 0, sizeof(DVPARAMETERS)); | ||
4312 | dv.id = id; | ||
4313 | |||
4314 | /* Populate tmax with the current maximum | ||
4315 | * transfer parameters for this target. | ||
4316 | * Exit if narrow and async. | ||
4317 | */ | ||
4318 | dv.cmd = MPT_GET_NVRAM_VALS; | ||
4319 | mptscsih_dv_parms(hd, &dv, NULL); | ||
4320 | |||
4321 | /* Prep SCSI IO structure | ||
4322 | */ | ||
4323 | iocmd.id = id; | ||
4324 | iocmd.bus = bus; | ||
4325 | iocmd.lun = lun; | ||
4326 | iocmd.flags = 0; | ||
4327 | iocmd.physDiskNum = -1; | ||
4328 | iocmd.rsvd = iocmd.rsvd2 = 0; | ||
4329 | |||
4330 | vtarget = hd->Targets[id]; | ||
4331 | |||
4332 | /* Use tagged commands if possible. | ||
4333 | */ | ||
4334 | if (vtarget) { | ||
4335 | if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) | ||
4336 | iocmd.flags |= MPT_ICFLAG_TAGGED_CMD; | ||
4337 | else { | ||
4338 | if (hd->ioc->facts.FWVersion.Word < 0x01000600) | ||
4339 | return 0; | ||
4340 | |||
4341 | if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && | ||
4342 | (hd->ioc->facts.FWVersion.Word < 0x01010B00)) | ||
4343 | return 0; | ||
4344 | } | ||
4345 | } | ||
4346 | |||
4347 | /* Prep cfg structure | ||
4348 | */ | ||
4349 | cfg.pageAddr = (bus<<8) | id; | ||
4350 | cfg.cfghdr.hdr = NULL; | ||
4351 | |||
4352 | /* Prep SDP0 header | ||
4353 | */ | ||
4354 | header0.PageVersion = ioc->spi_data.sdp0version; | ||
4355 | header0.PageLength = ioc->spi_data.sdp0length; | ||
4356 | header0.PageNumber = 0; | ||
4357 | header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
4358 | |||
4359 | /* Prep SDP1 header | ||
4360 | */ | ||
4361 | header1.PageVersion = ioc->spi_data.sdp1version; | ||
4362 | header1.PageLength = ioc->spi_data.sdp1length; | ||
4363 | header1.PageNumber = 1; | ||
4364 | header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
4365 | |||
4366 | if (header0.PageLength & 1) | ||
4367 | dv_alloc = (header0.PageLength * 4) + 4; | ||
4368 | |||
4369 | dv_alloc += (2048 + (header1.PageLength * 4)); | ||
4370 | |||
4371 | pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma); | ||
4372 | if (pDvBuf == NULL) | ||
4373 | return 0; | ||
4374 | |||
4375 | sz = 0; | ||
4376 | pbuf1 = (u8 *)pDvBuf; | ||
4377 | buf1_dma = dvbuf_dma; | ||
4378 | sz +=1024; | ||
4379 | |||
4380 | pbuf2 = (u8 *) (pDvBuf + sz); | ||
4381 | buf2_dma = dvbuf_dma + sz; | ||
4382 | sz +=1024; | ||
4383 | |||
4384 | pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz); | ||
4385 | cfg0_dma_addr = dvbuf_dma + sz; | ||
4386 | sz += header0.PageLength * 4; | ||
4387 | |||
4388 | /* 8-byte alignment | ||
4389 | */ | ||
4390 | if (header0.PageLength & 1) | ||
4391 | sz += 4; | ||
4392 | |||
4393 | pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz); | ||
4394 | cfg1_dma_addr = dvbuf_dma + sz; | ||
4395 | |||
4396 | /* Skip this ID? Set cfg.cfghdr.hdr to force config page write | ||
4397 | */ | ||
4398 | { | ||
4399 | SpiCfgData *pspi_data = &hd->ioc->spi_data; | ||
4400 | if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { | ||
4401 | /* Set the factor from nvram */ | ||
4402 | nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; | ||
4403 | if (nfactor < pspi_data->minSyncFactor ) | ||
4404 | nfactor = pspi_data->minSyncFactor; | ||
4405 | |||
4406 | if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) || | ||
4407 | (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) { | ||
4408 | |||
4409 | ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n", | ||
4410 | ioc->name, bus, id, lun)); | ||
4411 | |||
4412 | dv.cmd = MPT_SET_MAX; | ||
4413 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
4414 | cfg.cfghdr.hdr = &header1; | ||
4415 | |||
4416 | /* Save the final negotiated settings to | ||
4417 | * SCSI device page 1. | ||
4418 | */ | ||
4419 | cfg.physAddr = cfg1_dma_addr; | ||
4420 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
4421 | cfg.dir = 1; | ||
4422 | mpt_config(hd->ioc, &cfg); | ||
4423 | goto target_done; | ||
4424 | } | ||
4425 | } | ||
4426 | } | ||
4427 | |||
4428 | /* Finish iocmd inititialization - hidden or visible disk? */ | ||
4429 | if (ioc->raid_data.pIocPg3) { | ||
4430 | /* Search IOC page 3 for matching id | ||
4431 | */ | ||
4432 | Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; | ||
4433 | int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; | ||
4434 | |||
4435 | while (numPDisk) { | ||
4436 | if (pPDisk->PhysDiskID == id) { | ||
4437 | /* match */ | ||
4438 | iocmd.flags |= MPT_ICFLAG_PHYS_DISK; | ||
4439 | iocmd.physDiskNum = pPDisk->PhysDiskNum; | ||
4440 | |||
4441 | /* Quiesce the IM | ||
4442 | */ | ||
4443 | if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) { | ||
4444 | ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name)); | ||
4445 | goto target_done; | ||
4446 | } | ||
4447 | break; | ||
4448 | } | ||
4449 | pPDisk++; | ||
4450 | numPDisk--; | ||
4451 | } | ||
4452 | } | ||
4453 | |||
4454 | /* RAID Volume ID's may double for a physical device. If RAID but | ||
4455 | * not a physical ID as well, skip DV. | ||
4456 | */ | ||
4457 | if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) | ||
4458 | goto target_done; | ||
4459 | |||
4460 | |||
4461 | /* Basic Test. | ||
4462 | * Async & Narrow - Inquiry | ||
4463 | * Async & Narrow - Inquiry | ||
4464 | * Maximum transfer rate - Inquiry | ||
4465 | * Compare buffers: | ||
4466 | * If compare, test complete. | ||
4467 | * If miscompare and first pass, repeat | ||
4468 | * If miscompare and not first pass, fall back and repeat | ||
4469 | */ | ||
4470 | hd->pLocal = NULL; | ||
4471 | readPage0 = 0; | ||
4472 | sz = SCSI_MAX_INQUIRY_BYTES; | ||
4473 | rc = MPT_SCANDV_GOOD; | ||
4474 | while (1) { | ||
4475 | ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id)); | ||
4476 | retcode = 0; | ||
4477 | dv.cmd = MPT_SET_MIN; | ||
4478 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
4479 | |||
4480 | cfg.cfghdr.hdr = &header1; | ||
4481 | cfg.physAddr = cfg1_dma_addr; | ||
4482 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
4483 | cfg.dir = 1; | ||
4484 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
4485 | goto target_done; | ||
4486 | |||
4487 | /* Wide - narrow - wide workaround case | ||
4488 | */ | ||
4489 | if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) { | ||
4490 | /* Send an untagged command to reset disk Qs corrupted | ||
4491 | * when a parity error occurs on a Request Sense. | ||
4492 | */ | ||
4493 | if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) || | ||
4494 | ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && | ||
4495 | (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) { | ||
4496 | |||
4497 | iocmd.cmd = REQUEST_SENSE; | ||
4498 | iocmd.data_dma = buf1_dma; | ||
4499 | iocmd.data = pbuf1; | ||
4500 | iocmd.size = 0x12; | ||
4501 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4502 | goto target_done; | ||
4503 | else { | ||
4504 | if (hd->pLocal == NULL) | ||
4505 | goto target_done; | ||
4506 | rc = hd->pLocal->completion; | ||
4507 | if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) { | ||
4508 | dv.max.width = 0; | ||
4509 | doFallback = 0; | ||
4510 | } else | ||
4511 | goto target_done; | ||
4512 | } | ||
4513 | } else | ||
4514 | goto target_done; | ||
4515 | } | ||
4516 | |||
4517 | iocmd.cmd = INQUIRY; | ||
4518 | iocmd.data_dma = buf1_dma; | ||
4519 | iocmd.data = pbuf1; | ||
4520 | iocmd.size = sz; | ||
4521 | memset(pbuf1, 0x00, sz); | ||
4522 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4523 | goto target_done; | ||
4524 | else { | ||
4525 | if (hd->pLocal == NULL) | ||
4526 | goto target_done; | ||
4527 | rc = hd->pLocal->completion; | ||
4528 | if (rc == MPT_SCANDV_GOOD) { | ||
4529 | if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) { | ||
4530 | if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0) | ||
4531 | retcode = 1; | ||
4532 | else | ||
4533 | retcode = 0; | ||
4534 | |||
4535 | goto target_done; | ||
4536 | } | ||
4537 | } else if (rc == MPT_SCANDV_SENSE) { | ||
4538 | ; | ||
4539 | } else { | ||
4540 | /* If first command doesn't complete | ||
4541 | * with a good status or with a check condition, | ||
4542 | * exit. | ||
4543 | */ | ||
4544 | goto target_done; | ||
4545 | } | ||
4546 | } | ||
4547 | |||
4548 | /* Reset the size for disks | ||
4549 | */ | ||
4550 | inq0 = (*pbuf1) & 0x1F; | ||
4551 | if ((inq0 == 0) && vtarget && !vtarget->raidVolume) { | ||
4552 | sz = 0x40; | ||
4553 | iocmd.size = sz; | ||
4554 | } | ||
4555 | |||
4556 | /* Another GEM workaround. Check peripheral device type, | ||
4557 | * if PROCESSOR, quit DV. | ||
4558 | */ | ||
4559 | if (inq0 == TYPE_PROCESSOR) { | ||
4560 | mptscsih_initTarget(hd, | ||
4561 | vtarget, | ||
4562 | lun, | ||
4563 | pbuf1, | ||
4564 | sz); | ||
4565 | goto target_done; | ||
4566 | } | ||
4567 | |||
4568 | if (inq0 > 0x08) | ||
4569 | goto target_done; | ||
4570 | |||
4571 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4572 | goto target_done; | ||
4573 | |||
4574 | if (sz == 0x40) { | ||
4575 | if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A) | ||
4576 | && (vtarget->minSyncFactor > 0x09)) { | ||
4577 | if ((pbuf1[56] & 0x04) == 0) | ||
4578 | ; | ||
4579 | else if ((pbuf1[56] & 0x01) == 1) { | ||
4580 | vtarget->minSyncFactor = | ||
4581 | nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320; | ||
4582 | } else { | ||
4583 | vtarget->minSyncFactor = | ||
4584 | nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160; | ||
4585 | } | ||
4586 | |||
4587 | dv.max.factor = vtarget->minSyncFactor; | ||
4588 | |||
4589 | if ((pbuf1[56] & 0x02) == 0) { | ||
4590 | vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; | ||
4591 | hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; | ||
4592 | ddvprintk((MYIOC_s_NOTE_FMT | ||
4593 | "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", | ||
4594 | ioc->name, id, pbuf1[56])); | ||
4595 | } | ||
4596 | } | ||
4597 | } | ||
4598 | |||
4599 | if (doFallback) | ||
4600 | dv.cmd = MPT_FALLBACK; | ||
4601 | else | ||
4602 | dv.cmd = MPT_SET_MAX; | ||
4603 | |||
4604 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
4605 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
4606 | goto target_done; | ||
4607 | |||
4608 | if ((!dv.now.width) && (!dv.now.offset)) | ||
4609 | goto target_done; | ||
4610 | |||
4611 | iocmd.cmd = INQUIRY; | ||
4612 | iocmd.data_dma = buf2_dma; | ||
4613 | iocmd.data = pbuf2; | ||
4614 | iocmd.size = sz; | ||
4615 | memset(pbuf2, 0x00, sz); | ||
4616 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4617 | goto target_done; | ||
4618 | else if (hd->pLocal == NULL) | ||
4619 | goto target_done; | ||
4620 | else { | ||
4621 | /* Save the return code. | ||
4622 | * If this is the first pass, | ||
4623 | * read SCSI Device Page 0 | ||
4624 | * and update the target max parameters. | ||
4625 | */ | ||
4626 | rc = hd->pLocal->completion; | ||
4627 | doFallback = 0; | ||
4628 | if (rc == MPT_SCANDV_GOOD) { | ||
4629 | if (!readPage0) { | ||
4630 | u32 sdp0_info; | ||
4631 | u32 sdp0_nego; | ||
4632 | |||
4633 | cfg.cfghdr.hdr = &header0; | ||
4634 | cfg.physAddr = cfg0_dma_addr; | ||
4635 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
4636 | cfg.dir = 0; | ||
4637 | |||
4638 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
4639 | goto target_done; | ||
4640 | |||
4641 | sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E; | ||
4642 | sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8; | ||
4643 | |||
4644 | /* Quantum and Fujitsu workarounds. | ||
4645 | * Quantum: PPR U320 -> PPR reply with Ultra2 and wide | ||
4646 | * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide | ||
4647 | * Resetart with a request for U160. | ||
4648 | */ | ||
4649 | if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) { | ||
4650 | doFallback = 1; | ||
4651 | } else { | ||
4652 | dv.cmd = MPT_UPDATE_MAX; | ||
4653 | mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data); | ||
4654 | /* Update the SCSI device page 1 area | ||
4655 | */ | ||
4656 | pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters; | ||
4657 | readPage0 = 1; | ||
4658 | } | ||
4659 | } | ||
4660 | |||
4661 | /* Quantum workaround. Restart this test will the fallback | ||
4662 | * flag set. | ||
4663 | */ | ||
4664 | if (doFallback == 0) { | ||
4665 | if (memcmp(pbuf1, pbuf2, sz) != 0) { | ||
4666 | if (!firstPass) | ||
4667 | doFallback = 1; | ||
4668 | } else { | ||
4669 | ddvprintk((MYIOC_s_NOTE_FMT | ||
4670 | "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id)); | ||
4671 | hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE; | ||
4672 | mptscsih_initTarget(hd, | ||
4673 | vtarget, | ||
4674 | lun, | ||
4675 | pbuf1, | ||
4676 | sz); | ||
4677 | break; /* test complete */ | ||
4678 | } | ||
4679 | } | ||
4680 | |||
4681 | |||
4682 | } else if (rc == MPT_SCANDV_ISSUE_SENSE) | ||
4683 | doFallback = 1; /* set fallback flag */ | ||
4684 | else if ((rc == MPT_SCANDV_DID_RESET) || | ||
4685 | (rc == MPT_SCANDV_SENSE) || | ||
4686 | (rc == MPT_SCANDV_FALLBACK)) | ||
4687 | doFallback = 1; /* set fallback flag */ | ||
4688 | else | ||
4689 | goto target_done; | ||
4690 | |||
4691 | firstPass = 0; | ||
4692 | } | ||
4693 | } | ||
4694 | ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id)); | ||
4695 | |||
4696 | if (ioc->spi_data.mpt_dv == 0) | ||
4697 | goto target_done; | ||
4698 | |||
4699 | inq0 = (*pbuf1) & 0x1F; | ||
4700 | |||
4701 | /* Continue only for disks | ||
4702 | */ | ||
4703 | if (inq0 != 0) | ||
4704 | goto target_done; | ||
4705 | |||
4706 | if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY ) | ||
4707 | goto target_done; | ||
4708 | |||
4709 | /* Start the Enhanced Test. | ||
4710 | * 0) issue TUR to clear out check conditions | ||
4711 | * 1) read capacity of echo (regular) buffer | ||
4712 | * 2) reserve device | ||
4713 | * 3) do write-read-compare data pattern test | ||
4714 | * 4) release | ||
4715 | * 5) update nego parms to target struct | ||
4716 | */ | ||
4717 | cfg.cfghdr.hdr = &header1; | ||
4718 | cfg.physAddr = cfg1_dma_addr; | ||
4719 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
4720 | cfg.dir = 1; | ||
4721 | |||
4722 | iocmd.cmd = TEST_UNIT_READY; | ||
4723 | iocmd.data_dma = -1; | ||
4724 | iocmd.data = NULL; | ||
4725 | iocmd.size = 0; | ||
4726 | notDone = 1; | ||
4727 | while (notDone) { | ||
4728 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4729 | goto target_done; | ||
4730 | |||
4731 | if (hd->pLocal == NULL) | ||
4732 | goto target_done; | ||
4733 | |||
4734 | rc = hd->pLocal->completion; | ||
4735 | if (rc == MPT_SCANDV_GOOD) | ||
4736 | notDone = 0; | ||
4737 | else if (rc == MPT_SCANDV_SENSE) { | ||
4738 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
4739 | u8 asc = hd->pLocal->sense[12]; | ||
4740 | u8 ascq = hd->pLocal->sense[13]; | ||
4741 | ddvprintk((MYIOC_s_INFO_FMT | ||
4742 | "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", | ||
4743 | ioc->name, skey, asc, ascq)); | ||
4744 | |||
4745 | if (skey == UNIT_ATTENTION) | ||
4746 | notDone++; /* repeat */ | ||
4747 | else if ((skey == NOT_READY) && | ||
4748 | (asc == 0x04)&&(ascq == 0x01)) { | ||
4749 | /* wait then repeat */ | ||
4750 | mdelay (2000); | ||
4751 | notDone++; | ||
4752 | } else if ((skey == NOT_READY) && (asc == 0x3A)) { | ||
4753 | /* no medium, try read test anyway */ | ||
4754 | notDone = 0; | ||
4755 | } else { | ||
4756 | /* All other errors are fatal. | ||
4757 | */ | ||
4758 | ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.", | ||
4759 | ioc->name)); | ||
4760 | goto target_done; | ||
4761 | } | ||
4762 | } else | ||
4763 | goto target_done; | ||
4764 | } | ||
4765 | |||
4766 | iocmd.cmd = READ_BUFFER; | ||
4767 | iocmd.data_dma = buf1_dma; | ||
4768 | iocmd.data = pbuf1; | ||
4769 | iocmd.size = 4; | ||
4770 | iocmd.flags |= MPT_ICFLAG_BUF_CAP; | ||
4771 | |||
4772 | dataBufSize = 0; | ||
4773 | echoBufSize = 0; | ||
4774 | for (patt = 0; patt < 2; patt++) { | ||
4775 | if (patt == 0) | ||
4776 | iocmd.flags |= MPT_ICFLAG_ECHO; | ||
4777 | else | ||
4778 | iocmd.flags &= ~MPT_ICFLAG_ECHO; | ||
4779 | |||
4780 | notDone = 1; | ||
4781 | while (notDone) { | ||
4782 | bufsize = 0; | ||
4783 | |||
4784 | /* If not ready after 8 trials, | ||
4785 | * give up on this device. | ||
4786 | */ | ||
4787 | if (notDone > 8) | ||
4788 | goto target_done; | ||
4789 | |||
4790 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4791 | goto target_done; | ||
4792 | else if (hd->pLocal == NULL) | ||
4793 | goto target_done; | ||
4794 | else { | ||
4795 | rc = hd->pLocal->completion; | ||
4796 | ddvprintk(("ReadBuffer Comp Code %d", rc)); | ||
4797 | ddvprintk((" buff: %0x %0x %0x %0x\n", | ||
4798 | pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3])); | ||
4799 | |||
4800 | if (rc == MPT_SCANDV_GOOD) { | ||
4801 | notDone = 0; | ||
4802 | if (iocmd.flags & MPT_ICFLAG_ECHO) { | ||
4803 | bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3]; | ||
4804 | if (pbuf1[0] & 0x01) | ||
4805 | iocmd.flags |= MPT_ICFLAG_EBOS; | ||
4806 | } else { | ||
4807 | bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3]; | ||
4808 | } | ||
4809 | } else if (rc == MPT_SCANDV_SENSE) { | ||
4810 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
4811 | u8 asc = hd->pLocal->sense[12]; | ||
4812 | u8 ascq = hd->pLocal->sense[13]; | ||
4813 | ddvprintk((MYIOC_s_INFO_FMT | ||
4814 | "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", | ||
4815 | ioc->name, skey, asc, ascq)); | ||
4816 | if (skey == ILLEGAL_REQUEST) { | ||
4817 | notDone = 0; | ||
4818 | } else if (skey == UNIT_ATTENTION) { | ||
4819 | notDone++; /* repeat */ | ||
4820 | } else if ((skey == NOT_READY) && | ||
4821 | (asc == 0x04)&&(ascq == 0x01)) { | ||
4822 | /* wait then repeat */ | ||
4823 | mdelay (2000); | ||
4824 | notDone++; | ||
4825 | } else { | ||
4826 | /* All other errors are fatal. | ||
4827 | */ | ||
4828 | ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.", | ||
4829 | ioc->name)); | ||
4830 | goto target_done; | ||
4831 | } | ||
4832 | } else { | ||
4833 | /* All other errors are fatal | ||
4834 | */ | ||
4835 | goto target_done; | ||
4836 | } | ||
4837 | } | ||
4838 | } | ||
4839 | |||
4840 | if (iocmd.flags & MPT_ICFLAG_ECHO) | ||
4841 | echoBufSize = bufsize; | ||
4842 | else | ||
4843 | dataBufSize = bufsize; | ||
4844 | } | ||
4845 | sz = 0; | ||
4846 | iocmd.flags &= ~MPT_ICFLAG_BUF_CAP; | ||
4847 | |||
4848 | /* Use echo buffers if possible, | ||
4849 | * Exit if both buffers are 0. | ||
4850 | */ | ||
4851 | if (echoBufSize > 0) { | ||
4852 | iocmd.flags |= MPT_ICFLAG_ECHO; | ||
4853 | if (dataBufSize > 0) | ||
4854 | bufsize = min(echoBufSize, dataBufSize); | ||
4855 | else | ||
4856 | bufsize = echoBufSize; | ||
4857 | } else if (dataBufSize == 0) | ||
4858 | goto target_done; | ||
4859 | |||
4860 | ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name, | ||
4861 | (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize)); | ||
4862 | |||
4863 | /* Data buffers for write-read-compare test max 1K. | ||
4864 | */ | ||
4865 | sz = min(bufsize, 1024); | ||
4866 | |||
4867 | /* --- loop ---- | ||
4868 | * On first pass, always issue a reserve. | ||
4869 | * On additional loops, only if a reset has occurred. | ||
4870 | * iocmd.flags indicates if echo or regular buffer | ||
4871 | */ | ||
4872 | for (patt = 0; patt < 4; patt++) { | ||
4873 | ddvprintk(("Pattern %d\n", patt)); | ||
4874 | if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) { | ||
4875 | iocmd.cmd = TEST_UNIT_READY; | ||
4876 | iocmd.data_dma = -1; | ||
4877 | iocmd.data = NULL; | ||
4878 | iocmd.size = 0; | ||
4879 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4880 | goto target_done; | ||
4881 | |||
4882 | iocmd.cmd = RELEASE; | ||
4883 | iocmd.data_dma = -1; | ||
4884 | iocmd.data = NULL; | ||
4885 | iocmd.size = 0; | ||
4886 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4887 | goto target_done; | ||
4888 | else if (hd->pLocal == NULL) | ||
4889 | goto target_done; | ||
4890 | else { | ||
4891 | rc = hd->pLocal->completion; | ||
4892 | ddvprintk(("Release rc %d\n", rc)); | ||
4893 | if (rc == MPT_SCANDV_GOOD) | ||
4894 | iocmd.flags &= ~MPT_ICFLAG_RESERVED; | ||
4895 | else | ||
4896 | goto target_done; | ||
4897 | } | ||
4898 | iocmd.flags &= ~MPT_ICFLAG_RESERVED; | ||
4899 | } | ||
4900 | iocmd.flags &= ~MPT_ICFLAG_DID_RESET; | ||
4901 | |||
4902 | if (iocmd.flags & MPT_ICFLAG_EBOS) | ||
4903 | goto skip_Reserve; | ||
4904 | |||
4905 | repeat = 5; | ||
4906 | while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) { | ||
4907 | iocmd.cmd = RESERVE; | ||
4908 | iocmd.data_dma = -1; | ||
4909 | iocmd.data = NULL; | ||
4910 | iocmd.size = 0; | ||
4911 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4912 | goto target_done; | ||
4913 | else if (hd->pLocal == NULL) | ||
4914 | goto target_done; | ||
4915 | else { | ||
4916 | rc = hd->pLocal->completion; | ||
4917 | if (rc == MPT_SCANDV_GOOD) { | ||
4918 | iocmd.flags |= MPT_ICFLAG_RESERVED; | ||
4919 | } else if (rc == MPT_SCANDV_SENSE) { | ||
4920 | /* Wait if coming ready | ||
4921 | */ | ||
4922 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
4923 | u8 asc = hd->pLocal->sense[12]; | ||
4924 | u8 ascq = hd->pLocal->sense[13]; | ||
4925 | ddvprintk((MYIOC_s_INFO_FMT | ||
4926 | "DV: Reserve Failed: ", ioc->name)); | ||
4927 | ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", | ||
4928 | skey, asc, ascq)); | ||
4929 | |||
4930 | if ((skey == NOT_READY) && (asc == 0x04)&& | ||
4931 | (ascq == 0x01)) { | ||
4932 | /* wait then repeat */ | ||
4933 | mdelay (2000); | ||
4934 | notDone++; | ||
4935 | } else { | ||
4936 | ddvprintk((MYIOC_s_INFO_FMT | ||
4937 | "DV: Reserved Failed.", ioc->name)); | ||
4938 | goto target_done; | ||
4939 | } | ||
4940 | } else { | ||
4941 | ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.", | ||
4942 | ioc->name)); | ||
4943 | goto target_done; | ||
4944 | } | ||
4945 | } | ||
4946 | } | ||
4947 | |||
4948 | skip_Reserve: | ||
4949 | mptscsih_fillbuf(pbuf1, sz, patt, 1); | ||
4950 | iocmd.cmd = WRITE_BUFFER; | ||
4951 | iocmd.data_dma = buf1_dma; | ||
4952 | iocmd.data = pbuf1; | ||
4953 | iocmd.size = sz; | ||
4954 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4955 | goto target_done; | ||
4956 | else if (hd->pLocal == NULL) | ||
4957 | goto target_done; | ||
4958 | else { | ||
4959 | rc = hd->pLocal->completion; | ||
4960 | if (rc == MPT_SCANDV_GOOD) | ||
4961 | ; /* Issue read buffer */ | ||
4962 | else if (rc == MPT_SCANDV_DID_RESET) { | ||
4963 | /* If using echo buffers, reset to data buffers. | ||
4964 | * Else do Fallback and restart | ||
4965 | * this test (re-issue reserve | ||
4966 | * because of bus reset). | ||
4967 | */ | ||
4968 | if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) { | ||
4969 | iocmd.flags &= ~MPT_ICFLAG_ECHO; | ||
4970 | } else { | ||
4971 | dv.cmd = MPT_FALLBACK; | ||
4972 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
4973 | |||
4974 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
4975 | goto target_done; | ||
4976 | |||
4977 | if ((!dv.now.width) && (!dv.now.offset)) | ||
4978 | goto target_done; | ||
4979 | } | ||
4980 | |||
4981 | iocmd.flags |= MPT_ICFLAG_DID_RESET; | ||
4982 | patt = -1; | ||
4983 | continue; | ||
4984 | } else if (rc == MPT_SCANDV_SENSE) { | ||
4985 | /* Restart data test if UA, else quit. | ||
4986 | */ | ||
4987 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
4988 | ddvprintk((MYIOC_s_INFO_FMT | ||
4989 | "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, | ||
4990 | hd->pLocal->sense[12], hd->pLocal->sense[13])); | ||
4991 | if (skey == UNIT_ATTENTION) { | ||
4992 | patt = -1; | ||
4993 | continue; | ||
4994 | } else if (skey == ILLEGAL_REQUEST) { | ||
4995 | if (iocmd.flags & MPT_ICFLAG_ECHO) { | ||
4996 | if (dataBufSize >= bufsize) { | ||
4997 | iocmd.flags &= ~MPT_ICFLAG_ECHO; | ||
4998 | patt = -1; | ||
4999 | continue; | ||
5000 | } | ||
5001 | } | ||
5002 | goto target_done; | ||
5003 | } | ||
5004 | else | ||
5005 | goto target_done; | ||
5006 | } else { | ||
5007 | /* fatal error */ | ||
5008 | goto target_done; | ||
5009 | } | ||
5010 | } | ||
5011 | |||
5012 | iocmd.cmd = READ_BUFFER; | ||
5013 | iocmd.data_dma = buf2_dma; | ||
5014 | iocmd.data = pbuf2; | ||
5015 | iocmd.size = sz; | ||
5016 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
5017 | goto target_done; | ||
5018 | else if (hd->pLocal == NULL) | ||
5019 | goto target_done; | ||
5020 | else { | ||
5021 | rc = hd->pLocal->completion; | ||
5022 | if (rc == MPT_SCANDV_GOOD) { | ||
5023 | /* If buffers compare, | ||
5024 | * go to next pattern, | ||
5025 | * else, do a fallback and restart | ||
5026 | * data transfer test. | ||
5027 | */ | ||
5028 | if (memcmp (pbuf1, pbuf2, sz) == 0) { | ||
5029 | ; /* goto next pattern */ | ||
5030 | } else { | ||
5031 | /* Miscompare with Echo buffer, go to data buffer, | ||
5032 | * if that buffer exists. | ||
5033 | * Miscompare with Data buffer, check first 4 bytes, | ||
5034 | * some devices return capacity. Exit in this case. | ||
5035 | */ | ||
5036 | if (iocmd.flags & MPT_ICFLAG_ECHO) { | ||
5037 | if (dataBufSize >= bufsize) | ||
5038 | iocmd.flags &= ~MPT_ICFLAG_ECHO; | ||
5039 | else | ||
5040 | goto target_done; | ||
5041 | } else { | ||
5042 | if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) { | ||
5043 | /* Argh. Device returning wrong data. | ||
5044 | * Quit DV for this device. | ||
5045 | */ | ||
5046 | goto target_done; | ||
5047 | } | ||
5048 | |||
5049 | /* Had an actual miscompare. Slow down.*/ | ||
5050 | dv.cmd = MPT_FALLBACK; | ||
5051 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
5052 | |||
5053 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
5054 | goto target_done; | ||
5055 | |||
5056 | if ((!dv.now.width) && (!dv.now.offset)) | ||
5057 | goto target_done; | ||
5058 | } | ||
5059 | |||
5060 | patt = -1; | ||
5061 | continue; | ||
5062 | } | ||
5063 | } else if (rc == MPT_SCANDV_DID_RESET) { | ||
5064 | /* Do Fallback and restart | ||
5065 | * this test (re-issue reserve | ||
5066 | * because of bus reset). | ||
5067 | */ | ||
5068 | dv.cmd = MPT_FALLBACK; | ||
5069 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
5070 | |||
5071 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
5072 | goto target_done; | ||
5073 | |||
5074 | if ((!dv.now.width) && (!dv.now.offset)) | ||
5075 | goto target_done; | ||
5076 | |||
5077 | iocmd.flags |= MPT_ICFLAG_DID_RESET; | ||
5078 | patt = -1; | ||
5079 | continue; | ||
5080 | } else if (rc == MPT_SCANDV_SENSE) { | ||
5081 | /* Restart data test if UA, else quit. | ||
5082 | */ | ||
5083 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
5084 | ddvprintk((MYIOC_s_INFO_FMT | ||
5085 | "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, | ||
5086 | hd->pLocal->sense[12], hd->pLocal->sense[13])); | ||
5087 | if (skey == UNIT_ATTENTION) { | ||
5088 | patt = -1; | ||
5089 | continue; | ||
5090 | } | ||
5091 | else | ||
5092 | goto target_done; | ||
5093 | } else { | ||
5094 | /* fatal error */ | ||
5095 | goto target_done; | ||
5096 | } | ||
5097 | } | ||
5098 | |||
5099 | } /* --- end of patt loop ---- */ | ||
5100 | |||
5101 | target_done: | ||
5102 | if (iocmd.flags & MPT_ICFLAG_RESERVED) { | ||
5103 | iocmd.cmd = RELEASE; | ||
5104 | iocmd.data_dma = -1; | ||
5105 | iocmd.data = NULL; | ||
5106 | iocmd.size = 0; | ||
5107 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
5108 | printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d", | ||
5109 | ioc->name, id); | ||
5110 | else if (hd->pLocal) { | ||
5111 | if (hd->pLocal->completion == MPT_SCANDV_GOOD) | ||
5112 | iocmd.flags &= ~MPT_ICFLAG_RESERVED; | ||
5113 | } else { | ||
5114 | printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d", | ||
5115 | ioc->name, id); | ||
5116 | } | ||
5117 | } | ||
5118 | |||
5119 | |||
5120 | /* Set if cfg1_dma_addr contents is valid | ||
5121 | */ | ||
5122 | if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){ | ||
5123 | /* If disk, not U320, disable QAS | ||
5124 | */ | ||
5125 | if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) { | ||
5126 | hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; | ||
5127 | ddvprintk((MYIOC_s_NOTE_FMT | ||
5128 | "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor)); | ||
5129 | } | ||
5130 | |||
5131 | dv.cmd = MPT_SAVE; | ||
5132 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
5133 | |||
5134 | /* Double writes to SDP1 can cause problems, | ||
5135 | * skip save of the final negotiated settings to | ||
5136 | * SCSI device page 1. | ||
5137 | * | ||
5138 | cfg.cfghdr.hdr = &header1; | ||
5139 | cfg.physAddr = cfg1_dma_addr; | ||
5140 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
5141 | cfg.dir = 1; | ||
5142 | mpt_config(hd->ioc, &cfg); | ||
5143 | */ | ||
5144 | } | ||
5145 | |||
5146 | /* If this is a RAID Passthrough, enable internal IOs | ||
5147 | */ | ||
5148 | if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) { | ||
5149 | if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0) | ||
5150 | ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name)); | ||
5151 | } | ||
5152 | |||
5153 | /* Done with the DV scan of the current target | ||
5154 | */ | ||
5155 | if (pDvBuf) | ||
5156 | pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma); | ||
5157 | |||
5158 | ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n", | ||
5159 | ioc->name, id)); | ||
5160 | |||
5161 | return retcode; | ||
5162 | } | ||
5163 | |||
5164 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
5165 | /* mptscsih_dv_parms - perform a variety of operations on the | ||
5166 | * parameters used for negotiation. | ||
5167 | * @hd: Pointer to a SCSI host. | ||
5168 | * @dv: Pointer to a structure that contains the maximum and current | ||
5169 | * negotiated parameters. | ||
5170 | */ | ||
5171 | static void | ||
5172 | mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) | ||
5173 | { | ||
5174 | VirtTarget *vtarget; | ||
5175 | SCSIDevicePage0_t *pPage0; | ||
5176 | SCSIDevicePage1_t *pPage1; | ||
5177 | int val = 0, data, configuration; | ||
5178 | u8 width = 0; | ||
5179 | u8 offset = 0; | ||
5180 | u8 factor = 0; | ||
5181 | u8 negoFlags = 0; | ||
5182 | u8 cmd = dv->cmd; | ||
5183 | u8 id = dv->id; | ||
5184 | |||
5185 | switch (cmd) { | ||
5186 | case MPT_GET_NVRAM_VALS: | ||
5187 | ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ", | ||
5188 | hd->ioc->name)); | ||
5189 | /* Get the NVRAM values and save in tmax | ||
5190 | * If not an LVD bus, the adapter minSyncFactor has been | ||
5191 | * already throttled back. | ||
5192 | */ | ||
5193 | negoFlags = hd->ioc->spi_data.noQas; | ||
5194 | if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) { | ||
5195 | width = vtarget->maxWidth; | ||
5196 | offset = vtarget->maxOffset; | ||
5197 | factor = vtarget->minSyncFactor; | ||
5198 | negoFlags |= vtarget->negoFlags; | ||
5199 | } else { | ||
5200 | if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { | ||
5201 | data = hd->ioc->spi_data.nvram[id]; | ||
5202 | width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; | ||
5203 | if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0) | ||
5204 | factor = MPT_ASYNC; | ||
5205 | else { | ||
5206 | factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; | ||
5207 | if ((factor == 0) || (factor == MPT_ASYNC)){ | ||
5208 | factor = MPT_ASYNC; | ||
5209 | offset = 0; | ||
5210 | } | ||
5211 | } | ||
5212 | } else { | ||
5213 | width = MPT_NARROW; | ||
5214 | offset = 0; | ||
5215 | factor = MPT_ASYNC; | ||
5216 | } | ||
5217 | |||
5218 | /* Set the negotiation flags */ | ||
5219 | if (!width) | ||
5220 | negoFlags |= MPT_TARGET_NO_NEGO_WIDE; | ||
5221 | |||
5222 | if (!offset) | ||
5223 | negoFlags |= MPT_TARGET_NO_NEGO_SYNC; | ||
5224 | } | ||
5225 | |||
5226 | /* limit by adapter capabilities */ | ||
5227 | width = min(width, hd->ioc->spi_data.maxBusWidth); | ||
5228 | offset = min(offset, hd->ioc->spi_data.maxSyncOffset); | ||
5229 | factor = max(factor, hd->ioc->spi_data.minSyncFactor); | ||
5230 | |||
5231 | /* Check Consistency */ | ||
5232 | if (offset && (factor < MPT_ULTRA2) && !width) | ||
5233 | factor = MPT_ULTRA2; | ||
5234 | |||
5235 | dv->max.width = width; | ||
5236 | dv->max.offset = offset; | ||
5237 | dv->max.factor = factor; | ||
5238 | dv->max.flags = negoFlags; | ||
5239 | ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n", | ||
5240 | id, width, factor, offset, negoFlags)); | ||
5241 | break; | ||
5242 | |||
5243 | case MPT_UPDATE_MAX: | ||
5244 | ddvprintk((MYIOC_s_NOTE_FMT | ||
5245 | "Updating with SDP0 Data: ", hd->ioc->name)); | ||
5246 | /* Update tmax values with those from Device Page 0.*/ | ||
5247 | pPage0 = (SCSIDevicePage0_t *) pPage; | ||
5248 | if (pPage0) { | ||
5249 | val = le32_to_cpu(pPage0->NegotiatedParameters); | ||
5250 | dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0; | ||
5251 | dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16; | ||
5252 | dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8; | ||
5253 | } | ||
5254 | |||
5255 | dv->now.width = dv->max.width; | ||
5256 | dv->now.offset = dv->max.offset; | ||
5257 | dv->now.factor = dv->max.factor; | ||
5258 | ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n", | ||
5259 | id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); | ||
5260 | break; | ||
5261 | |||
5262 | case MPT_SET_MAX: | ||
5263 | ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ", | ||
5264 | hd->ioc->name)); | ||
5265 | /* Set current to the max values. Update the config page.*/ | ||
5266 | dv->now.width = dv->max.width; | ||
5267 | dv->now.offset = dv->max.offset; | ||
5268 | dv->now.factor = dv->max.factor; | ||
5269 | dv->now.flags = dv->max.flags; | ||
5270 | |||
5271 | pPage1 = (SCSIDevicePage1_t *)pPage; | ||
5272 | if (pPage1) { | ||
5273 | mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor, | ||
5274 | dv->now.offset, &val, &configuration, dv->now.flags); | ||
5275 | dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", | ||
5276 | id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); | ||
5277 | pPage1->RequestedParameters = cpu_to_le32(val); | ||
5278 | pPage1->Reserved = 0; | ||
5279 | pPage1->Configuration = cpu_to_le32(configuration); | ||
5280 | } | ||
5281 | |||
5282 | ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n", | ||
5283 | id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); | ||
5284 | break; | ||
5285 | |||
5286 | case MPT_SET_MIN: | ||
5287 | ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ", | ||
5288 | hd->ioc->name)); | ||
5289 | /* Set page to asynchronous and narrow | ||
5290 | * Do not update now, breaks fallback routine. */ | ||
5291 | width = MPT_NARROW; | ||
5292 | offset = 0; | ||
5293 | factor = MPT_ASYNC; | ||
5294 | negoFlags = dv->max.flags; | ||
5295 | |||
5296 | pPage1 = (SCSIDevicePage1_t *)pPage; | ||
5297 | if (pPage1) { | ||
5298 | mptscsih_setDevicePage1Flags (width, factor, | ||
5299 | offset, &val, &configuration, negoFlags); | ||
5300 | dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", | ||
5301 | id, width, factor, offset, negoFlags, val, configuration)); | ||
5302 | pPage1->RequestedParameters = cpu_to_le32(val); | ||
5303 | pPage1->Reserved = 0; | ||
5304 | pPage1->Configuration = cpu_to_le32(configuration); | ||
5305 | } | ||
5306 | ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n", | ||
5307 | id, width, factor, offset, val, configuration, negoFlags)); | ||
5308 | break; | ||
5309 | |||
5310 | case MPT_FALLBACK: | ||
5311 | ddvprintk((MYIOC_s_NOTE_FMT | ||
5312 | "Fallback: Start: offset %d, factor %x, width %d \n", | ||
5313 | hd->ioc->name, dv->now.offset, | ||
5314 | dv->now.factor, dv->now.width)); | ||
5315 | width = dv->now.width; | ||
5316 | offset = dv->now.offset; | ||
5317 | factor = dv->now.factor; | ||
5318 | if ((offset) && (dv->max.width)) { | ||
5319 | if (factor < MPT_ULTRA160) | ||
5320 | factor = MPT_ULTRA160; | ||
5321 | else if (factor < MPT_ULTRA2) { | ||
5322 | factor = MPT_ULTRA2; | ||
5323 | width = MPT_WIDE; | ||
5324 | } else if ((factor == MPT_ULTRA2) && width) { | ||
5325 | factor = MPT_ULTRA2; | ||
5326 | width = MPT_NARROW; | ||
5327 | } else if (factor < MPT_ULTRA) { | ||
5328 | factor = MPT_ULTRA; | ||
5329 | width = MPT_WIDE; | ||
5330 | } else if ((factor == MPT_ULTRA) && width) { | ||
5331 | width = MPT_NARROW; | ||
5332 | } else if (factor < MPT_FAST) { | ||
5333 | factor = MPT_FAST; | ||
5334 | width = MPT_WIDE; | ||
5335 | } else if ((factor == MPT_FAST) && width) { | ||
5336 | factor = MPT_FAST; | ||
5337 | width = MPT_NARROW; | ||
5338 | } else if (factor < MPT_SCSI) { | ||
5339 | factor = MPT_SCSI; | ||
5340 | width = MPT_WIDE; | ||
5341 | } else if ((factor == MPT_SCSI) && width) { | ||
5342 | factor = MPT_SCSI; | ||
5343 | width = MPT_NARROW; | ||
5344 | } else { | ||
5345 | factor = MPT_ASYNC; | ||
5346 | offset = 0; | ||
5347 | } | ||
5348 | |||
5349 | } else if (offset) { | ||
5350 | width = MPT_NARROW; | ||
5351 | if (factor < MPT_ULTRA) | ||
5352 | factor = MPT_ULTRA; | ||
5353 | else if (factor < MPT_FAST) | ||
5354 | factor = MPT_FAST; | ||
5355 | else if (factor < MPT_SCSI) | ||
5356 | factor = MPT_SCSI; | ||
5357 | else { | ||
5358 | factor = MPT_ASYNC; | ||
5359 | offset = 0; | ||
5360 | } | ||
5361 | |||
5362 | } else { | ||
5363 | width = MPT_NARROW; | ||
5364 | factor = MPT_ASYNC; | ||
5365 | } | ||
5366 | dv->max.flags |= MPT_TARGET_NO_NEGO_QAS; | ||
5367 | dv->max.flags &= ~MPT_TAPE_NEGO_IDP; | ||
5368 | |||
5369 | dv->now.width = width; | ||
5370 | dv->now.offset = offset; | ||
5371 | dv->now.factor = factor; | ||
5372 | dv->now.flags = dv->max.flags; | ||
5373 | |||
5374 | pPage1 = (SCSIDevicePage1_t *)pPage; | ||
5375 | if (pPage1) { | ||
5376 | mptscsih_setDevicePage1Flags (width, factor, offset, &val, | ||
5377 | &configuration, dv->now.flags); | ||
5378 | dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n", | ||
5379 | id, width, offset, factor, dv->now.flags, val, configuration)); | ||
5380 | |||
5381 | pPage1->RequestedParameters = cpu_to_le32(val); | ||
5382 | pPage1->Reserved = 0; | ||
5383 | pPage1->Configuration = cpu_to_le32(configuration); | ||
5384 | } | ||
5385 | |||
5386 | ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n", | ||
5387 | id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration)); | ||
5388 | break; | ||
5389 | |||
5390 | case MPT_SAVE: | ||
5391 | ddvprintk((MYIOC_s_NOTE_FMT | ||
5392 | "Saving to Target structure: ", hd->ioc->name)); | ||
5393 | ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n", | ||
5394 | id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); | ||
5395 | |||
5396 | /* Save these values to target structures | ||
5397 | * or overwrite nvram (phys disks only). | ||
5398 | */ | ||
5399 | |||
5400 | if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) { | ||
5401 | vtarget->maxWidth = dv->now.width; | ||
5402 | vtarget->maxOffset = dv->now.offset; | ||
5403 | vtarget->minSyncFactor = dv->now.factor; | ||
5404 | vtarget->negoFlags = dv->now.flags; | ||
5405 | } else { | ||
5406 | /* Preserv all flags, use | ||
5407 | * read-modify-write algorithm | ||
5408 | */ | ||
5409 | if (hd->ioc->spi_data.nvram) { | ||
5410 | data = hd->ioc->spi_data.nvram[id]; | ||
5411 | |||
5412 | if (dv->now.width) | ||
5413 | data &= ~MPT_NVRAM_WIDE_DISABLE; | ||
5414 | else | ||
5415 | data |= MPT_NVRAM_WIDE_DISABLE; | ||
5416 | |||
5417 | if (!dv->now.offset) | ||
5418 | factor = MPT_ASYNC; | ||
5419 | |||
5420 | data &= ~MPT_NVRAM_SYNC_MASK; | ||
5421 | data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK; | ||
5422 | |||
5423 | hd->ioc->spi_data.nvram[id] = data; | ||
5424 | } | ||
5425 | } | ||
5426 | break; | ||
5427 | } | ||
5428 | } | ||
5429 | |||
5430 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
5431 | /* mptscsih_fillbuf - fill a buffer with a special data pattern | ||
5432 | * cleanup. For bus scan only. | ||
5433 | * | ||
5434 | * @buffer: Pointer to data buffer to be filled. | ||
5435 | * @size: Number of bytes to fill | ||
5436 | * @index: Pattern index | ||
5437 | * @width: bus width, 0 (8 bits) or 1 (16 bits) | ||
5438 | */ | ||
5439 | static void | ||
5440 | mptscsih_fillbuf(char *buffer, int size, int index, int width) | ||
5441 | { | ||
5442 | char *ptr = buffer; | ||
5443 | int ii; | ||
5444 | char byte; | ||
5445 | short val; | ||
5446 | |||
5447 | switch (index) { | ||
5448 | case 0: | ||
5449 | |||
5450 | if (width) { | ||
5451 | /* Pattern: 0000 FFFF 0000 FFFF | ||
5452 | */ | ||
5453 | for (ii=0; ii < size; ii++, ptr++) { | ||
5454 | if (ii & 0x02) | ||
5455 | *ptr = 0xFF; | ||
5456 | else | ||
5457 | *ptr = 0x00; | ||
5458 | } | ||
5459 | } else { | ||
5460 | /* Pattern: 00 FF 00 FF | ||
5461 | */ | ||
5462 | for (ii=0; ii < size; ii++, ptr++) { | ||
5463 | if (ii & 0x01) | ||
5464 | *ptr = 0xFF; | ||
5465 | else | ||
5466 | *ptr = 0x00; | ||
5467 | } | ||
5468 | } | ||
5469 | break; | ||
5470 | |||
5471 | case 1: | ||
5472 | if (width) { | ||
5473 | /* Pattern: 5555 AAAA 5555 AAAA 5555 | ||
5474 | */ | ||
5475 | for (ii=0; ii < size; ii++, ptr++) { | ||
5476 | if (ii & 0x02) | ||
5477 | *ptr = 0xAA; | ||
5478 | else | ||
5479 | *ptr = 0x55; | ||
5480 | } | ||
5481 | } else { | ||
5482 | /* Pattern: 55 AA 55 AA 55 | ||
5483 | */ | ||
5484 | for (ii=0; ii < size; ii++, ptr++) { | ||
5485 | if (ii & 0x01) | ||
5486 | *ptr = 0xAA; | ||
5487 | else | ||
5488 | *ptr = 0x55; | ||
5489 | } | ||
5490 | } | ||
5491 | break; | ||
5492 | |||
5493 | case 2: | ||
5494 | /* Pattern: 00 01 02 03 04 05 | ||
5495 | * ... FE FF 00 01.. | ||
5496 | */ | ||
5497 | for (ii=0; ii < size; ii++, ptr++) | ||
5498 | *ptr = (char) ii; | ||
5499 | break; | ||
5500 | |||
5501 | case 3: | ||
5502 | if (width) { | ||
5503 | /* Wide Pattern: FFFE 0001 FFFD 0002 | ||
5504 | * ... 4000 DFFF 8000 EFFF | ||
5505 | */ | ||
5506 | byte = 0; | ||
5507 | for (ii=0; ii < size/2; ii++) { | ||
5508 | /* Create the base pattern | ||
5509 | */ | ||
5510 | val = (1 << byte); | ||
5511 | /* every 64 (0x40) bytes flip the pattern | ||
5512 | * since we fill 2 bytes / iteration, | ||
5513 | * test for ii = 0x20 | ||
5514 | */ | ||
5515 | if (ii & 0x20) | ||
5516 | val = ~(val); | ||
5517 | |||
5518 | if (ii & 0x01) { | ||
5519 | *ptr = (char)( (val & 0xFF00) >> 8); | ||
5520 | ptr++; | ||
5521 | *ptr = (char)(val & 0xFF); | ||
5522 | byte++; | ||
5523 | byte &= 0x0F; | ||
5524 | } else { | ||
5525 | val = ~val; | ||
5526 | *ptr = (char)( (val & 0xFF00) >> 8); | ||
5527 | ptr++; | ||
5528 | *ptr = (char)(val & 0xFF); | ||
5529 | } | ||
5530 | |||
5531 | ptr++; | ||
5532 | } | ||
5533 | } else { | ||
5534 | /* Narrow Pattern: FE 01 FD 02 FB 04 | ||
5535 | * .. 7F 80 01 FE 02 FD ... 80 7F | ||
5536 | */ | ||
5537 | byte = 0; | ||
5538 | for (ii=0; ii < size; ii++, ptr++) { | ||
5539 | /* Base pattern - first 32 bytes | ||
5540 | */ | ||
5541 | if (ii & 0x01) { | ||
5542 | *ptr = (1 << byte); | ||
5543 | byte++; | ||
5544 | byte &= 0x07; | ||
5545 | } else { | ||
5546 | *ptr = (char) (~(1 << byte)); | ||
5547 | } | ||
5548 | |||
5549 | /* Flip the pattern every 32 bytes | ||
5550 | */ | ||
5551 | if (ii & 0x20) | ||
5552 | *ptr = ~(*ptr); | ||
5553 | } | ||
5554 | } | ||
5555 | break; | ||
5556 | } | ||
5557 | } | ||
5558 | |||
5559 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
5560 | /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return. | ||
5561 | * Else set the NEED_DV flag after Read Capacity Issued (disks) | ||
5562 | * or Mode Sense (cdroms). | ||
5563 | * | ||
5564 | * Tapes, initTarget will set this flag on completion of Inquiry command. | ||
5565 | * Called only if DV_NOT_DONE flag is set | ||
5566 | */ | ||
5567 | static void | ||
5568 | mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc) | ||
5569 | { | ||
5570 | MPT_ADAPTER *ioc = hd->ioc; | ||
5571 | u8 cmd; | ||
5572 | SpiCfgData *pSpi; | ||
5573 | |||
5574 | ddvtprintk((MYIOC_s_NOTE_FMT | ||
5575 | " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", | ||
5576 | hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0])); | ||
5577 | |||
5578 | if ((sc->device->lun != 0) || (hd->negoNvram != 0)) | ||
5579 | return; | ||
5580 | |||
5581 | cmd = sc->cmnd[0]; | ||
5582 | |||
5583 | if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { | ||
5584 | pSpi = &ioc->spi_data; | ||
5585 | if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) { | ||
5586 | /* Set NEED_DV for all hidden disks | ||
5587 | */ | ||
5588 | Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; | ||
5589 | int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; | ||
5590 | |||
5591 | while (numPDisk) { | ||
5592 | pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; | ||
5593 | ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); | ||
5594 | pPDisk++; | ||
5595 | numPDisk--; | ||
5596 | } | ||
5597 | } | ||
5598 | pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV; | ||
5599 | ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id)); | ||
5600 | } | ||
5601 | } | ||
5602 | |||
5603 | /* mptscsih_raid_set_dv_flags() | ||
5604 | * | ||
5605 | * New or replaced disk. Set DV flag and schedule DV. | ||
5606 | */ | ||
5607 | static void | ||
5608 | mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id) | ||
5609 | { | ||
5610 | MPT_ADAPTER *ioc = hd->ioc; | ||
5611 | SpiCfgData *pSpi = &ioc->spi_data; | ||
5612 | Ioc3PhysDisk_t *pPDisk; | ||
5613 | int numPDisk; | ||
5614 | |||
5615 | if (hd->negoNvram != 0) | ||
5616 | return; | ||
5617 | |||
5618 | ddvtprintk(("DV requested for phys disk id %d\n", id)); | ||
5619 | if (ioc->raid_data.pIocPg3) { | ||
5620 | pPDisk = ioc->raid_data.pIocPg3->PhysDisk; | ||
5621 | numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; | ||
5622 | while (numPDisk) { | ||
5623 | if (id == pPDisk->PhysDiskNum) { | ||
5624 | pSpi->dvStatus[pPDisk->PhysDiskID] = | ||
5625 | (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); | ||
5626 | pSpi->forceDv = MPT_SCSICFG_NEED_DV; | ||
5627 | ddvtprintk(("NEED_DV set for phys disk id %d\n", | ||
5628 | pPDisk->PhysDiskID)); | ||
5629 | break; | ||
5630 | } | ||
5631 | pPDisk++; | ||
5632 | numPDisk--; | ||
5633 | } | ||
5634 | |||
5635 | if (numPDisk == 0) { | ||
5636 | /* The physical disk that needs DV was not found | ||
5637 | * in the stored IOC Page 3. The driver must reload | ||
5638 | * this page. DV routine will set the NEED_DV flag for | ||
5639 | * all phys disks that have DV_NOT_DONE set. | ||
5640 | */ | ||
5641 | pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; | ||
5642 | ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id)); | ||
5643 | } | ||
5644 | } | ||
5645 | } | ||
5646 | #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */ | ||
5647 | |||
5648 | EXPORT_SYMBOL(mptscsih_remove); | 3422 | EXPORT_SYMBOL(mptscsih_remove); |
5649 | EXPORT_SYMBOL(mptscsih_shutdown); | 3423 | EXPORT_SYMBOL(mptscsih_shutdown); |
5650 | #ifdef CONFIG_PM | 3424 | #ifdef CONFIG_PM |
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 44b248d51ea3..2447a203513f 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h | |||
@@ -60,16 +60,6 @@ | |||
60 | 60 | ||
61 | #define MPT_SCSI_MAX_SECTORS 8192 | 61 | #define MPT_SCSI_MAX_SECTORS 8192 |
62 | 62 | ||
63 | /* To disable domain validation, uncomment the | ||
64 | * following line. No effect for FC devices. | ||
65 | * For SCSI devices, driver will negotiate to | ||
66 | * NVRAM settings (if available) or to maximum adapter | ||
67 | * capabilities. | ||
68 | */ | ||
69 | |||
70 | #define MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
71 | |||
72 | |||
73 | /* SCSI driver setup structure. Settings can be overridden | 63 | /* SCSI driver setup structure. Settings can be overridden |
74 | * by command line options. | 64 | * by command line options. |
75 | */ | 65 | */ |
@@ -109,3 +99,4 @@ extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | |||
109 | extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); | 99 | extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); |
110 | extern void mptscsih_timer_expired(unsigned long data); | 100 | 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); | 101 | extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); |
102 | extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); | ||
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index f148dfa39117..437189f871b0 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c | |||
@@ -56,12 +56,15 @@ | |||
56 | #include <linux/reboot.h> /* notifier code */ | 56 | #include <linux/reboot.h> /* notifier code */ |
57 | #include <linux/sched.h> | 57 | #include <linux/sched.h> |
58 | #include <linux/workqueue.h> | 58 | #include <linux/workqueue.h> |
59 | #include <linux/raid_class.h> | ||
59 | 60 | ||
60 | #include <scsi/scsi.h> | 61 | #include <scsi/scsi.h> |
61 | #include <scsi/scsi_cmnd.h> | 62 | #include <scsi/scsi_cmnd.h> |
62 | #include <scsi/scsi_device.h> | 63 | #include <scsi/scsi_device.h> |
63 | #include <scsi/scsi_host.h> | 64 | #include <scsi/scsi_host.h> |
64 | #include <scsi/scsi_tcq.h> | 65 | #include <scsi/scsi_tcq.h> |
66 | #include <scsi/scsi_transport.h> | ||
67 | #include <scsi/scsi_transport_spi.h> | ||
65 | 68 | ||
66 | #include "mptbase.h" | 69 | #include "mptbase.h" |
67 | #include "mptscsih.h" | 70 | #include "mptscsih.h" |
@@ -76,20 +79,6 @@ MODULE_DESCRIPTION(my_NAME); | |||
76 | MODULE_LICENSE("GPL"); | 79 | MODULE_LICENSE("GPL"); |
77 | 80 | ||
78 | /* Command line args */ | 81 | /* Command line args */ |
79 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
80 | static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION; | ||
81 | module_param(mpt_dv, int, 0); | ||
82 | MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)"); | ||
83 | |||
84 | static int mpt_width = MPTSCSIH_MAX_WIDTH; | ||
85 | module_param(mpt_width, int, 0); | ||
86 | MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)"); | ||
87 | |||
88 | static ushort mpt_factor = MPTSCSIH_MIN_SYNC; | ||
89 | module_param(mpt_factor, ushort, 0); | ||
90 | MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)"); | ||
91 | #endif | ||
92 | |||
93 | static int mpt_saf_te = MPTSCSIH_SAF_TE; | 82 | static int mpt_saf_te = MPTSCSIH_SAF_TE; |
94 | module_param(mpt_saf_te, int, 0); | 83 | module_param(mpt_saf_te, int, 0); |
95 | MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); | 84 | MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); |
@@ -98,10 +87,308 @@ static int mpt_pq_filter = 0; | |||
98 | module_param(mpt_pq_filter, int, 0); | 87 | module_param(mpt_pq_filter, int, 0); |
99 | MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); | 88 | MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); |
100 | 89 | ||
90 | static void mptspi_write_offset(struct scsi_target *, int); | ||
91 | static void mptspi_write_width(struct scsi_target *, int); | ||
92 | static int mptspi_write_spi_device_pg1(struct scsi_target *, | ||
93 | struct _CONFIG_PAGE_SCSI_DEVICE_1 *); | ||
94 | |||
95 | static struct scsi_transport_template *mptspi_transport_template = NULL; | ||
96 | |||
101 | static int mptspiDoneCtx = -1; | 97 | static int mptspiDoneCtx = -1; |
102 | static int mptspiTaskCtx = -1; | 98 | static int mptspiTaskCtx = -1; |
103 | static int mptspiInternalCtx = -1; /* Used only for internal commands */ | 99 | static int mptspiInternalCtx = -1; /* Used only for internal commands */ |
104 | 100 | ||
101 | static int mptspi_target_alloc(struct scsi_target *starget) | ||
102 | { | ||
103 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
104 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
105 | int ret; | ||
106 | |||
107 | if (hd == NULL) | ||
108 | return -ENODEV; | ||
109 | |||
110 | ret = mptscsih_target_alloc(starget); | ||
111 | if (ret) | ||
112 | return ret; | ||
113 | |||
114 | /* if we're a device on virtual channel 1 and we're not part | ||
115 | * of an array, just return here (otherwise the setup below | ||
116 | * may actually affect a real physical device on channel 0 */ | ||
117 | if (starget->channel == 1 && | ||
118 | mptscsih_raid_id_to_num(hd, starget->id) < 0) | ||
119 | return 0; | ||
120 | |||
121 | if (hd->ioc->spi_data.nvram && | ||
122 | hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { | ||
123 | u32 nvram = hd->ioc->spi_data.nvram[starget->id]; | ||
124 | spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; | ||
125 | spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; | ||
126 | } else { | ||
127 | spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor; | ||
128 | spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth; | ||
129 | } | ||
130 | spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset; | ||
131 | |||
132 | spi_offset(starget) = 0; | ||
133 | mptspi_write_width(starget, 0); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int mptspi_read_spi_device_pg0(struct scsi_target *starget, | ||
139 | struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) | ||
140 | { | ||
141 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
142 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
143 | struct _MPT_ADAPTER *ioc = hd->ioc; | ||
144 | struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0; | ||
145 | dma_addr_t pg0_dma; | ||
146 | int size; | ||
147 | struct _x_config_parms cfg; | ||
148 | struct _CONFIG_PAGE_HEADER hdr; | ||
149 | int err = -EBUSY; | ||
150 | |||
151 | /* No SPI parameters for RAID devices */ | ||
152 | if (starget->channel == 0 && | ||
153 | (hd->ioc->raid_data.isRaid & (1 << starget->id))) | ||
154 | return -1; | ||
155 | |||
156 | size = ioc->spi_data.sdp0length * 4; | ||
157 | /* | ||
158 | if (ioc->spi_data.sdp0length & 1) | ||
159 | size += size + 4; | ||
160 | size += 2048; | ||
161 | */ | ||
162 | |||
163 | pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL); | ||
164 | if (pg0 == NULL) { | ||
165 | starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | |||
169 | memset(&hdr, 0, sizeof(hdr)); | ||
170 | |||
171 | hdr.PageVersion = ioc->spi_data.sdp0version; | ||
172 | hdr.PageLength = ioc->spi_data.sdp0length; | ||
173 | hdr.PageNumber = 0; | ||
174 | hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
175 | |||
176 | memset(&cfg, 0, sizeof(cfg)); | ||
177 | |||
178 | cfg.cfghdr.hdr = &hdr; | ||
179 | cfg.physAddr = pg0_dma; | ||
180 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
181 | cfg.dir = 0; | ||
182 | cfg.pageAddr = starget->id; | ||
183 | |||
184 | if (mpt_config(ioc, &cfg)) { | ||
185 | starget_printk(KERN_ERR, starget, "mpt_config failed\n"); | ||
186 | goto out_free; | ||
187 | } | ||
188 | err = 0; | ||
189 | memcpy(pass_pg0, pg0, size); | ||
190 | |||
191 | out_free: | ||
192 | dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma); | ||
193 | return err; | ||
194 | } | ||
195 | |||
196 | static u32 mptspi_getRP(struct scsi_target *starget) | ||
197 | { | ||
198 | u32 nego = 0; | ||
199 | |||
200 | nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0; | ||
201 | nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0; | ||
202 | nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0; | ||
203 | nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0; | ||
204 | nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0; | ||
205 | nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0; | ||
206 | nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0; | ||
207 | nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0; | ||
208 | |||
209 | nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK; | ||
210 | nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK; | ||
211 | nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; | ||
212 | |||
213 | return nego; | ||
214 | } | ||
215 | |||
216 | static void mptspi_read_parameters(struct scsi_target *starget) | ||
217 | { | ||
218 | int nego; | ||
219 | struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0; | ||
220 | |||
221 | mptspi_read_spi_device_pg0(starget, &pg0); | ||
222 | |||
223 | nego = le32_to_cpu(pg0.NegotiatedParameters); | ||
224 | |||
225 | spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0; | ||
226 | spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0; | ||
227 | spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0; | ||
228 | spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0; | ||
229 | spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0; | ||
230 | spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0; | ||
231 | spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0; | ||
232 | spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0; | ||
233 | spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD; | ||
234 | spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET; | ||
235 | spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0; | ||
236 | } | ||
237 | |||
238 | static int | ||
239 | mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) | ||
240 | { | ||
241 | MpiRaidActionRequest_t *pReq; | ||
242 | MPT_FRAME_HDR *mf; | ||
243 | |||
244 | /* Get and Populate a free Frame | ||
245 | */ | ||
246 | if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { | ||
247 | ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", | ||
248 | hd->ioc->name)); | ||
249 | return -EAGAIN; | ||
250 | } | ||
251 | pReq = (MpiRaidActionRequest_t *)mf; | ||
252 | if (quiesce) | ||
253 | pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO; | ||
254 | else | ||
255 | pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO; | ||
256 | pReq->Reserved1 = 0; | ||
257 | pReq->ChainOffset = 0; | ||
258 | pReq->Function = MPI_FUNCTION_RAID_ACTION; | ||
259 | pReq->VolumeID = disk; | ||
260 | pReq->VolumeBus = 0; | ||
261 | pReq->PhysDiskNum = 0; | ||
262 | pReq->MsgFlags = 0; | ||
263 | pReq->Reserved2 = 0; | ||
264 | pReq->ActionDataWord = 0; /* Reserved for this action */ | ||
265 | |||
266 | mpt_add_sge((char *)&pReq->ActionDataSGE, | ||
267 | MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); | ||
268 | |||
269 | ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", | ||
270 | hd->ioc->name, action, io->id)); | ||
271 | |||
272 | hd->pLocal = NULL; | ||
273 | hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ | ||
274 | hd->scandv_wait_done = 0; | ||
275 | |||
276 | /* Save cmd pointer, for resource free if timeout or | ||
277 | * FW reload occurs | ||
278 | */ | ||
279 | hd->cmdPtr = mf; | ||
280 | |||
281 | add_timer(&hd->timer); | ||
282 | mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); | ||
283 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | ||
284 | |||
285 | if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0)) | ||
286 | return -1; | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, | ||
292 | struct scsi_device *sdev) | ||
293 | { | ||
294 | VirtTarget *vtarget = scsi_target(sdev)->hostdata; | ||
295 | |||
296 | /* no DV on RAID devices */ | ||
297 | if (sdev->channel == 0 && | ||
298 | (hd->ioc->raid_data.isRaid & (1 << sdev->id))) | ||
299 | return; | ||
300 | |||
301 | /* If this is a piece of a RAID, then quiesce first */ | ||
302 | if (sdev->channel == 1 && | ||
303 | mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) { | ||
304 | starget_printk(KERN_ERR, scsi_target(sdev), | ||
305 | "Integrated RAID quiesce failed\n"); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | spi_dv_device(sdev); | ||
310 | |||
311 | if (sdev->channel == 1 && | ||
312 | mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0) | ||
313 | starget_printk(KERN_ERR, scsi_target(sdev), | ||
314 | "Integrated RAID resume failed\n"); | ||
315 | |||
316 | mptspi_read_parameters(sdev->sdev_target); | ||
317 | spi_display_xfer_agreement(sdev->sdev_target); | ||
318 | mptspi_read_parameters(sdev->sdev_target); | ||
319 | } | ||
320 | |||
321 | static int mptspi_slave_alloc(struct scsi_device *sdev) | ||
322 | { | ||
323 | int ret; | ||
324 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; | ||
325 | /* gcc doesn't see that all uses of this variable occur within | ||
326 | * the if() statements, so stop it from whining */ | ||
327 | int physdisknum = 0; | ||
328 | |||
329 | if (sdev->channel == 1) { | ||
330 | physdisknum = mptscsih_raid_id_to_num(hd, sdev->id); | ||
331 | |||
332 | if (physdisknum < 0) | ||
333 | return physdisknum; | ||
334 | } | ||
335 | |||
336 | ret = mptscsih_slave_alloc(sdev); | ||
337 | |||
338 | if (ret) | ||
339 | return ret; | ||
340 | |||
341 | if (sdev->channel == 1) { | ||
342 | VirtDevice *vdev = sdev->hostdata; | ||
343 | sdev->no_uld_attach = 1; | ||
344 | vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
345 | /* The real channel for this device is zero */ | ||
346 | vdev->bus_id = 0; | ||
347 | /* The actual physdisknum (for RAID passthrough) */ | ||
348 | vdev->target_id = physdisknum; | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int mptspi_slave_configure(struct scsi_device *sdev) | ||
355 | { | ||
356 | int ret = mptscsih_slave_configure(sdev); | ||
357 | struct _MPT_SCSI_HOST *hd = | ||
358 | (struct _MPT_SCSI_HOST *)sdev->host->hostdata; | ||
359 | |||
360 | if (ret) | ||
361 | return ret; | ||
362 | |||
363 | if ((sdev->channel == 1 || | ||
364 | !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) && | ||
365 | !spi_initial_dv(sdev->sdev_target)) | ||
366 | mptspi_dv_device(hd, sdev); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static void mptspi_slave_destroy(struct scsi_device *sdev) | ||
372 | { | ||
373 | struct scsi_target *starget = scsi_target(sdev); | ||
374 | VirtTarget *vtarget = starget->hostdata; | ||
375 | VirtDevice *vdevice = sdev->hostdata; | ||
376 | |||
377 | /* Will this be the last lun on a non-raid device? */ | ||
378 | if (vtarget->num_luns == 1 && vdevice->configured_lun) { | ||
379 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
380 | |||
381 | /* Async Narrow */ | ||
382 | pg1.RequestedParameters = 0; | ||
383 | pg1.Reserved = 0; | ||
384 | pg1.Configuration = 0; | ||
385 | |||
386 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
387 | } | ||
388 | |||
389 | mptscsih_slave_destroy(sdev); | ||
390 | } | ||
391 | |||
105 | static struct scsi_host_template mptspi_driver_template = { | 392 | static struct scsi_host_template mptspi_driver_template = { |
106 | .module = THIS_MODULE, | 393 | .module = THIS_MODULE, |
107 | .proc_name = "mptspi", | 394 | .proc_name = "mptspi", |
@@ -109,11 +396,11 @@ static struct scsi_host_template mptspi_driver_template = { | |||
109 | .name = "MPT SPI Host", | 396 | .name = "MPT SPI Host", |
110 | .info = mptscsih_info, | 397 | .info = mptscsih_info, |
111 | .queuecommand = mptscsih_qcmd, | 398 | .queuecommand = mptscsih_qcmd, |
112 | .target_alloc = mptscsih_target_alloc, | 399 | .target_alloc = mptspi_target_alloc, |
113 | .slave_alloc = mptscsih_slave_alloc, | 400 | .slave_alloc = mptspi_slave_alloc, |
114 | .slave_configure = mptscsih_slave_configure, | 401 | .slave_configure = mptspi_slave_configure, |
115 | .target_destroy = mptscsih_target_destroy, | 402 | .target_destroy = mptscsih_target_destroy, |
116 | .slave_destroy = mptscsih_slave_destroy, | 403 | .slave_destroy = mptspi_slave_destroy, |
117 | .change_queue_depth = mptscsih_change_queue_depth, | 404 | .change_queue_depth = mptscsih_change_queue_depth, |
118 | .eh_abort_handler = mptscsih_abort, | 405 | .eh_abort_handler = mptscsih_abort, |
119 | .eh_device_reset_handler = mptscsih_dev_reset, | 406 | .eh_device_reset_handler = mptscsih_dev_reset, |
@@ -128,6 +415,360 @@ static struct scsi_host_template mptspi_driver_template = { | |||
128 | .use_clustering = ENABLE_CLUSTERING, | 415 | .use_clustering = ENABLE_CLUSTERING, |
129 | }; | 416 | }; |
130 | 417 | ||
418 | static int mptspi_write_spi_device_pg1(struct scsi_target *starget, | ||
419 | struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1) | ||
420 | { | ||
421 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
422 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
423 | struct _MPT_ADAPTER *ioc = hd->ioc; | ||
424 | struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1; | ||
425 | dma_addr_t pg1_dma; | ||
426 | int size; | ||
427 | struct _x_config_parms cfg; | ||
428 | struct _CONFIG_PAGE_HEADER hdr; | ||
429 | int err = -EBUSY; | ||
430 | |||
431 | /* don't allow updating nego parameters on RAID devices */ | ||
432 | if (starget->channel == 0 && | ||
433 | (hd->ioc->raid_data.isRaid & (1 << starget->id))) | ||
434 | return -1; | ||
435 | |||
436 | size = ioc->spi_data.sdp1length * 4; | ||
437 | |||
438 | pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL); | ||
439 | if (pg1 == NULL) { | ||
440 | starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | |||
444 | memset(&hdr, 0, sizeof(hdr)); | ||
445 | |||
446 | hdr.PageVersion = ioc->spi_data.sdp1version; | ||
447 | hdr.PageLength = ioc->spi_data.sdp1length; | ||
448 | hdr.PageNumber = 1; | ||
449 | hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
450 | |||
451 | memset(&cfg, 0, sizeof(cfg)); | ||
452 | |||
453 | cfg.cfghdr.hdr = &hdr; | ||
454 | cfg.physAddr = pg1_dma; | ||
455 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
456 | cfg.dir = 1; | ||
457 | cfg.pageAddr = starget->id; | ||
458 | |||
459 | memcpy(pg1, pass_pg1, size); | ||
460 | |||
461 | pg1->Header.PageVersion = hdr.PageVersion; | ||
462 | pg1->Header.PageLength = hdr.PageLength; | ||
463 | pg1->Header.PageNumber = hdr.PageNumber; | ||
464 | pg1->Header.PageType = hdr.PageType; | ||
465 | |||
466 | if (mpt_config(ioc, &cfg)) { | ||
467 | starget_printk(KERN_ERR, starget, "mpt_config failed\n"); | ||
468 | goto out_free; | ||
469 | } | ||
470 | err = 0; | ||
471 | |||
472 | out_free: | ||
473 | dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma); | ||
474 | return err; | ||
475 | } | ||
476 | |||
477 | static void mptspi_write_offset(struct scsi_target *starget, int offset) | ||
478 | { | ||
479 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
480 | u32 nego; | ||
481 | |||
482 | if (offset < 0) | ||
483 | offset = 0; | ||
484 | |||
485 | if (offset > 255) | ||
486 | offset = 255; | ||
487 | |||
488 | if (spi_offset(starget) == -1) | ||
489 | mptspi_read_parameters(starget); | ||
490 | |||
491 | spi_offset(starget) = offset; | ||
492 | |||
493 | nego = mptspi_getRP(starget); | ||
494 | |||
495 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
496 | pg1.Reserved = 0; | ||
497 | pg1.Configuration = 0; | ||
498 | |||
499 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
500 | } | ||
501 | |||
502 | static void mptspi_write_period(struct scsi_target *starget, int period) | ||
503 | { | ||
504 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
505 | u32 nego; | ||
506 | |||
507 | if (period < 8) | ||
508 | period = 8; | ||
509 | |||
510 | if (period > 255) | ||
511 | period = 255; | ||
512 | |||
513 | if (spi_period(starget) == -1) | ||
514 | mptspi_read_parameters(starget); | ||
515 | |||
516 | if (period == 8) { | ||
517 | spi_iu(starget) = 1; | ||
518 | spi_dt(starget) = 1; | ||
519 | } else if (period == 9) { | ||
520 | spi_dt(starget) = 1; | ||
521 | } | ||
522 | |||
523 | spi_period(starget) = period; | ||
524 | |||
525 | nego = mptspi_getRP(starget); | ||
526 | |||
527 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
528 | pg1.Reserved = 0; | ||
529 | pg1.Configuration = 0; | ||
530 | |||
531 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
532 | } | ||
533 | |||
534 | static void mptspi_write_dt(struct scsi_target *starget, int dt) | ||
535 | { | ||
536 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
537 | u32 nego; | ||
538 | |||
539 | if (spi_period(starget) == -1) | ||
540 | mptspi_read_parameters(starget); | ||
541 | |||
542 | if (!dt && spi_period(starget) < 10) | ||
543 | spi_period(starget) = 10; | ||
544 | |||
545 | spi_dt(starget) = dt; | ||
546 | |||
547 | nego = mptspi_getRP(starget); | ||
548 | |||
549 | |||
550 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
551 | pg1.Reserved = 0; | ||
552 | pg1.Configuration = 0; | ||
553 | |||
554 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
555 | } | ||
556 | |||
557 | static void mptspi_write_iu(struct scsi_target *starget, int iu) | ||
558 | { | ||
559 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
560 | u32 nego; | ||
561 | |||
562 | if (spi_period(starget) == -1) | ||
563 | mptspi_read_parameters(starget); | ||
564 | |||
565 | if (!iu && spi_period(starget) < 9) | ||
566 | spi_period(starget) = 9; | ||
567 | |||
568 | spi_iu(starget) = iu; | ||
569 | |||
570 | nego = mptspi_getRP(starget); | ||
571 | |||
572 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
573 | pg1.Reserved = 0; | ||
574 | pg1.Configuration = 0; | ||
575 | |||
576 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
577 | } | ||
578 | |||
579 | #define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) \ | ||
580 | static void mptspi_write_##parm(struct scsi_target *starget, int parm)\ | ||
581 | { \ | ||
582 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; \ | ||
583 | u32 nego; \ | ||
584 | \ | ||
585 | spi_##parm(starget) = parm; \ | ||
586 | \ | ||
587 | nego = mptspi_getRP(starget); \ | ||
588 | \ | ||
589 | pg1.RequestedParameters = cpu_to_le32(nego); \ | ||
590 | pg1.Reserved = 0; \ | ||
591 | pg1.Configuration = 0; \ | ||
592 | \ | ||
593 | mptspi_write_spi_device_pg1(starget, &pg1); \ | ||
594 | } | ||
595 | |||
596 | MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm) | ||
597 | MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow) | ||
598 | MPTSPI_SIMPLE_TRANSPORT_PARM(rti) | ||
599 | MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs) | ||
600 | MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en) | ||
601 | |||
602 | static void mptspi_write_qas(struct scsi_target *starget, int qas) | ||
603 | { | ||
604 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
605 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
606 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
607 | VirtTarget *vtarget = starget->hostdata; | ||
608 | u32 nego; | ||
609 | |||
610 | if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) || | ||
611 | hd->ioc->spi_data.noQas) | ||
612 | spi_qas(starget) = 0; | ||
613 | else | ||
614 | spi_qas(starget) = qas; | ||
615 | |||
616 | nego = mptspi_getRP(starget); | ||
617 | |||
618 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
619 | pg1.Reserved = 0; | ||
620 | pg1.Configuration = 0; | ||
621 | |||
622 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
623 | } | ||
624 | |||
625 | static void mptspi_write_width(struct scsi_target *starget, int width) | ||
626 | { | ||
627 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
628 | u32 nego; | ||
629 | |||
630 | if (!width) { | ||
631 | spi_dt(starget) = 0; | ||
632 | if (spi_period(starget) < 10) | ||
633 | spi_period(starget) = 10; | ||
634 | } | ||
635 | |||
636 | spi_width(starget) = width; | ||
637 | |||
638 | nego = mptspi_getRP(starget); | ||
639 | |||
640 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
641 | pg1.Reserved = 0; | ||
642 | pg1.Configuration = 0; | ||
643 | |||
644 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
645 | } | ||
646 | |||
647 | struct work_queue_wrapper { | ||
648 | struct work_struct work; | ||
649 | struct _MPT_SCSI_HOST *hd; | ||
650 | int disk; | ||
651 | }; | ||
652 | |||
653 | static void mpt_work_wrapper(void *data) | ||
654 | { | ||
655 | struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; | ||
656 | struct _MPT_SCSI_HOST *hd = wqw->hd; | ||
657 | struct Scsi_Host *shost = hd->ioc->sh; | ||
658 | struct scsi_device *sdev; | ||
659 | int disk = wqw->disk; | ||
660 | struct _CONFIG_PAGE_IOC_3 *pg3; | ||
661 | |||
662 | kfree(wqw); | ||
663 | |||
664 | mpt_findImVolumes(hd->ioc); | ||
665 | pg3 = hd->ioc->raid_data.pIocPg3; | ||
666 | if (!pg3) | ||
667 | return; | ||
668 | |||
669 | shost_for_each_device(sdev,shost) { | ||
670 | struct scsi_target *starget = scsi_target(sdev); | ||
671 | VirtTarget *vtarget = starget->hostdata; | ||
672 | |||
673 | /* only want to search RAID components */ | ||
674 | if (sdev->channel != 1) | ||
675 | continue; | ||
676 | |||
677 | /* The target_id is the raid PhysDiskNum, even if | ||
678 | * starget->id is the actual target address */ | ||
679 | if(vtarget->target_id != disk) | ||
680 | continue; | ||
681 | |||
682 | starget_printk(KERN_INFO, vtarget->starget, | ||
683 | "Integrated RAID requests DV of new device\n"); | ||
684 | mptspi_dv_device(hd, sdev); | ||
685 | } | ||
686 | shost_printk(KERN_INFO, shost, | ||
687 | "Integrated RAID detects new device %d\n", disk); | ||
688 | scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1); | ||
689 | } | ||
690 | |||
691 | |||
692 | static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk) | ||
693 | { | ||
694 | struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC); | ||
695 | |||
696 | if (!wqw) { | ||
697 | shost_printk(KERN_ERR, hd->ioc->sh, | ||
698 | "Failed to act on RAID event for physical disk %d\n", | ||
699 | disk); | ||
700 | return; | ||
701 | } | ||
702 | INIT_WORK(&wqw->work, mpt_work_wrapper, wqw); | ||
703 | wqw->hd = hd; | ||
704 | wqw->disk = disk; | ||
705 | |||
706 | schedule_work(&wqw->work); | ||
707 | } | ||
708 | |||
709 | static int | ||
710 | mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | ||
711 | { | ||
712 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; | ||
713 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; | ||
714 | |||
715 | if (hd && event == MPI_EVENT_INTEGRATED_RAID) { | ||
716 | int reason | ||
717 | = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; | ||
718 | |||
719 | if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { | ||
720 | int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24; | ||
721 | mpt_dv_raid(hd, disk); | ||
722 | } | ||
723 | } | ||
724 | return mptscsih_event_process(ioc, pEvReply); | ||
725 | } | ||
726 | |||
727 | static int | ||
728 | mptspi_deny_binding(struct scsi_target *starget) | ||
729 | { | ||
730 | struct _MPT_SCSI_HOST *hd = | ||
731 | (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata; | ||
732 | return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) && | ||
733 | starget->channel == 0) ? 1 : 0; | ||
734 | } | ||
735 | |||
736 | static struct spi_function_template mptspi_transport_functions = { | ||
737 | .get_offset = mptspi_read_parameters, | ||
738 | .set_offset = mptspi_write_offset, | ||
739 | .show_offset = 1, | ||
740 | .get_period = mptspi_read_parameters, | ||
741 | .set_period = mptspi_write_period, | ||
742 | .show_period = 1, | ||
743 | .get_width = mptspi_read_parameters, | ||
744 | .set_width = mptspi_write_width, | ||
745 | .show_width = 1, | ||
746 | .get_iu = mptspi_read_parameters, | ||
747 | .set_iu = mptspi_write_iu, | ||
748 | .show_iu = 1, | ||
749 | .get_dt = mptspi_read_parameters, | ||
750 | .set_dt = mptspi_write_dt, | ||
751 | .show_dt = 1, | ||
752 | .get_qas = mptspi_read_parameters, | ||
753 | .set_qas = mptspi_write_qas, | ||
754 | .show_qas = 1, | ||
755 | .get_wr_flow = mptspi_read_parameters, | ||
756 | .set_wr_flow = mptspi_write_wr_flow, | ||
757 | .show_wr_flow = 1, | ||
758 | .get_rd_strm = mptspi_read_parameters, | ||
759 | .set_rd_strm = mptspi_write_rd_strm, | ||
760 | .show_rd_strm = 1, | ||
761 | .get_rti = mptspi_read_parameters, | ||
762 | .set_rti = mptspi_write_rti, | ||
763 | .show_rti = 1, | ||
764 | .get_pcomp_en = mptspi_read_parameters, | ||
765 | .set_pcomp_en = mptspi_write_pcomp_en, | ||
766 | .show_pcomp_en = 1, | ||
767 | .get_hold_mcs = mptspi_read_parameters, | ||
768 | .set_hold_mcs = mptspi_write_hold_mcs, | ||
769 | .show_hold_mcs = 1, | ||
770 | .deny_binding = mptspi_deny_binding, | ||
771 | }; | ||
131 | 772 | ||
132 | /**************************************************************************** | 773 | /**************************************************************************** |
133 | * Supported hardware | 774 | * Supported hardware |
@@ -242,7 +883,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
242 | sh->max_id = MPT_MAX_SCSI_DEVICES; | 883 | sh->max_id = MPT_MAX_SCSI_DEVICES; |
243 | 884 | ||
244 | sh->max_lun = MPT_LAST_LUN + 1; | 885 | sh->max_lun = MPT_LAST_LUN + 1; |
245 | sh->max_channel = 0; | 886 | /* |
887 | * If RAID Firmware Detected, setup virtual channel | ||
888 | */ | ||
889 | if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | ||
890 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) | ||
891 | sh->max_channel = 1; | ||
892 | else | ||
893 | sh->max_channel = 0; | ||
246 | sh->this_id = ioc->pfacts[0].PortSCSIID; | 894 | sh->this_id = ioc->pfacts[0].PortSCSIID; |
247 | 895 | ||
248 | /* Required entry. | 896 | /* Required entry. |
@@ -301,7 +949,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
301 | * indicates a device exists. | 949 | * indicates a device exists. |
302 | * max_id = 1 + maximum id (hosts.h) | 950 | * max_id = 1 + maximum id (hosts.h) |
303 | */ | 951 | */ |
304 | hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); | 952 | hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1), |
953 | sizeof(void *), GFP_ATOMIC); | ||
305 | if (!hd->Targets) { | 954 | if (!hd->Targets) { |
306 | error = -ENOMEM; | 955 | error = -ENOMEM; |
307 | goto out_mptspi_probe; | 956 | goto out_mptspi_probe; |
@@ -334,49 +983,23 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
334 | ioc->spi_data.Saf_Te = mpt_saf_te; | 983 | ioc->spi_data.Saf_Te = mpt_saf_te; |
335 | hd->mpt_pq_filter = mpt_pq_filter; | 984 | hd->mpt_pq_filter = mpt_pq_filter; |
336 | 985 | ||
337 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
338 | if (ioc->spi_data.maxBusWidth > mpt_width) | ||
339 | ioc->spi_data.maxBusWidth = mpt_width; | ||
340 | if (ioc->spi_data.minSyncFactor < mpt_factor) | ||
341 | ioc->spi_data.minSyncFactor = mpt_factor; | ||
342 | if (ioc->spi_data.minSyncFactor == MPT_ASYNC) { | ||
343 | ioc->spi_data.maxSyncOffset = 0; | ||
344 | } | ||
345 | ioc->spi_data.mpt_dv = mpt_dv; | ||
346 | hd->negoNvram = 0; | ||
347 | |||
348 | ddvprintk((MYIOC_s_INFO_FMT | ||
349 | "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n", | ||
350 | ioc->name, | ||
351 | mpt_dv, | ||
352 | mpt_width, | ||
353 | mpt_factor, | ||
354 | mpt_saf_te, | ||
355 | mpt_pq_filter)); | ||
356 | #else | ||
357 | hd->negoNvram = MPT_SCSICFG_USE_NVRAM; | 986 | hd->negoNvram = MPT_SCSICFG_USE_NVRAM; |
358 | ddvprintk((MYIOC_s_INFO_FMT | 987 | ddvprintk((MYIOC_s_INFO_FMT |
359 | "saf_te %x mpt_pq_filter %x\n", | 988 | "saf_te %x mpt_pq_filter %x\n", |
360 | ioc->name, | 989 | ioc->name, |
361 | mpt_saf_te, | 990 | mpt_saf_te, |
362 | mpt_pq_filter)); | 991 | mpt_pq_filter)); |
363 | #endif | ||
364 | |||
365 | ioc->spi_data.forceDv = 0; | ||
366 | ioc->spi_data.noQas = 0; | 992 | ioc->spi_data.noQas = 0; |
367 | 993 | ||
368 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) | ||
369 | ioc->spi_data.dvStatus[ii] = | ||
370 | MPT_SCSICFG_NEGOTIATE; | ||
371 | |||
372 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) | ||
373 | ioc->spi_data.dvStatus[ii] |= | ||
374 | MPT_SCSICFG_DV_NOT_DONE; | ||
375 | |||
376 | init_waitqueue_head(&hd->scandv_waitq); | 994 | init_waitqueue_head(&hd->scandv_waitq); |
377 | hd->scandv_wait_done = 0; | 995 | hd->scandv_wait_done = 0; |
378 | hd->last_queue_full = 0; | 996 | hd->last_queue_full = 0; |
379 | 997 | ||
998 | /* Some versions of the firmware don't support page 0; without | ||
999 | * that we can't get the parameters */ | ||
1000 | if (hd->ioc->spi_data.sdp0length != 0) | ||
1001 | sh->transportt = mptspi_transport_template; | ||
1002 | |||
380 | error = scsi_add_host (sh, &ioc->pcidev->dev); | 1003 | error = scsi_add_host (sh, &ioc->pcidev->dev); |
381 | if(error) { | 1004 | if(error) { |
382 | dprintk((KERN_ERR MYNAM | 1005 | dprintk((KERN_ERR MYNAM |
@@ -423,14 +1046,17 @@ static struct pci_driver mptspi_driver = { | |||
423 | static int __init | 1046 | static int __init |
424 | mptspi_init(void) | 1047 | mptspi_init(void) |
425 | { | 1048 | { |
426 | |||
427 | show_mptmod_ver(my_NAME, my_VERSION); | 1049 | show_mptmod_ver(my_NAME, my_VERSION); |
428 | 1050 | ||
1051 | mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions); | ||
1052 | if (!mptspi_transport_template) | ||
1053 | return -ENODEV; | ||
1054 | |||
429 | mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); | 1055 | mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); |
430 | mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); | 1056 | mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); |
431 | mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); | 1057 | mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); |
432 | 1058 | ||
433 | if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) { | 1059 | if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) { |
434 | devtprintk((KERN_INFO MYNAM | 1060 | devtprintk((KERN_INFO MYNAM |
435 | ": Registered for IOC event notifications\n")); | 1061 | ": Registered for IOC event notifications\n")); |
436 | } | 1062 | } |
@@ -465,6 +1091,7 @@ mptspi_exit(void) | |||
465 | mpt_deregister(mptspiInternalCtx); | 1091 | mpt_deregister(mptspiInternalCtx); |
466 | mpt_deregister(mptspiTaskCtx); | 1092 | mpt_deregister(mptspiTaskCtx); |
467 | mpt_deregister(mptspiDoneCtx); | 1093 | mpt_deregister(mptspiDoneCtx); |
1094 | spi_release_transport(mptspi_transport_template); | ||
468 | } | 1095 | } |
469 | 1096 | ||
470 | module_init(mptspi_init); | 1097 | module_init(mptspi_init); |