diff options
Diffstat (limited to 'drivers/message/fusion/mptscsih.c')
| -rw-r--r-- | drivers/message/fusion/mptscsih.c | 2486 |
1 files changed, 116 insertions, 2370 deletions
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 4fee6befc93d..3729062db317 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 */ |
| @@ -931,7 +887,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | |||
| 931 | dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", | 887 | dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", |
| 932 | hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); | 888 | hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); |
| 933 | 889 | ||
| 934 | if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) | 890 | if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) |
| 935 | continue; | 891 | continue; |
| 936 | 892 | ||
| 937 | /* Cleanup | 893 | /* Cleanup |
| @@ -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,14 @@ 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 ((hd->ioc->bus_type == SPI) && | ||
| 1239 | vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && | ||
| 1240 | mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { | ||
| 1241 | SCpnt->result = DID_NO_CONNECT << 16; | ||
| 1242 | done(SCpnt); | ||
| 1243 | return 0; | ||
| 1244 | } | ||
| 1245 | |||
| 1320 | /* | 1246 | /* |
| 1321 | * Put together a MPT SCSI request... | 1247 | * Put together a MPT SCSI request... |
| 1322 | */ | 1248 | */ |
| @@ -1360,10 +1286,13 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
| 1360 | 1286 | ||
| 1361 | /* Use the above information to set up the message frame | 1287 | /* Use the above information to set up the message frame |
| 1362 | */ | 1288 | */ |
| 1363 | pScsiReq->TargetID = (u8) vdev->target_id; | 1289 | pScsiReq->TargetID = (u8) vdev->vtarget->target_id; |
| 1364 | pScsiReq->Bus = vdev->bus_id; | 1290 | pScsiReq->Bus = vdev->vtarget->bus_id; |
| 1365 | pScsiReq->ChainOffset = 0; | 1291 | pScsiReq->ChainOffset = 0; |
| 1366 | pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; | 1292 | if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) |
| 1293 | pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; | ||
| 1294 | else | ||
| 1295 | pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; | ||
| 1367 | pScsiReq->CDBLength = SCpnt->cmd_len; | 1296 | pScsiReq->CDBLength = SCpnt->cmd_len; |
| 1368 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; | 1297 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; |
| 1369 | pScsiReq->Reserved = 0; | 1298 | pScsiReq->Reserved = 0; |
| @@ -1411,49 +1340,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
| 1411 | hd->ScsiLookup[my_idx] = SCpnt; | 1340 | hd->ScsiLookup[my_idx] = SCpnt; |
| 1412 | SCpnt->host_scribble = NULL; | 1341 | SCpnt->host_scribble = NULL; |
| 1413 | 1342 | ||
| 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); | 1343 | 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", | 1344 | dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", |
| 1459 | hd->ioc->name, SCpnt, mf, my_idx)); | 1345 | hd->ioc->name, SCpnt, mf, my_idx)); |
| @@ -1816,7 +1702,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
| 1816 | 1702 | ||
| 1817 | vdev = SCpnt->device->hostdata; | 1703 | vdev = SCpnt->device->hostdata; |
| 1818 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, | 1704 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, |
| 1819 | vdev->bus_id, vdev->target_id, vdev->lun, | 1705 | vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, |
| 1820 | ctx2abort, mptscsih_get_tm_timeout(ioc)); | 1706 | ctx2abort, mptscsih_get_tm_timeout(ioc)); |
| 1821 | 1707 | ||
| 1822 | printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", | 1708 | printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", |
| @@ -1867,7 +1753,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
| 1867 | 1753 | ||
| 1868 | vdev = SCpnt->device->hostdata; | 1754 | vdev = SCpnt->device->hostdata; |
| 1869 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, | 1755 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, |
| 1870 | vdev->bus_id, vdev->target_id, | 1756 | vdev->vtarget->bus_id, vdev->vtarget->target_id, |
| 1871 | 0, 0, mptscsih_get_tm_timeout(hd->ioc)); | 1757 | 0, 0, mptscsih_get_tm_timeout(hd->ioc)); |
| 1872 | 1758 | ||
| 1873 | printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", | 1759 | printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", |
| @@ -1918,7 +1804,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) | |||
| 1918 | 1804 | ||
| 1919 | vdev = SCpnt->device->hostdata; | 1805 | vdev = SCpnt->device->hostdata; |
| 1920 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | 1806 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, |
| 1921 | vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); | 1807 | vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); |
| 1922 | 1808 | ||
| 1923 | printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", | 1809 | printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", |
| 1924 | hd->ioc->name, | 1810 | hd->ioc->name, |
| @@ -2218,6 +2104,42 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, | |||
| 2218 | return 0; | 2104 | return 0; |
| 2219 | } | 2105 | } |
| 2220 | 2106 | ||
| 2107 | /* Search IOC page 3 to determine if this is hidden physical disk | ||
| 2108 | * | ||
| 2109 | */ | ||
| 2110 | int | ||
| 2111 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) | ||
| 2112 | { | ||
| 2113 | int i; | ||
| 2114 | |||
| 2115 | if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) | ||
| 2116 | return 0; | ||
| 2117 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
| 2118 | if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) | ||
| 2119 | return 1; | ||
| 2120 | } | ||
| 2121 | return 0; | ||
| 2122 | } | ||
| 2123 | EXPORT_SYMBOL(mptscsih_is_phys_disk); | ||
| 2124 | |||
| 2125 | int | ||
| 2126 | mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) | ||
| 2127 | { | ||
| 2128 | int i; | ||
| 2129 | |||
| 2130 | if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3) | ||
| 2131 | return -ENXIO; | ||
| 2132 | |||
| 2133 | for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
| 2134 | if (physdiskid == | ||
| 2135 | hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) | ||
| 2136 | return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; | ||
| 2137 | } | ||
| 2138 | |||
| 2139 | return -ENXIO; | ||
| 2140 | } | ||
| 2141 | EXPORT_SYMBOL(mptscsih_raid_id_to_num); | ||
| 2142 | |||
| 2221 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2143 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 2222 | /* | 2144 | /* |
| 2223 | * OS entry point to allow host driver to alloc memory | 2145 | * OS entry point to allow host driver to alloc memory |
| @@ -2233,6 +2155,7 @@ mptscsih_target_alloc(struct scsi_target *starget) | |||
| 2233 | if (!vtarget) | 2155 | if (!vtarget) |
| 2234 | return -ENOMEM; | 2156 | return -ENOMEM; |
| 2235 | starget->hostdata = vtarget; | 2157 | starget->hostdata = vtarget; |
| 2158 | vtarget->starget = starget; | ||
| 2236 | return 0; | 2159 | return 0; |
| 2237 | } | 2160 | } |
| 2238 | 2161 | ||
| @@ -2258,14 +2181,12 @@ mptscsih_slave_alloc(struct scsi_device *sdev) | |||
| 2258 | return -ENOMEM; | 2181 | return -ENOMEM; |
| 2259 | } | 2182 | } |
| 2260 | 2183 | ||
| 2261 | vdev->ioc_id = hd->ioc->id; | ||
| 2262 | vdev->target_id = sdev->id; | ||
| 2263 | vdev->bus_id = sdev->channel; | ||
| 2264 | vdev->lun = sdev->lun; | 2184 | vdev->lun = sdev->lun; |
| 2265 | sdev->hostdata = vdev; | 2185 | sdev->hostdata = vdev; |
| 2266 | 2186 | ||
| 2267 | starget = scsi_target(sdev); | 2187 | starget = scsi_target(sdev); |
| 2268 | vtarget = starget->hostdata; | 2188 | vtarget = starget->hostdata; |
| 2189 | |||
| 2269 | vdev->vtarget = vtarget; | 2190 | vdev->vtarget = vtarget; |
| 2270 | 2191 | ||
| 2271 | if (vtarget->num_luns == 0) { | 2192 | if (vtarget->num_luns == 0) { |
| @@ -2274,14 +2195,11 @@ mptscsih_slave_alloc(struct scsi_device *sdev) | |||
| 2274 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; | 2195 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; |
| 2275 | vtarget->target_id = sdev->id; | 2196 | vtarget->target_id = sdev->id; |
| 2276 | vtarget->bus_id = sdev->channel; | 2197 | vtarget->bus_id = sdev->channel; |
| 2277 | if (hd->ioc->bus_type == SPI) { | 2198 | if (hd->ioc->bus_type == SPI && sdev->channel == 0 && |
| 2278 | if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) { | 2199 | hd->ioc->raid_data.isRaid & (1 << sdev->id)) { |
| 2279 | vtarget->raidVolume = 1; | 2200 | vtarget->raidVolume = 1; |
| 2280 | ddvtprintk((KERN_INFO | 2201 | ddvtprintk((KERN_INFO |
| 2281 | "RAID Volume @ id %d\n", sdev->id)); | 2202 | "RAID Volume @ id %d\n", sdev->id)); |
| 2282 | } | ||
| 2283 | } else { | ||
| 2284 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; | ||
| 2285 | } | 2203 | } |
| 2286 | } | 2204 | } |
| 2287 | vtarget->num_luns++; | 2205 | vtarget->num_luns++; |
| @@ -2321,19 +2239,6 @@ mptscsih_slave_destroy(struct scsi_device *sdev) | |||
| 2321 | vtarget->luns[0] &= ~(1 << vdevice->lun); | 2239 | vtarget->luns[0] &= ~(1 << vdevice->lun); |
| 2322 | vtarget->num_luns--; | 2240 | vtarget->num_luns--; |
| 2323 | if (vtarget->num_luns == 0) { | 2241 | 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; | 2242 | hd->Targets[sdev->id] = NULL; |
| 2338 | } | 2243 | } |
| 2339 | mptscsih_synchronize_cache(hd, vdevice); | 2244 | mptscsih_synchronize_cache(hd, vdevice); |
| @@ -2362,18 +2267,13 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
| 2362 | vtarget = starget->hostdata; | 2267 | vtarget = starget->hostdata; |
| 2363 | 2268 | ||
| 2364 | if (hd->ioc->bus_type == SPI) { | 2269 | if (hd->ioc->bus_type == SPI) { |
| 2365 | if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { | 2270 | 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; | 2271 | max_depth = 1; |
| 2376 | } | 2272 | else if (sdev->type == TYPE_DISK && |
| 2273 | vtarget->minSyncFactor <= MPT_ULTRA160) | ||
| 2274 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; | ||
| 2275 | else | ||
| 2276 | max_depth = MPT_SCSI_CMD_PER_DEV_LOW; | ||
| 2377 | } else | 2277 | } else |
| 2378 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; | 2278 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; |
| 2379 | 2279 | ||
| @@ -2427,8 +2327,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) | |||
| 2427 | lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ | 2327 | lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ |
| 2428 | indexed_lun = (vdevice->lun % 32); | 2328 | indexed_lun = (vdevice->lun % 32); |
| 2429 | vtarget->luns[lun_index] |= (1 << indexed_lun); | 2329 | vtarget->luns[lun_index] |= (1 << indexed_lun); |
| 2430 | mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry, | 2330 | mptscsih_initTarget(hd, vtarget, sdev); |
| 2431 | sdev->inquiry_len ); | ||
| 2432 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); | 2331 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); |
| 2433 | 2332 | ||
| 2434 | dsprintk((MYIOC_s_INFO_FMT | 2333 | dsprintk((MYIOC_s_INFO_FMT |
| @@ -2597,10 +2496,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
| 2597 | 2496 | ||
| 2598 | /* 4. Renegotiate to all devices, if SPI | 2497 | /* 4. Renegotiate to all devices, if SPI |
| 2599 | */ | 2498 | */ |
| 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 | 2499 | ||
| 2605 | /* 5. Enable new commands to be posted | 2500 | /* 5. Enable new commands to be posted |
| 2606 | */ | 2501 | */ |
| @@ -2624,13 +2519,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
| 2624 | hd->cmdPtr = NULL; | 2519 | hd->cmdPtr = NULL; |
| 2625 | } | 2520 | } |
| 2626 | 2521 | ||
| 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. | 2522 | /* 7. FC: Rescan for blocked rports which might have returned. |
| 2635 | */ | 2523 | */ |
| 2636 | else if (ioc->bus_type == FC) { | 2524 | else if (ioc->bus_type == FC) { |
| @@ -2659,7 +2547,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
| 2659 | int work_count; | 2547 | int work_count; |
| 2660 | unsigned long flags; | 2548 | unsigned long flags; |
| 2661 | 2549 | ||
| 2662 | devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", | 2550 | devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", |
| 2663 | ioc->name, event)); | 2551 | ioc->name, event)); |
| 2664 | 2552 | ||
| 2665 | if (ioc->sh == NULL || | 2553 | if (ioc->sh == NULL || |
| @@ -2699,18 +2587,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
| 2699 | break; | 2587 | break; |
| 2700 | 2588 | ||
| 2701 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ | 2589 | 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; | 2590 | break; |
| 2713 | } | ||
| 2714 | 2591 | ||
| 2715 | case MPI_EVENT_NONE: /* 00 */ | 2592 | case MPI_EVENT_NONE: /* 00 */ |
| 2716 | case MPI_EVENT_LOG_DATA: /* 01 */ | 2593 | case MPI_EVENT_LOG_DATA: /* 01 */ |
| @@ -2729,9 +2606,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
| 2729 | * mptscsih_initTarget - Target, LUN alloc/free functionality. | 2606 | * mptscsih_initTarget - Target, LUN alloc/free functionality. |
| 2730 | * @hd: Pointer to MPT_SCSI_HOST structure | 2607 | * @hd: Pointer to MPT_SCSI_HOST structure |
| 2731 | * @vtarget: per target private data | 2608 | * @vtarget: per target private data |
| 2732 | * @lun: SCSI LUN id | 2609 | * @sdev: SCSI device |
| 2733 | * @data: Pointer to data | ||
| 2734 | * @dlen: Number of INQUIRY bytes | ||
| 2735 | * | 2610 | * |
| 2736 | * NOTE: It's only SAFE to call this routine if data points to | 2611 | * NOTE: It's only SAFE to call this routine if data points to |
| 2737 | * sane & valid STANDARD INQUIRY data! | 2612 | * sane & valid STANDARD INQUIRY data! |
| @@ -2741,98 +2616,46 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
| 2741 | * | 2616 | * |
| 2742 | */ | 2617 | */ |
| 2743 | static void | 2618 | static void |
| 2744 | mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen) | 2619 | mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, |
| 2620 | struct scsi_device *sdev) | ||
| 2745 | { | 2621 | { |
| 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", | 2622 | 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)); | 2623 | hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd)); |
| 2752 | 2624 | ||
| 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 | 2625 | /* Is LUN supported? If so, upper 2 bits will be 0 |
| 2766 | * in first byte of inquiry data. | 2626 | * in first byte of inquiry data. |
| 2767 | */ | 2627 | */ |
| 2768 | if (data[0] & 0xe0) | 2628 | if (sdev->inq_periph_qual != 0) |
| 2769 | return; | 2629 | return; |
| 2770 | 2630 | ||
| 2771 | if (vtarget == NULL) | 2631 | if (vtarget == NULL) |
| 2772 | return; | 2632 | return; |
| 2773 | 2633 | ||
| 2774 | if (data) | 2634 | vtarget->type = sdev->type; |
| 2775 | vtarget->type = data[0]; | ||
| 2776 | 2635 | ||
| 2777 | if (hd->ioc->bus_type != SPI) | 2636 | if (hd->ioc->bus_type != SPI) |
| 2778 | return; | 2637 | return; |
| 2779 | 2638 | ||
| 2780 | if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { | 2639 | if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { |
| 2781 | /* Treat all Processors as SAF-TE if | 2640 | /* Treat all Processors as SAF-TE if |
| 2782 | * command line option is set */ | 2641 | * command line option is set */ |
| 2783 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; | 2642 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; |
| 2784 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); | 2643 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); |
| 2785 | }else if ((data[0] == TYPE_PROCESSOR) && | 2644 | }else if ((sdev->type == TYPE_PROCESSOR) && |
| 2786 | !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { | 2645 | !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { |
| 2787 | if ( dlen > 49 ) { | 2646 | if (sdev->inquiry_len > 49 ) { |
| 2788 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; | 2647 | if (sdev->inquiry[44] == 'S' && |
| 2789 | if ( data[44] == 'S' && | 2648 | sdev->inquiry[45] == 'A' && |
| 2790 | data[45] == 'A' && | 2649 | sdev->inquiry[46] == 'F' && |
| 2791 | data[46] == 'F' && | 2650 | sdev->inquiry[47] == '-' && |
| 2792 | data[47] == '-' && | 2651 | sdev->inquiry[48] == 'T' && |
| 2793 | data[48] == 'T' && | 2652 | sdev->inquiry[49] == 'E' ) { |
| 2794 | data[49] == 'E' ) { | ||
| 2795 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; | 2653 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; |
| 2796 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); | 2654 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); |
| 2797 | } | 2655 | } |
| 2798 | } | 2656 | } |
| 2799 | } | 2657 | } |
| 2800 | if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { | 2658 | 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 | } | 2659 | } |
| 2837 | 2660 | ||
| 2838 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2661 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -2842,66 +2665,51 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, | |||
| 2842 | * | 2665 | * |
| 2843 | */ | 2666 | */ |
| 2844 | static void | 2667 | static void |
| 2845 | mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) | 2668 | mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, |
| 2669 | struct scsi_device *sdev) | ||
| 2846 | { | 2670 | { |
| 2847 | SpiCfgData *pspi_data = &hd->ioc->spi_data; | 2671 | SpiCfgData *pspi_data = &hd->ioc->spi_data; |
| 2848 | int id = (int) target->target_id; | 2672 | int id = (int) target->target_id; |
| 2849 | int nvram; | 2673 | int nvram; |
| 2850 | VirtTarget *vtarget; | ||
| 2851 | int ii; | ||
| 2852 | u8 width = MPT_NARROW; | 2674 | u8 width = MPT_NARROW; |
| 2853 | u8 factor = MPT_ASYNC; | 2675 | u8 factor = MPT_ASYNC; |
| 2854 | u8 offset = 0; | 2676 | u8 offset = 0; |
| 2855 | u8 version, nfactor; | 2677 | u8 nfactor; |
| 2856 | u8 noQas = 1; | 2678 | u8 noQas = 1; |
| 2857 | 2679 | ||
| 2858 | target->negoFlags = pspi_data->noQas; | 2680 | target->negoFlags = pspi_data->noQas; |
| 2859 | 2681 | ||
| 2860 | /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine | 2682 | /* 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 | 2683 | ||
| 2865 | /* Set flags based on Inquiry data | 2684 | if (sdev->scsi_level < SCSI_2) { |
| 2866 | */ | ||
| 2867 | version = target->inq_data[2] & 0x07; | ||
| 2868 | if (version < 2) { | ||
| 2869 | width = 0; | 2685 | width = 0; |
| 2870 | factor = MPT_ULTRA2; | 2686 | factor = MPT_ULTRA2; |
| 2871 | offset = pspi_data->maxSyncOffset; | 2687 | offset = pspi_data->maxSyncOffset; |
| 2872 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; | 2688 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; |
| 2873 | } else { | 2689 | } else { |
| 2874 | if (target->inq_data[7] & 0x20) { | 2690 | if (scsi_device_wide(sdev)) { |
| 2875 | width = 1; | 2691 | width = 1; |
| 2876 | } | 2692 | } |
| 2877 | 2693 | ||
| 2878 | if (target->inq_data[7] & 0x10) { | 2694 | if (scsi_device_sync(sdev)) { |
| 2879 | factor = pspi_data->minSyncFactor; | 2695 | factor = pspi_data->minSyncFactor; |
| 2880 | if (target->tflags & MPT_TARGET_FLAGS_VALID_56) { | 2696 | if (!scsi_device_dt(sdev)) |
| 2881 | /* bits 2 & 3 show Clocking support */ | ||
| 2882 | if ((byte56 & 0x0C) == 0) | ||
| 2883 | factor = MPT_ULTRA2; | 2697 | factor = MPT_ULTRA2; |
| 2698 | else { | ||
| 2699 | if (!scsi_device_ius(sdev) && | ||
| 2700 | !scsi_device_qas(sdev)) | ||
| 2701 | factor = MPT_ULTRA160; | ||
| 2884 | else { | 2702 | else { |
| 2885 | if ((byte56 & 0x03) == 0) | 2703 | factor = MPT_ULTRA320; |
| 2886 | factor = MPT_ULTRA160; | 2704 | if (scsi_device_qas(sdev)) { |
| 2887 | else { | 2705 | ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); |
| 2888 | factor = MPT_ULTRA320; | 2706 | 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 | } | 2707 | } |
| 2708 | if (sdev->type == TYPE_TAPE && | ||
| 2709 | scsi_device_ius(sdev)) | ||
| 2710 | target->negoFlags |= MPT_TAPE_NEGO_IDP; | ||
| 2899 | } | 2711 | } |
| 2900 | } else { | ||
| 2901 | ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id)); | ||
| 2902 | noQas = 0; | ||
| 2903 | } | 2712 | } |
| 2904 | |||
| 2905 | offset = pspi_data->maxSyncOffset; | 2713 | offset = pspi_data->maxSyncOffset; |
| 2906 | 2714 | ||
| 2907 | /* If RAID, never disable QAS | 2715 | /* If RAID, never disable QAS |
| @@ -2919,7 +2727,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) | |||
| 2919 | } | 2727 | } |
| 2920 | } | 2728 | } |
| 2921 | 2729 | ||
| 2922 | if ( (target->inq_data[7] & 0x02) == 0) { | 2730 | if (!sdev->tagged_supported) { |
| 2923 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; | 2731 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; |
| 2924 | } | 2732 | } |
| 2925 | 2733 | ||
| @@ -2977,305 +2785,23 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) | |||
| 2977 | if ( factor > MPT_ULTRA320 ) | 2785 | if ( factor > MPT_ULTRA320 ) |
| 2978 | noQas = 0; | 2786 | noQas = 0; |
| 2979 | 2787 | ||
| 2980 | /* GEM, processor WORKAROUND | 2788 | if (noQas && (pspi_data->noQas == 0)) { |
| 2981 | */ | 2789 | pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; |
| 2982 | if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) { | 2790 | target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; |
| 2983 | target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); | 2791 | |
| 2984 | pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; | 2792 | /* Disable QAS in a mixed configuration case |
| 2985 | } else { | 2793 | */ |
| 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 | 2794 | ||
| 3003 | /* Write SDP1 on this I/O to this target */ | 2795 | 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 | } | 2796 | } |
| 3013 | } | 2797 | } |
| 3014 | 2798 | ||
| 3015 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2799 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 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 | 2800 | ||
| 3030 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2801 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 3031 | /* | 2802 | /* |
| 3032 | * SCSI Config Page functionality ... | 2803 | * SCSI Config Page functionality ... |
| 3033 | */ | 2804 | */ |
| 3034 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 3035 | /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags | ||
| 3036 | * based on width, factor and offset parameters. | ||
| 3037 | * @width: bus width | ||
| 3038 | * @factor: sync factor | ||
| 3039 | * @offset: sync offset | ||
| 3040 | * @requestedPtr: pointer to requested values (updated) | ||
| 3041 | * @configurationPtr: pointer to configuration values (updated) | ||
| 3042 | * @flags: flags to block WDTR or SDTR negotiation | ||
| 3043 | * | ||
| 3044 | * Return: None. | ||
| 3045 | * | ||
| 3046 | * Remark: Called by writeSDP1 and _dv_params | ||
| 3047 | */ | ||
| 3048 | static void | ||
| 3049 | mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags) | ||
| 3050 | { | ||
| 3051 | u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE; | ||
| 3052 | u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC; | ||
| 3053 | |||
| 3054 | *configurationPtr = 0; | ||
| 3055 | *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; | ||
| 3056 | *requestedPtr |= (offset << 16) | (factor << 8); | ||
| 3057 | |||
| 3058 | if (width && offset && !nowide && !nosync) { | ||
| 3059 | if (factor < MPT_ULTRA160) { | ||
| 3060 | *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT); | ||
| 3061 | if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0) | ||
| 3062 | *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS; | ||
| 3063 | if (flags & MPT_TAPE_NEGO_IDP) | ||
| 3064 | *requestedPtr |= 0x08000000; | ||
| 3065 | } else if (factor < MPT_ULTRA2) { | ||
| 3066 | *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT; | ||
| 3067 | } | ||
| 3068 | } | ||
| 3069 | |||
| 3070 | if (nowide) | ||
| 3071 | *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED; | ||
| 3072 | |||
| 3073 | if (nosync) | ||
| 3074 | *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED; | ||
| 3075 | |||
| 3076 | return; | ||
| 3077 | } | ||
| 3078 | |||
| 3079 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 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 | 2805 | ||
| 3280 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2806 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 3281 | /* mptscsih_writeIOCPage4 - write IOC Page 4 | 2807 | /* mptscsih_writeIOCPage4 - write IOC Page 4 |
| @@ -3465,6 +2991,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
| 3465 | completionCode = MPT_SCANDV_GOOD; | 2991 | completionCode = MPT_SCANDV_GOOD; |
| 3466 | else | 2992 | else |
| 3467 | completionCode = MPT_SCANDV_SOME_ERROR; | 2993 | completionCode = MPT_SCANDV_SOME_ERROR; |
| 2994 | memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense)); | ||
| 3468 | 2995 | ||
| 3469 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { | 2996 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { |
| 3470 | u8 *sense_data; | 2997 | u8 *sense_data; |
| @@ -3578,78 +3105,6 @@ mptscsih_timer_expired(unsigned long data) | |||
| 3578 | return; | 3105 | return; |
| 3579 | } | 3106 | } |
| 3580 | 3107 | ||
| 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 | 3108 | ||
| 3654 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3109 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 3655 | /** | 3110 | /** |
| @@ -3903,93 +3358,6 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3903 | 3358 | ||
| 3904 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3359 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 3905 | /** | 3360 | /** |
| 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. | 3361 | * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. |
| 3994 | * @hd: Pointer to a SCSI HOST structure | 3362 | * @hd: Pointer to a SCSI HOST structure |
| 3995 | * @vtarget: per device private data | 3363 | * @vtarget: per device private data |
| @@ -4014,1637 +3382,15 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | |||
| 4014 | iocmd.data_dma = -1; | 3382 | iocmd.data_dma = -1; |
| 4015 | iocmd.size = 0; | 3383 | iocmd.size = 0; |
| 4016 | iocmd.rsvd = iocmd.rsvd2 = 0; | 3384 | iocmd.rsvd = iocmd.rsvd2 = 0; |
| 4017 | iocmd.bus = vdevice->bus_id; | 3385 | iocmd.bus = vdevice->vtarget->bus_id; |
| 4018 | iocmd.id = vdevice->target_id; | 3386 | iocmd.id = vdevice->vtarget->target_id; |
| 4019 | iocmd.lun = (u8)vdevice->lun; | 3387 | iocmd.lun = (u8)vdevice->lun; |
| 4020 | 3388 | ||
| 4021 | if ((vdevice->vtarget->type & TYPE_DISK) && | 3389 | if ((vdevice->vtarget->type == TYPE_DISK) && |
| 4022 | (vdevice->configured_lun)) | 3390 | (vdevice->configured_lun)) |
| 4023 | mptscsih_do_cmd(hd, &iocmd); | 3391 | mptscsih_do_cmd(hd, &iocmd); |
| 4024 | } | 3392 | } |
| 4025 | 3393 | ||
| 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); | 3394 | EXPORT_SYMBOL(mptscsih_remove); |
| 5649 | EXPORT_SYMBOL(mptscsih_shutdown); | 3395 | EXPORT_SYMBOL(mptscsih_shutdown); |
| 5650 | #ifdef CONFIG_PM | 3396 | #ifdef CONFIG_PM |
