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/mptscsih.c | |
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/mptscsih.c')
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 2402 |
1 files changed, 88 insertions, 2314 deletions
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 |