From 501280f5a043ec73979b94d4c23e7aae1727f32e Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 22 Mar 2016 20:32:03 +0100 Subject: [PATCH 001/138] scsi: make some Additional Sense strings more grep'able There's little point in breaking these strings over multiple lines. Signed-off-by: Rasmus Villemoes Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/constants.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index fa09d4be2b53..58d94e3c3713 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -346,11 +346,9 @@ static const struct error_info additional[] = {0x0407, "Logical unit not ready, operation in progress"}, {0x0408, "Logical unit not ready, long write in progress"}, {0x0409, "Logical unit not ready, self-test in progress"}, - {0x040A, "Logical unit not accessible, asymmetric access state " - "transition"}, + {0x040A, "Logical unit not accessible, asymmetric access state transition"}, {0x040B, "Logical unit not accessible, target port in standby state"}, - {0x040C, "Logical unit not accessible, target port in unavailable " - "state"}, + {0x040C, "Logical unit not accessible, target port in unavailable state"}, {0x040D, "Logical unit not ready, structure check required"}, {0x040E, "Logical unit not ready, security session in progress"}, {0x0410, "Logical unit not ready, auxiliary memory not accessible"}, @@ -363,11 +361,9 @@ static const struct error_info additional[] = {0x0417, "Logical unit not ready, calibration required"}, {0x0418, "Logical unit not ready, a door is open"}, {0x0419, "Logical unit not ready, operating in sequential mode"}, - {0x041A, "Logical unit not ready, start stop unit command in " - "progress"}, + {0x041A, "Logical unit not ready, start stop unit command in progress"}, {0x041B, "Logical unit not ready, sanitize in progress"}, - {0x041C, "Logical unit not ready, additional power use not yet " - "granted"}, + {0x041C, "Logical unit not ready, additional power use not yet granted"}, {0x041D, "Logical unit not ready, configuration in progress"}, {0x041E, "Logical unit not ready, microcode activation required"}, {0x041F, "Logical unit not ready, microcode download required"}, @@ -559,8 +555,7 @@ static const struct error_info additional[] = {0x2300, "Invalid token operation, cause not reportable"}, {0x2301, "Invalid token operation, unsupported token type"}, {0x2302, "Invalid token operation, remote token usage not supported"}, - {0x2303, "Invalid token operation, remote rod token creation not " - "supported"}, + {0x2303, "Invalid token operation, remote rod token creation not supported"}, {0x2304, "Invalid token operation, token unknown"}, {0x2305, "Invalid token operation, token corrupt"}, {0x2306, "Invalid token operation, token revoked"}, @@ -641,8 +636,7 @@ static const struct error_info additional[] = {0x2A0D, "Data encryption capabilities changed"}, {0x2A10, "Timestamp changed"}, {0x2A11, "Data encryption parameters changed by another i_t nexus"}, - {0x2A12, "Data encryption parameters changed by vendor specific " - "event"}, + {0x2A12, "Data encryption parameters changed by vendor specific event"}, {0x2A13, "Data encryption key instance counter has changed"}, {0x2A14, "SA creation capabilities data has changed"}, {0x2A15, "Medium removal prevention preempted"}, @@ -759,8 +753,7 @@ static const struct error_info additional[] = {0x3B19, "Element enabled"}, {0x3B1A, "Data transfer device removed"}, {0x3B1B, "Data transfer device inserted"}, - {0x3B1C, "Too many logical objects on partition to support " - "operation"}, + {0x3B1C, "Too many logical objects on partition to support operation"}, {0x3D00, "Invalid bits in identify message"}, @@ -957,8 +950,7 @@ static const struct error_info additional[] = {0x5D39, "Data channel impending failure throughput performance"}, {0x5D3A, "Data channel impending failure seek time performance"}, {0x5D3B, "Data channel impending failure spin-up retry count"}, - {0x5D3C, "Data channel impending failure drive calibration retry " - "count"}, + {0x5D3C, "Data channel impending failure drive calibration retry count"}, {0x5D40, "Servo impending failure general hard drive failure"}, {0x5D41, "Servo impending failure drive error rate too high"}, {0x5D42, "Servo impending failure data error rate too high"}, @@ -1070,8 +1062,7 @@ static const struct error_info additional[] = {0x6E00, "Command to logical unit failed"}, - {0x6F00, "Copy protection key exchange failure - authentication " - "failure"}, + {0x6F00, "Copy protection key exchange failure - authentication failure"}, {0x6F01, "Copy protection key exchange failure - key not present"}, {0x6F02, "Copy protection key exchange failure - key not established"}, {0x6F03, "Read of scrambled sector without authentication"}, From 9d99a2e33a02c3290cb53013150ee06a304588ae Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 22 Mar 2016 20:32:04 +0100 Subject: [PATCH 002/138] scsi: move Additional Sense Codes to separate file This is a purely mechanical move of the list of additional sense codes to a separate file, in preparation for reducing the impact of choosing CONFIG_SCSI_CONSTANTS=y by about 8k. Signed-off-by: Rasmus Villemoes Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/constants.c | 830 +------------------------------------ drivers/scsi/sense_codes.h | 826 ++++++++++++++++++++++++++++++++++++ 2 files changed, 829 insertions(+), 827 deletions(-) create mode 100644 drivers/scsi/sense_codes.h diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 58d94e3c3713..6e813eec4f8d 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -295,835 +295,11 @@ struct error_info { const char * text; }; -/* - * The canonical list of T10 Additional Sense Codes is available at: - * http://www.t10.org/lists/asc-num.txt [most recent: 20141221] - */ - static const struct error_info additional[] = { - {0x0000, "No additional sense information"}, - {0x0001, "Filemark detected"}, - {0x0002, "End-of-partition/medium detected"}, - {0x0003, "Setmark detected"}, - {0x0004, "Beginning-of-partition/medium detected"}, - {0x0005, "End-of-data detected"}, - {0x0006, "I/O process terminated"}, - {0x0007, "Programmable early warning detected"}, - {0x0011, "Audio play operation in progress"}, - {0x0012, "Audio play operation paused"}, - {0x0013, "Audio play operation successfully completed"}, - {0x0014, "Audio play operation stopped due to error"}, - {0x0015, "No current audio status to return"}, - {0x0016, "Operation in progress"}, - {0x0017, "Cleaning requested"}, - {0x0018, "Erase operation in progress"}, - {0x0019, "Locate operation in progress"}, - {0x001A, "Rewind operation in progress"}, - {0x001B, "Set capacity operation in progress"}, - {0x001C, "Verify operation in progress"}, - {0x001D, "ATA pass through information available"}, - {0x001E, "Conflicting SA creation request"}, - {0x001F, "Logical unit transitioning to another power condition"}, - {0x0020, "Extended copy information available"}, - {0x0021, "Atomic command aborted due to ACA"}, - - {0x0100, "No index/sector signal"}, - - {0x0200, "No seek complete"}, - - {0x0300, "Peripheral device write fault"}, - {0x0301, "No write current"}, - {0x0302, "Excessive write errors"}, - - {0x0400, "Logical unit not ready, cause not reportable"}, - {0x0401, "Logical unit is in process of becoming ready"}, - {0x0402, "Logical unit not ready, initializing command required"}, - {0x0403, "Logical unit not ready, manual intervention required"}, - {0x0404, "Logical unit not ready, format in progress"}, - {0x0405, "Logical unit not ready, rebuild in progress"}, - {0x0406, "Logical unit not ready, recalculation in progress"}, - {0x0407, "Logical unit not ready, operation in progress"}, - {0x0408, "Logical unit not ready, long write in progress"}, - {0x0409, "Logical unit not ready, self-test in progress"}, - {0x040A, "Logical unit not accessible, asymmetric access state transition"}, - {0x040B, "Logical unit not accessible, target port in standby state"}, - {0x040C, "Logical unit not accessible, target port in unavailable state"}, - {0x040D, "Logical unit not ready, structure check required"}, - {0x040E, "Logical unit not ready, security session in progress"}, - {0x0410, "Logical unit not ready, auxiliary memory not accessible"}, - {0x0411, "Logical unit not ready, notify (enable spinup) required"}, - {0x0412, "Logical unit not ready, offline"}, - {0x0413, "Logical unit not ready, SA creation in progress"}, - {0x0414, "Logical unit not ready, space allocation in progress"}, - {0x0415, "Logical unit not ready, robotics disabled"}, - {0x0416, "Logical unit not ready, configuration required"}, - {0x0417, "Logical unit not ready, calibration required"}, - {0x0418, "Logical unit not ready, a door is open"}, - {0x0419, "Logical unit not ready, operating in sequential mode"}, - {0x041A, "Logical unit not ready, start stop unit command in progress"}, - {0x041B, "Logical unit not ready, sanitize in progress"}, - {0x041C, "Logical unit not ready, additional power use not yet granted"}, - {0x041D, "Logical unit not ready, configuration in progress"}, - {0x041E, "Logical unit not ready, microcode activation required"}, - {0x041F, "Logical unit not ready, microcode download required"}, - {0x0420, "Logical unit not ready, logical unit reset required"}, - {0x0421, "Logical unit not ready, hard reset required"}, - {0x0422, "Logical unit not ready, power cycle required"}, - - {0x0500, "Logical unit does not respond to selection"}, - - {0x0600, "No reference position found"}, - - {0x0700, "Multiple peripheral devices selected"}, - - {0x0800, "Logical unit communication failure"}, - {0x0801, "Logical unit communication time-out"}, - {0x0802, "Logical unit communication parity error"}, - {0x0803, "Logical unit communication CRC error (Ultra-DMA/32)"}, - {0x0804, "Unreachable copy target"}, - - {0x0900, "Track following error"}, - {0x0901, "Tracking servo failure"}, - {0x0902, "Focus servo failure"}, - {0x0903, "Spindle servo failure"}, - {0x0904, "Head select fault"}, - {0x0905, "Vibration induced tracking error"}, - - {0x0A00, "Error log overflow"}, - - {0x0B00, "Warning"}, - {0x0B01, "Warning - specified temperature exceeded"}, - {0x0B02, "Warning - enclosure degraded"}, - {0x0B03, "Warning - background self-test failed"}, - {0x0B04, "Warning - background pre-scan detected medium error"}, - {0x0B05, "Warning - background medium scan detected medium error"}, - {0x0B06, "Warning - non-volatile cache now volatile"}, - {0x0B07, "Warning - degraded power to non-volatile cache"}, - {0x0B08, "Warning - power loss expected"}, - {0x0B09, "Warning - device statistics notification active"}, - - {0x0C00, "Write error"}, - {0x0C01, "Write error - recovered with auto reallocation"}, - {0x0C02, "Write error - auto reallocation failed"}, - {0x0C03, "Write error - recommend reassignment"}, - {0x0C04, "Compression check miscompare error"}, - {0x0C05, "Data expansion occurred during compression"}, - {0x0C06, "Block not compressible"}, - {0x0C07, "Write error - recovery needed"}, - {0x0C08, "Write error - recovery failed"}, - {0x0C09, "Write error - loss of streaming"}, - {0x0C0A, "Write error - padding blocks added"}, - {0x0C0B, "Auxiliary memory write error"}, - {0x0C0C, "Write error - unexpected unsolicited data"}, - {0x0C0D, "Write error - not enough unsolicited data"}, - {0x0C0E, "Multiple write errors"}, - {0x0C0F, "Defects in error window"}, - {0x0C10, "Incomplete multiple atomic write operations"}, - - {0x0D00, "Error detected by third party temporary initiator"}, - {0x0D01, "Third party device failure"}, - {0x0D02, "Copy target device not reachable"}, - {0x0D03, "Incorrect copy target device type"}, - {0x0D04, "Copy target device data underrun"}, - {0x0D05, "Copy target device data overrun"}, - - {0x0E00, "Invalid information unit"}, - {0x0E01, "Information unit too short"}, - {0x0E02, "Information unit too long"}, - {0x0E03, "Invalid field in command information unit"}, - - {0x1000, "Id CRC or ECC error"}, - {0x1001, "Logical block guard check failed"}, - {0x1002, "Logical block application tag check failed"}, - {0x1003, "Logical block reference tag check failed"}, - {0x1004, "Logical block protection error on recover buffered data"}, - {0x1005, "Logical block protection method error"}, - - {0x1100, "Unrecovered read error"}, - {0x1101, "Read retries exhausted"}, - {0x1102, "Error too long to correct"}, - {0x1103, "Multiple read errors"}, - {0x1104, "Unrecovered read error - auto reallocate failed"}, - {0x1105, "L-EC uncorrectable error"}, - {0x1106, "CIRC unrecovered error"}, - {0x1107, "Data re-synchronization error"}, - {0x1108, "Incomplete block read"}, - {0x1109, "No gap found"}, - {0x110A, "Miscorrected error"}, - {0x110B, "Unrecovered read error - recommend reassignment"}, - {0x110C, "Unrecovered read error - recommend rewrite the data"}, - {0x110D, "De-compression CRC error"}, - {0x110E, "Cannot decompress using declared algorithm"}, - {0x110F, "Error reading UPC/EAN number"}, - {0x1110, "Error reading ISRC number"}, - {0x1111, "Read error - loss of streaming"}, - {0x1112, "Auxiliary memory read error"}, - {0x1113, "Read error - failed retransmission request"}, - {0x1114, "Read error - lba marked bad by application client"}, - {0x1115, "Write after sanitize required"}, - - {0x1200, "Address mark not found for id field"}, - - {0x1300, "Address mark not found for data field"}, - - {0x1400, "Recorded entity not found"}, - {0x1401, "Record not found"}, - {0x1402, "Filemark or setmark not found"}, - {0x1403, "End-of-data not found"}, - {0x1404, "Block sequence error"}, - {0x1405, "Record not found - recommend reassignment"}, - {0x1406, "Record not found - data auto-reallocated"}, - {0x1407, "Locate operation failure"}, - - {0x1500, "Random positioning error"}, - {0x1501, "Mechanical positioning error"}, - {0x1502, "Positioning error detected by read of medium"}, - - {0x1600, "Data synchronization mark error"}, - {0x1601, "Data sync error - data rewritten"}, - {0x1602, "Data sync error - recommend rewrite"}, - {0x1603, "Data sync error - data auto-reallocated"}, - {0x1604, "Data sync error - recommend reassignment"}, - - {0x1700, "Recovered data with no error correction applied"}, - {0x1701, "Recovered data with retries"}, - {0x1702, "Recovered data with positive head offset"}, - {0x1703, "Recovered data with negative head offset"}, - {0x1704, "Recovered data with retries and/or circ applied"}, - {0x1705, "Recovered data using previous sector id"}, - {0x1706, "Recovered data without ECC - data auto-reallocated"}, - {0x1707, "Recovered data without ECC - recommend reassignment"}, - {0x1708, "Recovered data without ECC - recommend rewrite"}, - {0x1709, "Recovered data without ECC - data rewritten"}, - - {0x1800, "Recovered data with error correction applied"}, - {0x1801, "Recovered data with error corr. & retries applied"}, - {0x1802, "Recovered data - data auto-reallocated"}, - {0x1803, "Recovered data with CIRC"}, - {0x1804, "Recovered data with L-EC"}, - {0x1805, "Recovered data - recommend reassignment"}, - {0x1806, "Recovered data - recommend rewrite"}, - {0x1807, "Recovered data with ECC - data rewritten"}, - {0x1808, "Recovered data with linking"}, - - {0x1900, "Defect list error"}, - {0x1901, "Defect list not available"}, - {0x1902, "Defect list error in primary list"}, - {0x1903, "Defect list error in grown list"}, - - {0x1A00, "Parameter list length error"}, - - {0x1B00, "Synchronous data transfer error"}, - - {0x1C00, "Defect list not found"}, - {0x1C01, "Primary defect list not found"}, - {0x1C02, "Grown defect list not found"}, - - {0x1D00, "Miscompare during verify operation"}, - {0x1D01, "Miscompare verify of unmapped LBA"}, - - {0x1E00, "Recovered id with ECC correction"}, - - {0x1F00, "Partial defect list transfer"}, - - {0x2000, "Invalid command operation code"}, - {0x2001, "Access denied - initiator pending-enrolled"}, - {0x2002, "Access denied - no access rights"}, - {0x2003, "Access denied - invalid mgmt id key"}, - {0x2004, "Illegal command while in write capable state"}, - {0x2005, "Obsolete"}, - {0x2006, "Illegal command while in explicit address mode"}, - {0x2007, "Illegal command while in implicit address mode"}, - {0x2008, "Access denied - enrollment conflict"}, - {0x2009, "Access denied - invalid LU identifier"}, - {0x200A, "Access denied - invalid proxy token"}, - {0x200B, "Access denied - ACL LUN conflict"}, - {0x200C, "Illegal command when not in append-only mode"}, - - {0x2100, "Logical block address out of range"}, - {0x2101, "Invalid element address"}, - {0x2102, "Invalid address for write"}, - {0x2103, "Invalid write crossing layer jump"}, - {0x2104, "Unaligned write command"}, - {0x2105, "Write boundary violation"}, - {0x2106, "Attempt to read invalid data"}, - {0x2107, "Read boundary violation"}, - - {0x2200, "Illegal function (use 20 00, 24 00, or 26 00)"}, - - {0x2300, "Invalid token operation, cause not reportable"}, - {0x2301, "Invalid token operation, unsupported token type"}, - {0x2302, "Invalid token operation, remote token usage not supported"}, - {0x2303, "Invalid token operation, remote rod token creation not supported"}, - {0x2304, "Invalid token operation, token unknown"}, - {0x2305, "Invalid token operation, token corrupt"}, - {0x2306, "Invalid token operation, token revoked"}, - {0x2307, "Invalid token operation, token expired"}, - {0x2308, "Invalid token operation, token cancelled"}, - {0x2309, "Invalid token operation, token deleted"}, - {0x230A, "Invalid token operation, invalid token length"}, - - {0x2400, "Invalid field in cdb"}, - {0x2401, "CDB decryption error"}, - {0x2402, "Obsolete"}, - {0x2403, "Obsolete"}, - {0x2404, "Security audit value frozen"}, - {0x2405, "Security working key frozen"}, - {0x2406, "Nonce not unique"}, - {0x2407, "Nonce timestamp out of range"}, - {0x2408, "Invalid XCDB"}, - - {0x2500, "Logical unit not supported"}, - - {0x2600, "Invalid field in parameter list"}, - {0x2601, "Parameter not supported"}, - {0x2602, "Parameter value invalid"}, - {0x2603, "Threshold parameters not supported"}, - {0x2604, "Invalid release of persistent reservation"}, - {0x2605, "Data decryption error"}, - {0x2606, "Too many target descriptors"}, - {0x2607, "Unsupported target descriptor type code"}, - {0x2608, "Too many segment descriptors"}, - {0x2609, "Unsupported segment descriptor type code"}, - {0x260A, "Unexpected inexact segment"}, - {0x260B, "Inline data length exceeded"}, - {0x260C, "Invalid operation for copy source or destination"}, - {0x260D, "Copy segment granularity violation"}, - {0x260E, "Invalid parameter while port is enabled"}, - {0x260F, "Invalid data-out buffer integrity check value"}, - {0x2610, "Data decryption key fail limit reached"}, - {0x2611, "Incomplete key-associated data set"}, - {0x2612, "Vendor specific key reference not found"}, - - {0x2700, "Write protected"}, - {0x2701, "Hardware write protected"}, - {0x2702, "Logical unit software write protected"}, - {0x2703, "Associated write protect"}, - {0x2704, "Persistent write protect"}, - {0x2705, "Permanent write protect"}, - {0x2706, "Conditional write protect"}, - {0x2707, "Space allocation failed write protect"}, - {0x2708, "Zone is read only"}, - - {0x2800, "Not ready to ready change, medium may have changed"}, - {0x2801, "Import or export element accessed"}, - {0x2802, "Format-layer may have changed"}, - {0x2803, "Import/export element accessed, medium changed"}, - - {0x2900, "Power on, reset, or bus device reset occurred"}, - {0x2901, "Power on occurred"}, - {0x2902, "Scsi bus reset occurred"}, - {0x2903, "Bus device reset function occurred"}, - {0x2904, "Device internal reset"}, - {0x2905, "Transceiver mode changed to single-ended"}, - {0x2906, "Transceiver mode changed to lvd"}, - {0x2907, "I_T nexus loss occurred"}, - - {0x2A00, "Parameters changed"}, - {0x2A01, "Mode parameters changed"}, - {0x2A02, "Log parameters changed"}, - {0x2A03, "Reservations preempted"}, - {0x2A04, "Reservations released"}, - {0x2A05, "Registrations preempted"}, - {0x2A06, "Asymmetric access state changed"}, - {0x2A07, "Implicit asymmetric access state transition failed"}, - {0x2A08, "Priority changed"}, - {0x2A09, "Capacity data has changed"}, - {0x2A0A, "Error history I_T nexus cleared"}, - {0x2A0B, "Error history snapshot released"}, - {0x2A0C, "Error recovery attributes have changed"}, - {0x2A0D, "Data encryption capabilities changed"}, - {0x2A10, "Timestamp changed"}, - {0x2A11, "Data encryption parameters changed by another i_t nexus"}, - {0x2A12, "Data encryption parameters changed by vendor specific event"}, - {0x2A13, "Data encryption key instance counter has changed"}, - {0x2A14, "SA creation capabilities data has changed"}, - {0x2A15, "Medium removal prevention preempted"}, - - {0x2B00, "Copy cannot execute since host cannot disconnect"}, - - {0x2C00, "Command sequence error"}, - {0x2C01, "Too many windows specified"}, - {0x2C02, "Invalid combination of windows specified"}, - {0x2C03, "Current program area is not empty"}, - {0x2C04, "Current program area is empty"}, - {0x2C05, "Illegal power condition request"}, - {0x2C06, "Persistent prevent conflict"}, - {0x2C07, "Previous busy status"}, - {0x2C08, "Previous task set full status"}, - {0x2C09, "Previous reservation conflict status"}, - {0x2C0A, "Partition or collection contains user objects"}, - {0x2C0B, "Not reserved"}, - {0x2C0C, "Orwrite generation does not match"}, - {0x2C0D, "Reset write pointer not allowed"}, - {0x2C0E, "Zone is offline"}, - - {0x2D00, "Overwrite error on update in place"}, - - {0x2E00, "Insufficient time for operation"}, - {0x2E01, "Command timeout before processing"}, - {0x2E02, "Command timeout during processing"}, - {0x2E03, "Command timeout during processing due to error recovery"}, - - {0x2F00, "Commands cleared by another initiator"}, - {0x2F01, "Commands cleared by power loss notification"}, - {0x2F02, "Commands cleared by device server"}, - {0x2F03, "Some commands cleared by queuing layer event"}, - - {0x3000, "Incompatible medium installed"}, - {0x3001, "Cannot read medium - unknown format"}, - {0x3002, "Cannot read medium - incompatible format"}, - {0x3003, "Cleaning cartridge installed"}, - {0x3004, "Cannot write medium - unknown format"}, - {0x3005, "Cannot write medium - incompatible format"}, - {0x3006, "Cannot format medium - incompatible medium"}, - {0x3007, "Cleaning failure"}, - {0x3008, "Cannot write - application code mismatch"}, - {0x3009, "Current session not fixated for append"}, - {0x300A, "Cleaning request rejected"}, - {0x300C, "WORM medium - overwrite attempted"}, - {0x300D, "WORM medium - integrity check"}, - {0x3010, "Medium not formatted"}, - {0x3011, "Incompatible volume type"}, - {0x3012, "Incompatible volume qualifier"}, - {0x3013, "Cleaning volume expired"}, - - {0x3100, "Medium format corrupted"}, - {0x3101, "Format command failed"}, - {0x3102, "Zoned formatting failed due to spare linking"}, - {0x3103, "Sanitize command failed"}, - - {0x3200, "No defect spare location available"}, - {0x3201, "Defect list update failure"}, - - {0x3300, "Tape length error"}, - - {0x3400, "Enclosure failure"}, - - {0x3500, "Enclosure services failure"}, - {0x3501, "Unsupported enclosure function"}, - {0x3502, "Enclosure services unavailable"}, - {0x3503, "Enclosure services transfer failure"}, - {0x3504, "Enclosure services transfer refused"}, - {0x3505, "Enclosure services checksum error"}, - - {0x3600, "Ribbon, ink, or toner failure"}, - - {0x3700, "Rounded parameter"}, - - {0x3800, "Event status notification"}, - {0x3802, "Esn - power management class event"}, - {0x3804, "Esn - media class event"}, - {0x3806, "Esn - device busy class event"}, - {0x3807, "Thin Provisioning soft threshold reached"}, - - {0x3900, "Saving parameters not supported"}, - - {0x3A00, "Medium not present"}, - {0x3A01, "Medium not present - tray closed"}, - {0x3A02, "Medium not present - tray open"}, - {0x3A03, "Medium not present - loadable"}, - {0x3A04, "Medium not present - medium auxiliary memory accessible"}, - - {0x3B00, "Sequential positioning error"}, - {0x3B01, "Tape position error at beginning-of-medium"}, - {0x3B02, "Tape position error at end-of-medium"}, - {0x3B03, "Tape or electronic vertical forms unit not ready"}, - {0x3B04, "Slew failure"}, - {0x3B05, "Paper jam"}, - {0x3B06, "Failed to sense top-of-form"}, - {0x3B07, "Failed to sense bottom-of-form"}, - {0x3B08, "Reposition error"}, - {0x3B09, "Read past end of medium"}, - {0x3B0A, "Read past beginning of medium"}, - {0x3B0B, "Position past end of medium"}, - {0x3B0C, "Position past beginning of medium"}, - {0x3B0D, "Medium destination element full"}, - {0x3B0E, "Medium source element empty"}, - {0x3B0F, "End of medium reached"}, - {0x3B11, "Medium magazine not accessible"}, - {0x3B12, "Medium magazine removed"}, - {0x3B13, "Medium magazine inserted"}, - {0x3B14, "Medium magazine locked"}, - {0x3B15, "Medium magazine unlocked"}, - {0x3B16, "Mechanical positioning or changer error"}, - {0x3B17, "Read past end of user object"}, - {0x3B18, "Element disabled"}, - {0x3B19, "Element enabled"}, - {0x3B1A, "Data transfer device removed"}, - {0x3B1B, "Data transfer device inserted"}, - {0x3B1C, "Too many logical objects on partition to support operation"}, - - {0x3D00, "Invalid bits in identify message"}, - - {0x3E00, "Logical unit has not self-configured yet"}, - {0x3E01, "Logical unit failure"}, - {0x3E02, "Timeout on logical unit"}, - {0x3E03, "Logical unit failed self-test"}, - {0x3E04, "Logical unit unable to update self-test log"}, - - {0x3F00, "Target operating conditions have changed"}, - {0x3F01, "Microcode has been changed"}, - {0x3F02, "Changed operating definition"}, - {0x3F03, "Inquiry data has changed"}, - {0x3F04, "Component device attached"}, - {0x3F05, "Device identifier changed"}, - {0x3F06, "Redundancy group created or modified"}, - {0x3F07, "Redundancy group deleted"}, - {0x3F08, "Spare created or modified"}, - {0x3F09, "Spare deleted"}, - {0x3F0A, "Volume set created or modified"}, - {0x3F0B, "Volume set deleted"}, - {0x3F0C, "Volume set deassigned"}, - {0x3F0D, "Volume set reassigned"}, - {0x3F0E, "Reported luns data has changed"}, - {0x3F0F, "Echo buffer overwritten"}, - {0x3F10, "Medium loadable"}, - {0x3F11, "Medium auxiliary memory accessible"}, - {0x3F12, "iSCSI IP address added"}, - {0x3F13, "iSCSI IP address removed"}, - {0x3F14, "iSCSI IP address changed"}, - {0x3F15, "Inspect referrals sense descriptors"}, - {0x3F16, "Microcode has been changed without reset"}, -/* - * {0x40NN, "Ram failure"}, - * {0x40NN, "Diagnostic failure on component nn"}, - * {0x41NN, "Data path failure"}, - * {0x42NN, "Power-on or self-test failure"}, - */ - {0x4300, "Message error"}, - - {0x4400, "Internal target failure"}, - {0x4401, "Persistent reservation information lost"}, - {0x4471, "ATA device failed set features"}, - - {0x4500, "Select or reselect failure"}, - - {0x4600, "Unsuccessful soft reset"}, - - {0x4700, "Scsi parity error"}, - {0x4701, "Data phase CRC error detected"}, - {0x4702, "Scsi parity error detected during st data phase"}, - {0x4703, "Information unit iuCRC error detected"}, - {0x4704, "Asynchronous information protection error detected"}, - {0x4705, "Protocol service CRC error"}, - {0x4706, "Phy test function in progress"}, - {0x477f, "Some commands cleared by iSCSI Protocol event"}, - - {0x4800, "Initiator detected error message received"}, - - {0x4900, "Invalid message error"}, - - {0x4A00, "Command phase error"}, - - {0x4B00, "Data phase error"}, - {0x4B01, "Invalid target port transfer tag received"}, - {0x4B02, "Too much write data"}, - {0x4B03, "Ack/nak timeout"}, - {0x4B04, "Nak received"}, - {0x4B05, "Data offset error"}, - {0x4B06, "Initiator response timeout"}, - {0x4B07, "Connection lost"}, - {0x4B08, "Data-in buffer overflow - data buffer size"}, - {0x4B09, "Data-in buffer overflow - data buffer descriptor area"}, - {0x4B0A, "Data-in buffer error"}, - {0x4B0B, "Data-out buffer overflow - data buffer size"}, - {0x4B0C, "Data-out buffer overflow - data buffer descriptor area"}, - {0x4B0D, "Data-out buffer error"}, - {0x4B0E, "PCIe fabric error"}, - {0x4B0F, "PCIe completion timeout"}, - {0x4B10, "PCIe completer abort"}, - {0x4B11, "PCIe poisoned tlp received"}, - {0x4B12, "PCIe eCRC check failed"}, - {0x4B13, "PCIe unsupported request"}, - {0x4B14, "PCIe acs violation"}, - {0x4B15, "PCIe tlp prefix blocked"}, - - {0x4C00, "Logical unit failed self-configuration"}, -/* - * {0x4DNN, "Tagged overlapped commands (nn = queue tag)"}, - */ - {0x4E00, "Overlapped commands attempted"}, - - {0x5000, "Write append error"}, - {0x5001, "Write append position error"}, - {0x5002, "Position error related to timing"}, - - {0x5100, "Erase failure"}, - {0x5101, "Erase failure - incomplete erase operation detected"}, - - {0x5200, "Cartridge fault"}, - - {0x5300, "Media load or eject failed"}, - {0x5301, "Unload tape failure"}, - {0x5302, "Medium removal prevented"}, - {0x5303, "Medium removal prevented by data transfer element"}, - {0x5304, "Medium thread or unthread failure"}, - {0x5305, "Volume identifier invalid"}, - {0x5306, "Volume identifier missing"}, - {0x5307, "Duplicate volume identifier"}, - {0x5308, "Element status unknown"}, - {0x5309, "Data transfer device error - load failed"}, - {0x530a, "Data transfer device error - unload failed"}, - {0x530b, "Data transfer device error - unload missing"}, - {0x530c, "Data transfer device error - eject failed"}, - {0x530d, "Data transfer device error - library communication failed"}, - - {0x5400, "Scsi to host system interface failure"}, - - {0x5500, "System resource failure"}, - {0x5501, "System buffer full"}, - {0x5502, "Insufficient reservation resources"}, - {0x5503, "Insufficient resources"}, - {0x5504, "Insufficient registration resources"}, - {0x5505, "Insufficient access control resources"}, - {0x5506, "Auxiliary memory out of space"}, - {0x5507, "Quota error"}, - {0x5508, "Maximum number of supplemental decryption keys exceeded"}, - {0x5509, "Medium auxiliary memory not accessible"}, - {0x550A, "Data currently unavailable"}, - {0x550B, "Insufficient power for operation"}, - {0x550C, "Insufficient resources to create rod"}, - {0x550D, "Insufficient resources to create rod token"}, - {0x550E, "Insufficient zone resources"}, - - {0x5700, "Unable to recover table-of-contents"}, - - {0x5800, "Generation does not exist"}, - - {0x5900, "Updated block read"}, - - {0x5A00, "Operator request or state change input"}, - {0x5A01, "Operator medium removal request"}, - {0x5A02, "Operator selected write protect"}, - {0x5A03, "Operator selected write permit"}, - - {0x5B00, "Log exception"}, - {0x5B01, "Threshold condition met"}, - {0x5B02, "Log counter at maximum"}, - {0x5B03, "Log list codes exhausted"}, - - {0x5C00, "Rpl status change"}, - {0x5C01, "Spindles synchronized"}, - {0x5C02, "Spindles not synchronized"}, - - {0x5D00, "Failure prediction threshold exceeded"}, - {0x5D01, "Media failure prediction threshold exceeded"}, - {0x5D02, "Logical unit failure prediction threshold exceeded"}, - {0x5D03, "Spare area exhaustion prediction threshold exceeded"}, - {0x5D10, "Hardware impending failure general hard drive failure"}, - {0x5D11, "Hardware impending failure drive error rate too high"}, - {0x5D12, "Hardware impending failure data error rate too high"}, - {0x5D13, "Hardware impending failure seek error rate too high"}, - {0x5D14, "Hardware impending failure too many block reassigns"}, - {0x5D15, "Hardware impending failure access times too high"}, - {0x5D16, "Hardware impending failure start unit times too high"}, - {0x5D17, "Hardware impending failure channel parametrics"}, - {0x5D18, "Hardware impending failure controller detected"}, - {0x5D19, "Hardware impending failure throughput performance"}, - {0x5D1A, "Hardware impending failure seek time performance"}, - {0x5D1B, "Hardware impending failure spin-up retry count"}, - {0x5D1C, "Hardware impending failure drive calibration retry count"}, - {0x5D20, "Controller impending failure general hard drive failure"}, - {0x5D21, "Controller impending failure drive error rate too high"}, - {0x5D22, "Controller impending failure data error rate too high"}, - {0x5D23, "Controller impending failure seek error rate too high"}, - {0x5D24, "Controller impending failure too many block reassigns"}, - {0x5D25, "Controller impending failure access times too high"}, - {0x5D26, "Controller impending failure start unit times too high"}, - {0x5D27, "Controller impending failure channel parametrics"}, - {0x5D28, "Controller impending failure controller detected"}, - {0x5D29, "Controller impending failure throughput performance"}, - {0x5D2A, "Controller impending failure seek time performance"}, - {0x5D2B, "Controller impending failure spin-up retry count"}, - {0x5D2C, "Controller impending failure drive calibration retry count"}, - {0x5D30, "Data channel impending failure general hard drive failure"}, - {0x5D31, "Data channel impending failure drive error rate too high"}, - {0x5D32, "Data channel impending failure data error rate too high"}, - {0x5D33, "Data channel impending failure seek error rate too high"}, - {0x5D34, "Data channel impending failure too many block reassigns"}, - {0x5D35, "Data channel impending failure access times too high"}, - {0x5D36, "Data channel impending failure start unit times too high"}, - {0x5D37, "Data channel impending failure channel parametrics"}, - {0x5D38, "Data channel impending failure controller detected"}, - {0x5D39, "Data channel impending failure throughput performance"}, - {0x5D3A, "Data channel impending failure seek time performance"}, - {0x5D3B, "Data channel impending failure spin-up retry count"}, - {0x5D3C, "Data channel impending failure drive calibration retry count"}, - {0x5D40, "Servo impending failure general hard drive failure"}, - {0x5D41, "Servo impending failure drive error rate too high"}, - {0x5D42, "Servo impending failure data error rate too high"}, - {0x5D43, "Servo impending failure seek error rate too high"}, - {0x5D44, "Servo impending failure too many block reassigns"}, - {0x5D45, "Servo impending failure access times too high"}, - {0x5D46, "Servo impending failure start unit times too high"}, - {0x5D47, "Servo impending failure channel parametrics"}, - {0x5D48, "Servo impending failure controller detected"}, - {0x5D49, "Servo impending failure throughput performance"}, - {0x5D4A, "Servo impending failure seek time performance"}, - {0x5D4B, "Servo impending failure spin-up retry count"}, - {0x5D4C, "Servo impending failure drive calibration retry count"}, - {0x5D50, "Spindle impending failure general hard drive failure"}, - {0x5D51, "Spindle impending failure drive error rate too high"}, - {0x5D52, "Spindle impending failure data error rate too high"}, - {0x5D53, "Spindle impending failure seek error rate too high"}, - {0x5D54, "Spindle impending failure too many block reassigns"}, - {0x5D55, "Spindle impending failure access times too high"}, - {0x5D56, "Spindle impending failure start unit times too high"}, - {0x5D57, "Spindle impending failure channel parametrics"}, - {0x5D58, "Spindle impending failure controller detected"}, - {0x5D59, "Spindle impending failure throughput performance"}, - {0x5D5A, "Spindle impending failure seek time performance"}, - {0x5D5B, "Spindle impending failure spin-up retry count"}, - {0x5D5C, "Spindle impending failure drive calibration retry count"}, - {0x5D60, "Firmware impending failure general hard drive failure"}, - {0x5D61, "Firmware impending failure drive error rate too high"}, - {0x5D62, "Firmware impending failure data error rate too high"}, - {0x5D63, "Firmware impending failure seek error rate too high"}, - {0x5D64, "Firmware impending failure too many block reassigns"}, - {0x5D65, "Firmware impending failure access times too high"}, - {0x5D66, "Firmware impending failure start unit times too high"}, - {0x5D67, "Firmware impending failure channel parametrics"}, - {0x5D68, "Firmware impending failure controller detected"}, - {0x5D69, "Firmware impending failure throughput performance"}, - {0x5D6A, "Firmware impending failure seek time performance"}, - {0x5D6B, "Firmware impending failure spin-up retry count"}, - {0x5D6C, "Firmware impending failure drive calibration retry count"}, - {0x5DFF, "Failure prediction threshold exceeded (false)"}, - - {0x5E00, "Low power condition on"}, - {0x5E01, "Idle condition activated by timer"}, - {0x5E02, "Standby condition activated by timer"}, - {0x5E03, "Idle condition activated by command"}, - {0x5E04, "Standby condition activated by command"}, - {0x5E05, "Idle_b condition activated by timer"}, - {0x5E06, "Idle_b condition activated by command"}, - {0x5E07, "Idle_c condition activated by timer"}, - {0x5E08, "Idle_c condition activated by command"}, - {0x5E09, "Standby_y condition activated by timer"}, - {0x5E0A, "Standby_y condition activated by command"}, - {0x5E41, "Power state change to active"}, - {0x5E42, "Power state change to idle"}, - {0x5E43, "Power state change to standby"}, - {0x5E45, "Power state change to sleep"}, - {0x5E47, "Power state change to device control"}, - - {0x6000, "Lamp failure"}, - - {0x6100, "Video acquisition error"}, - {0x6101, "Unable to acquire video"}, - {0x6102, "Out of focus"}, - - {0x6200, "Scan head positioning error"}, - - {0x6300, "End of user area encountered on this track"}, - {0x6301, "Packet does not fit in available space"}, - - {0x6400, "Illegal mode for this track"}, - {0x6401, "Invalid packet size"}, - - {0x6500, "Voltage fault"}, - - {0x6600, "Automatic document feeder cover up"}, - {0x6601, "Automatic document feeder lift up"}, - {0x6602, "Document jam in automatic document feeder"}, - {0x6603, "Document miss feed automatic in document feeder"}, - - {0x6700, "Configuration failure"}, - {0x6701, "Configuration of incapable logical units failed"}, - {0x6702, "Add logical unit failed"}, - {0x6703, "Modification of logical unit failed"}, - {0x6704, "Exchange of logical unit failed"}, - {0x6705, "Remove of logical unit failed"}, - {0x6706, "Attachment of logical unit failed"}, - {0x6707, "Creation of logical unit failed"}, - {0x6708, "Assign failure occurred"}, - {0x6709, "Multiply assigned logical unit"}, - {0x670A, "Set target port groups command failed"}, - {0x670B, "ATA device feature not enabled"}, - - {0x6800, "Logical unit not configured"}, - {0x6801, "Subsidiary logical unit not configured"}, - - {0x6900, "Data loss on logical unit"}, - {0x6901, "Multiple logical unit failures"}, - {0x6902, "Parity/data mismatch"}, - - {0x6A00, "Informational, refer to log"}, - - {0x6B00, "State change has occurred"}, - {0x6B01, "Redundancy level got better"}, - {0x6B02, "Redundancy level got worse"}, - - {0x6C00, "Rebuild failure occurred"}, - - {0x6D00, "Recalculate failure occurred"}, - - {0x6E00, "Command to logical unit failed"}, - - {0x6F00, "Copy protection key exchange failure - authentication failure"}, - {0x6F01, "Copy protection key exchange failure - key not present"}, - {0x6F02, "Copy protection key exchange failure - key not established"}, - {0x6F03, "Read of scrambled sector without authentication"}, - {0x6F04, "Media region code is mismatched to logical unit region"}, - {0x6F05, "Drive region must be permanent/region reset count error"}, - {0x6F06, "Insufficient block count for binding nonce recording"}, - {0x6F07, "Conflict in binding nonce recording"}, -/* - * {0x70NN, "Decompression exception short algorithm id of nn"}, - */ - {0x7100, "Decompression exception long algorithm id"}, - - {0x7200, "Session fixation error"}, - {0x7201, "Session fixation error writing lead-in"}, - {0x7202, "Session fixation error writing lead-out"}, - {0x7203, "Session fixation error - incomplete track in session"}, - {0x7204, "Empty or partially written reserved track"}, - {0x7205, "No more track reservations allowed"}, - {0x7206, "RMZ extension is not allowed"}, - {0x7207, "No more test zone extensions are allowed"}, - - {0x7300, "Cd control error"}, - {0x7301, "Power calibration area almost full"}, - {0x7302, "Power calibration area is full"}, - {0x7303, "Power calibration area error"}, - {0x7304, "Program memory area update failure"}, - {0x7305, "Program memory area is full"}, - {0x7306, "RMA/PMA is almost full"}, - {0x7310, "Current power calibration area almost full"}, - {0x7311, "Current power calibration area is full"}, - {0x7317, "RDZ is full"}, - - {0x7400, "Security error"}, - {0x7401, "Unable to decrypt data"}, - {0x7402, "Unencrypted data encountered while decrypting"}, - {0x7403, "Incorrect data encryption key"}, - {0x7404, "Cryptographic integrity validation failed"}, - {0x7405, "Error decrypting data"}, - {0x7406, "Unknown signature verification key"}, - {0x7407, "Encryption parameters not useable"}, - {0x7408, "Digital signature validation failure"}, - {0x7409, "Encryption mode mismatch on read"}, - {0x740A, "Encrypted block not raw read enabled"}, - {0x740B, "Incorrect Encryption parameters"}, - {0x740C, "Unable to decrypt parameter list"}, - {0x740D, "Encryption algorithm disabled"}, - {0x7410, "SA creation parameter value invalid"}, - {0x7411, "SA creation parameter value rejected"}, - {0x7412, "Invalid SA usage"}, - {0x7421, "Data Encryption configuration prevented"}, - {0x7430, "SA creation parameter not supported"}, - {0x7440, "Authentication failed"}, - {0x7461, "External data encryption key manager access error"}, - {0x7462, "External data encryption key manager error"}, - {0x7463, "External data encryption key not found"}, - {0x7464, "External data encryption request not authorized"}, - {0x746E, "External data encryption control timeout"}, - {0x746F, "External data encryption control error"}, - {0x7471, "Logical unit access not authorized"}, - {0x7479, "Security conflict in translated device"}, - +#define SENSE_CODE(c, s) {c, s}, +#include "sense_codes.h" +#undef SENSE_CODE {0, NULL} }; diff --git a/drivers/scsi/sense_codes.h b/drivers/scsi/sense_codes.h new file mode 100644 index 000000000000..e4e1dccd1f2f --- /dev/null +++ b/drivers/scsi/sense_codes.h @@ -0,0 +1,826 @@ +/* + * The canonical list of T10 Additional Sense Codes is available at: + * http://www.t10.org/lists/asc-num.txt [most recent: 20141221] + */ + +SENSE_CODE(0x0000, "No additional sense information") +SENSE_CODE(0x0001, "Filemark detected") +SENSE_CODE(0x0002, "End-of-partition/medium detected") +SENSE_CODE(0x0003, "Setmark detected") +SENSE_CODE(0x0004, "Beginning-of-partition/medium detected") +SENSE_CODE(0x0005, "End-of-data detected") +SENSE_CODE(0x0006, "I/O process terminated") +SENSE_CODE(0x0007, "Programmable early warning detected") +SENSE_CODE(0x0011, "Audio play operation in progress") +SENSE_CODE(0x0012, "Audio play operation paused") +SENSE_CODE(0x0013, "Audio play operation successfully completed") +SENSE_CODE(0x0014, "Audio play operation stopped due to error") +SENSE_CODE(0x0015, "No current audio status to return") +SENSE_CODE(0x0016, "Operation in progress") +SENSE_CODE(0x0017, "Cleaning requested") +SENSE_CODE(0x0018, "Erase operation in progress") +SENSE_CODE(0x0019, "Locate operation in progress") +SENSE_CODE(0x001A, "Rewind operation in progress") +SENSE_CODE(0x001B, "Set capacity operation in progress") +SENSE_CODE(0x001C, "Verify operation in progress") +SENSE_CODE(0x001D, "ATA pass through information available") +SENSE_CODE(0x001E, "Conflicting SA creation request") +SENSE_CODE(0x001F, "Logical unit transitioning to another power condition") +SENSE_CODE(0x0020, "Extended copy information available") +SENSE_CODE(0x0021, "Atomic command aborted due to ACA") + +SENSE_CODE(0x0100, "No index/sector signal") + +SENSE_CODE(0x0200, "No seek complete") + +SENSE_CODE(0x0300, "Peripheral device write fault") +SENSE_CODE(0x0301, "No write current") +SENSE_CODE(0x0302, "Excessive write errors") + +SENSE_CODE(0x0400, "Logical unit not ready, cause not reportable") +SENSE_CODE(0x0401, "Logical unit is in process of becoming ready") +SENSE_CODE(0x0402, "Logical unit not ready, initializing command required") +SENSE_CODE(0x0403, "Logical unit not ready, manual intervention required") +SENSE_CODE(0x0404, "Logical unit not ready, format in progress") +SENSE_CODE(0x0405, "Logical unit not ready, rebuild in progress") +SENSE_CODE(0x0406, "Logical unit not ready, recalculation in progress") +SENSE_CODE(0x0407, "Logical unit not ready, operation in progress") +SENSE_CODE(0x0408, "Logical unit not ready, long write in progress") +SENSE_CODE(0x0409, "Logical unit not ready, self-test in progress") +SENSE_CODE(0x040A, "Logical unit not accessible, asymmetric access state transition") +SENSE_CODE(0x040B, "Logical unit not accessible, target port in standby state") +SENSE_CODE(0x040C, "Logical unit not accessible, target port in unavailable state") +SENSE_CODE(0x040D, "Logical unit not ready, structure check required") +SENSE_CODE(0x040E, "Logical unit not ready, security session in progress") +SENSE_CODE(0x0410, "Logical unit not ready, auxiliary memory not accessible") +SENSE_CODE(0x0411, "Logical unit not ready, notify (enable spinup) required") +SENSE_CODE(0x0412, "Logical unit not ready, offline") +SENSE_CODE(0x0413, "Logical unit not ready, SA creation in progress") +SENSE_CODE(0x0414, "Logical unit not ready, space allocation in progress") +SENSE_CODE(0x0415, "Logical unit not ready, robotics disabled") +SENSE_CODE(0x0416, "Logical unit not ready, configuration required") +SENSE_CODE(0x0417, "Logical unit not ready, calibration required") +SENSE_CODE(0x0418, "Logical unit not ready, a door is open") +SENSE_CODE(0x0419, "Logical unit not ready, operating in sequential mode") +SENSE_CODE(0x041A, "Logical unit not ready, start stop unit command in progress") +SENSE_CODE(0x041B, "Logical unit not ready, sanitize in progress") +SENSE_CODE(0x041C, "Logical unit not ready, additional power use not yet granted") +SENSE_CODE(0x041D, "Logical unit not ready, configuration in progress") +SENSE_CODE(0x041E, "Logical unit not ready, microcode activation required") +SENSE_CODE(0x041F, "Logical unit not ready, microcode download required") +SENSE_CODE(0x0420, "Logical unit not ready, logical unit reset required") +SENSE_CODE(0x0421, "Logical unit not ready, hard reset required") +SENSE_CODE(0x0422, "Logical unit not ready, power cycle required") + +SENSE_CODE(0x0500, "Logical unit does not respond to selection") + +SENSE_CODE(0x0600, "No reference position found") + +SENSE_CODE(0x0700, "Multiple peripheral devices selected") + +SENSE_CODE(0x0800, "Logical unit communication failure") +SENSE_CODE(0x0801, "Logical unit communication time-out") +SENSE_CODE(0x0802, "Logical unit communication parity error") +SENSE_CODE(0x0803, "Logical unit communication CRC error (Ultra-DMA/32)") +SENSE_CODE(0x0804, "Unreachable copy target") + +SENSE_CODE(0x0900, "Track following error") +SENSE_CODE(0x0901, "Tracking servo failure") +SENSE_CODE(0x0902, "Focus servo failure") +SENSE_CODE(0x0903, "Spindle servo failure") +SENSE_CODE(0x0904, "Head select fault") +SENSE_CODE(0x0905, "Vibration induced tracking error") + +SENSE_CODE(0x0A00, "Error log overflow") + +SENSE_CODE(0x0B00, "Warning") +SENSE_CODE(0x0B01, "Warning - specified temperature exceeded") +SENSE_CODE(0x0B02, "Warning - enclosure degraded") +SENSE_CODE(0x0B03, "Warning - background self-test failed") +SENSE_CODE(0x0B04, "Warning - background pre-scan detected medium error") +SENSE_CODE(0x0B05, "Warning - background medium scan detected medium error") +SENSE_CODE(0x0B06, "Warning - non-volatile cache now volatile") +SENSE_CODE(0x0B07, "Warning - degraded power to non-volatile cache") +SENSE_CODE(0x0B08, "Warning - power loss expected") +SENSE_CODE(0x0B09, "Warning - device statistics notification active") + +SENSE_CODE(0x0C00, "Write error") +SENSE_CODE(0x0C01, "Write error - recovered with auto reallocation") +SENSE_CODE(0x0C02, "Write error - auto reallocation failed") +SENSE_CODE(0x0C03, "Write error - recommend reassignment") +SENSE_CODE(0x0C04, "Compression check miscompare error") +SENSE_CODE(0x0C05, "Data expansion occurred during compression") +SENSE_CODE(0x0C06, "Block not compressible") +SENSE_CODE(0x0C07, "Write error - recovery needed") +SENSE_CODE(0x0C08, "Write error - recovery failed") +SENSE_CODE(0x0C09, "Write error - loss of streaming") +SENSE_CODE(0x0C0A, "Write error - padding blocks added") +SENSE_CODE(0x0C0B, "Auxiliary memory write error") +SENSE_CODE(0x0C0C, "Write error - unexpected unsolicited data") +SENSE_CODE(0x0C0D, "Write error - not enough unsolicited data") +SENSE_CODE(0x0C0E, "Multiple write errors") +SENSE_CODE(0x0C0F, "Defects in error window") +SENSE_CODE(0x0C10, "Incomplete multiple atomic write operations") + +SENSE_CODE(0x0D00, "Error detected by third party temporary initiator") +SENSE_CODE(0x0D01, "Third party device failure") +SENSE_CODE(0x0D02, "Copy target device not reachable") +SENSE_CODE(0x0D03, "Incorrect copy target device type") +SENSE_CODE(0x0D04, "Copy target device data underrun") +SENSE_CODE(0x0D05, "Copy target device data overrun") + +SENSE_CODE(0x0E00, "Invalid information unit") +SENSE_CODE(0x0E01, "Information unit too short") +SENSE_CODE(0x0E02, "Information unit too long") +SENSE_CODE(0x0E03, "Invalid field in command information unit") + +SENSE_CODE(0x1000, "Id CRC or ECC error") +SENSE_CODE(0x1001, "Logical block guard check failed") +SENSE_CODE(0x1002, "Logical block application tag check failed") +SENSE_CODE(0x1003, "Logical block reference tag check failed") +SENSE_CODE(0x1004, "Logical block protection error on recover buffered data") +SENSE_CODE(0x1005, "Logical block protection method error") + +SENSE_CODE(0x1100, "Unrecovered read error") +SENSE_CODE(0x1101, "Read retries exhausted") +SENSE_CODE(0x1102, "Error too long to correct") +SENSE_CODE(0x1103, "Multiple read errors") +SENSE_CODE(0x1104, "Unrecovered read error - auto reallocate failed") +SENSE_CODE(0x1105, "L-EC uncorrectable error") +SENSE_CODE(0x1106, "CIRC unrecovered error") +SENSE_CODE(0x1107, "Data re-synchronization error") +SENSE_CODE(0x1108, "Incomplete block read") +SENSE_CODE(0x1109, "No gap found") +SENSE_CODE(0x110A, "Miscorrected error") +SENSE_CODE(0x110B, "Unrecovered read error - recommend reassignment") +SENSE_CODE(0x110C, "Unrecovered read error - recommend rewrite the data") +SENSE_CODE(0x110D, "De-compression CRC error") +SENSE_CODE(0x110E, "Cannot decompress using declared algorithm") +SENSE_CODE(0x110F, "Error reading UPC/EAN number") +SENSE_CODE(0x1110, "Error reading ISRC number") +SENSE_CODE(0x1111, "Read error - loss of streaming") +SENSE_CODE(0x1112, "Auxiliary memory read error") +SENSE_CODE(0x1113, "Read error - failed retransmission request") +SENSE_CODE(0x1114, "Read error - lba marked bad by application client") +SENSE_CODE(0x1115, "Write after sanitize required") + +SENSE_CODE(0x1200, "Address mark not found for id field") + +SENSE_CODE(0x1300, "Address mark not found for data field") + +SENSE_CODE(0x1400, "Recorded entity not found") +SENSE_CODE(0x1401, "Record not found") +SENSE_CODE(0x1402, "Filemark or setmark not found") +SENSE_CODE(0x1403, "End-of-data not found") +SENSE_CODE(0x1404, "Block sequence error") +SENSE_CODE(0x1405, "Record not found - recommend reassignment") +SENSE_CODE(0x1406, "Record not found - data auto-reallocated") +SENSE_CODE(0x1407, "Locate operation failure") + +SENSE_CODE(0x1500, "Random positioning error") +SENSE_CODE(0x1501, "Mechanical positioning error") +SENSE_CODE(0x1502, "Positioning error detected by read of medium") + +SENSE_CODE(0x1600, "Data synchronization mark error") +SENSE_CODE(0x1601, "Data sync error - data rewritten") +SENSE_CODE(0x1602, "Data sync error - recommend rewrite") +SENSE_CODE(0x1603, "Data sync error - data auto-reallocated") +SENSE_CODE(0x1604, "Data sync error - recommend reassignment") + +SENSE_CODE(0x1700, "Recovered data with no error correction applied") +SENSE_CODE(0x1701, "Recovered data with retries") +SENSE_CODE(0x1702, "Recovered data with positive head offset") +SENSE_CODE(0x1703, "Recovered data with negative head offset") +SENSE_CODE(0x1704, "Recovered data with retries and/or circ applied") +SENSE_CODE(0x1705, "Recovered data using previous sector id") +SENSE_CODE(0x1706, "Recovered data without ECC - data auto-reallocated") +SENSE_CODE(0x1707, "Recovered data without ECC - recommend reassignment") +SENSE_CODE(0x1708, "Recovered data without ECC - recommend rewrite") +SENSE_CODE(0x1709, "Recovered data without ECC - data rewritten") + +SENSE_CODE(0x1800, "Recovered data with error correction applied") +SENSE_CODE(0x1801, "Recovered data with error corr. & retries applied") +SENSE_CODE(0x1802, "Recovered data - data auto-reallocated") +SENSE_CODE(0x1803, "Recovered data with CIRC") +SENSE_CODE(0x1804, "Recovered data with L-EC") +SENSE_CODE(0x1805, "Recovered data - recommend reassignment") +SENSE_CODE(0x1806, "Recovered data - recommend rewrite") +SENSE_CODE(0x1807, "Recovered data with ECC - data rewritten") +SENSE_CODE(0x1808, "Recovered data with linking") + +SENSE_CODE(0x1900, "Defect list error") +SENSE_CODE(0x1901, "Defect list not available") +SENSE_CODE(0x1902, "Defect list error in primary list") +SENSE_CODE(0x1903, "Defect list error in grown list") + +SENSE_CODE(0x1A00, "Parameter list length error") + +SENSE_CODE(0x1B00, "Synchronous data transfer error") + +SENSE_CODE(0x1C00, "Defect list not found") +SENSE_CODE(0x1C01, "Primary defect list not found") +SENSE_CODE(0x1C02, "Grown defect list not found") + +SENSE_CODE(0x1D00, "Miscompare during verify operation") +SENSE_CODE(0x1D01, "Miscompare verify of unmapped LBA") + +SENSE_CODE(0x1E00, "Recovered id with ECC correction") + +SENSE_CODE(0x1F00, "Partial defect list transfer") + +SENSE_CODE(0x2000, "Invalid command operation code") +SENSE_CODE(0x2001, "Access denied - initiator pending-enrolled") +SENSE_CODE(0x2002, "Access denied - no access rights") +SENSE_CODE(0x2003, "Access denied - invalid mgmt id key") +SENSE_CODE(0x2004, "Illegal command while in write capable state") +SENSE_CODE(0x2005, "Obsolete") +SENSE_CODE(0x2006, "Illegal command while in explicit address mode") +SENSE_CODE(0x2007, "Illegal command while in implicit address mode") +SENSE_CODE(0x2008, "Access denied - enrollment conflict") +SENSE_CODE(0x2009, "Access denied - invalid LU identifier") +SENSE_CODE(0x200A, "Access denied - invalid proxy token") +SENSE_CODE(0x200B, "Access denied - ACL LUN conflict") +SENSE_CODE(0x200C, "Illegal command when not in append-only mode") + +SENSE_CODE(0x2100, "Logical block address out of range") +SENSE_CODE(0x2101, "Invalid element address") +SENSE_CODE(0x2102, "Invalid address for write") +SENSE_CODE(0x2103, "Invalid write crossing layer jump") +SENSE_CODE(0x2104, "Unaligned write command") +SENSE_CODE(0x2105, "Write boundary violation") +SENSE_CODE(0x2106, "Attempt to read invalid data") +SENSE_CODE(0x2107, "Read boundary violation") + +SENSE_CODE(0x2200, "Illegal function (use 20 00, 24 00, or 26 00)") + +SENSE_CODE(0x2300, "Invalid token operation, cause not reportable") +SENSE_CODE(0x2301, "Invalid token operation, unsupported token type") +SENSE_CODE(0x2302, "Invalid token operation, remote token usage not supported") +SENSE_CODE(0x2303, "Invalid token operation, remote rod token creation not supported") +SENSE_CODE(0x2304, "Invalid token operation, token unknown") +SENSE_CODE(0x2305, "Invalid token operation, token corrupt") +SENSE_CODE(0x2306, "Invalid token operation, token revoked") +SENSE_CODE(0x2307, "Invalid token operation, token expired") +SENSE_CODE(0x2308, "Invalid token operation, token cancelled") +SENSE_CODE(0x2309, "Invalid token operation, token deleted") +SENSE_CODE(0x230A, "Invalid token operation, invalid token length") + +SENSE_CODE(0x2400, "Invalid field in cdb") +SENSE_CODE(0x2401, "CDB decryption error") +SENSE_CODE(0x2402, "Obsolete") +SENSE_CODE(0x2403, "Obsolete") +SENSE_CODE(0x2404, "Security audit value frozen") +SENSE_CODE(0x2405, "Security working key frozen") +SENSE_CODE(0x2406, "Nonce not unique") +SENSE_CODE(0x2407, "Nonce timestamp out of range") +SENSE_CODE(0x2408, "Invalid XCDB") + +SENSE_CODE(0x2500, "Logical unit not supported") + +SENSE_CODE(0x2600, "Invalid field in parameter list") +SENSE_CODE(0x2601, "Parameter not supported") +SENSE_CODE(0x2602, "Parameter value invalid") +SENSE_CODE(0x2603, "Threshold parameters not supported") +SENSE_CODE(0x2604, "Invalid release of persistent reservation") +SENSE_CODE(0x2605, "Data decryption error") +SENSE_CODE(0x2606, "Too many target descriptors") +SENSE_CODE(0x2607, "Unsupported target descriptor type code") +SENSE_CODE(0x2608, "Too many segment descriptors") +SENSE_CODE(0x2609, "Unsupported segment descriptor type code") +SENSE_CODE(0x260A, "Unexpected inexact segment") +SENSE_CODE(0x260B, "Inline data length exceeded") +SENSE_CODE(0x260C, "Invalid operation for copy source or destination") +SENSE_CODE(0x260D, "Copy segment granularity violation") +SENSE_CODE(0x260E, "Invalid parameter while port is enabled") +SENSE_CODE(0x260F, "Invalid data-out buffer integrity check value") +SENSE_CODE(0x2610, "Data decryption key fail limit reached") +SENSE_CODE(0x2611, "Incomplete key-associated data set") +SENSE_CODE(0x2612, "Vendor specific key reference not found") + +SENSE_CODE(0x2700, "Write protected") +SENSE_CODE(0x2701, "Hardware write protected") +SENSE_CODE(0x2702, "Logical unit software write protected") +SENSE_CODE(0x2703, "Associated write protect") +SENSE_CODE(0x2704, "Persistent write protect") +SENSE_CODE(0x2705, "Permanent write protect") +SENSE_CODE(0x2706, "Conditional write protect") +SENSE_CODE(0x2707, "Space allocation failed write protect") +SENSE_CODE(0x2708, "Zone is read only") + +SENSE_CODE(0x2800, "Not ready to ready change, medium may have changed") +SENSE_CODE(0x2801, "Import or export element accessed") +SENSE_CODE(0x2802, "Format-layer may have changed") +SENSE_CODE(0x2803, "Import/export element accessed, medium changed") + +SENSE_CODE(0x2900, "Power on, reset, or bus device reset occurred") +SENSE_CODE(0x2901, "Power on occurred") +SENSE_CODE(0x2902, "Scsi bus reset occurred") +SENSE_CODE(0x2903, "Bus device reset function occurred") +SENSE_CODE(0x2904, "Device internal reset") +SENSE_CODE(0x2905, "Transceiver mode changed to single-ended") +SENSE_CODE(0x2906, "Transceiver mode changed to lvd") +SENSE_CODE(0x2907, "I_T nexus loss occurred") + +SENSE_CODE(0x2A00, "Parameters changed") +SENSE_CODE(0x2A01, "Mode parameters changed") +SENSE_CODE(0x2A02, "Log parameters changed") +SENSE_CODE(0x2A03, "Reservations preempted") +SENSE_CODE(0x2A04, "Reservations released") +SENSE_CODE(0x2A05, "Registrations preempted") +SENSE_CODE(0x2A06, "Asymmetric access state changed") +SENSE_CODE(0x2A07, "Implicit asymmetric access state transition failed") +SENSE_CODE(0x2A08, "Priority changed") +SENSE_CODE(0x2A09, "Capacity data has changed") +SENSE_CODE(0x2A0A, "Error history I_T nexus cleared") +SENSE_CODE(0x2A0B, "Error history snapshot released") +SENSE_CODE(0x2A0C, "Error recovery attributes have changed") +SENSE_CODE(0x2A0D, "Data encryption capabilities changed") +SENSE_CODE(0x2A10, "Timestamp changed") +SENSE_CODE(0x2A11, "Data encryption parameters changed by another i_t nexus") +SENSE_CODE(0x2A12, "Data encryption parameters changed by vendor specific event") +SENSE_CODE(0x2A13, "Data encryption key instance counter has changed") +SENSE_CODE(0x2A14, "SA creation capabilities data has changed") +SENSE_CODE(0x2A15, "Medium removal prevention preempted") + +SENSE_CODE(0x2B00, "Copy cannot execute since host cannot disconnect") + +SENSE_CODE(0x2C00, "Command sequence error") +SENSE_CODE(0x2C01, "Too many windows specified") +SENSE_CODE(0x2C02, "Invalid combination of windows specified") +SENSE_CODE(0x2C03, "Current program area is not empty") +SENSE_CODE(0x2C04, "Current program area is empty") +SENSE_CODE(0x2C05, "Illegal power condition request") +SENSE_CODE(0x2C06, "Persistent prevent conflict") +SENSE_CODE(0x2C07, "Previous busy status") +SENSE_CODE(0x2C08, "Previous task set full status") +SENSE_CODE(0x2C09, "Previous reservation conflict status") +SENSE_CODE(0x2C0A, "Partition or collection contains user objects") +SENSE_CODE(0x2C0B, "Not reserved") +SENSE_CODE(0x2C0C, "Orwrite generation does not match") +SENSE_CODE(0x2C0D, "Reset write pointer not allowed") +SENSE_CODE(0x2C0E, "Zone is offline") + +SENSE_CODE(0x2D00, "Overwrite error on update in place") + +SENSE_CODE(0x2E00, "Insufficient time for operation") +SENSE_CODE(0x2E01, "Command timeout before processing") +SENSE_CODE(0x2E02, "Command timeout during processing") +SENSE_CODE(0x2E03, "Command timeout during processing due to error recovery") + +SENSE_CODE(0x2F00, "Commands cleared by another initiator") +SENSE_CODE(0x2F01, "Commands cleared by power loss notification") +SENSE_CODE(0x2F02, "Commands cleared by device server") +SENSE_CODE(0x2F03, "Some commands cleared by queuing layer event") + +SENSE_CODE(0x3000, "Incompatible medium installed") +SENSE_CODE(0x3001, "Cannot read medium - unknown format") +SENSE_CODE(0x3002, "Cannot read medium - incompatible format") +SENSE_CODE(0x3003, "Cleaning cartridge installed") +SENSE_CODE(0x3004, "Cannot write medium - unknown format") +SENSE_CODE(0x3005, "Cannot write medium - incompatible format") +SENSE_CODE(0x3006, "Cannot format medium - incompatible medium") +SENSE_CODE(0x3007, "Cleaning failure") +SENSE_CODE(0x3008, "Cannot write - application code mismatch") +SENSE_CODE(0x3009, "Current session not fixated for append") +SENSE_CODE(0x300A, "Cleaning request rejected") +SENSE_CODE(0x300C, "WORM medium - overwrite attempted") +SENSE_CODE(0x300D, "WORM medium - integrity check") +SENSE_CODE(0x3010, "Medium not formatted") +SENSE_CODE(0x3011, "Incompatible volume type") +SENSE_CODE(0x3012, "Incompatible volume qualifier") +SENSE_CODE(0x3013, "Cleaning volume expired") + +SENSE_CODE(0x3100, "Medium format corrupted") +SENSE_CODE(0x3101, "Format command failed") +SENSE_CODE(0x3102, "Zoned formatting failed due to spare linking") +SENSE_CODE(0x3103, "Sanitize command failed") + +SENSE_CODE(0x3200, "No defect spare location available") +SENSE_CODE(0x3201, "Defect list update failure") + +SENSE_CODE(0x3300, "Tape length error") + +SENSE_CODE(0x3400, "Enclosure failure") + +SENSE_CODE(0x3500, "Enclosure services failure") +SENSE_CODE(0x3501, "Unsupported enclosure function") +SENSE_CODE(0x3502, "Enclosure services unavailable") +SENSE_CODE(0x3503, "Enclosure services transfer failure") +SENSE_CODE(0x3504, "Enclosure services transfer refused") +SENSE_CODE(0x3505, "Enclosure services checksum error") + +SENSE_CODE(0x3600, "Ribbon, ink, or toner failure") + +SENSE_CODE(0x3700, "Rounded parameter") + +SENSE_CODE(0x3800, "Event status notification") +SENSE_CODE(0x3802, "Esn - power management class event") +SENSE_CODE(0x3804, "Esn - media class event") +SENSE_CODE(0x3806, "Esn - device busy class event") +SENSE_CODE(0x3807, "Thin Provisioning soft threshold reached") + +SENSE_CODE(0x3900, "Saving parameters not supported") + +SENSE_CODE(0x3A00, "Medium not present") +SENSE_CODE(0x3A01, "Medium not present - tray closed") +SENSE_CODE(0x3A02, "Medium not present - tray open") +SENSE_CODE(0x3A03, "Medium not present - loadable") +SENSE_CODE(0x3A04, "Medium not present - medium auxiliary memory accessible") + +SENSE_CODE(0x3B00, "Sequential positioning error") +SENSE_CODE(0x3B01, "Tape position error at beginning-of-medium") +SENSE_CODE(0x3B02, "Tape position error at end-of-medium") +SENSE_CODE(0x3B03, "Tape or electronic vertical forms unit not ready") +SENSE_CODE(0x3B04, "Slew failure") +SENSE_CODE(0x3B05, "Paper jam") +SENSE_CODE(0x3B06, "Failed to sense top-of-form") +SENSE_CODE(0x3B07, "Failed to sense bottom-of-form") +SENSE_CODE(0x3B08, "Reposition error") +SENSE_CODE(0x3B09, "Read past end of medium") +SENSE_CODE(0x3B0A, "Read past beginning of medium") +SENSE_CODE(0x3B0B, "Position past end of medium") +SENSE_CODE(0x3B0C, "Position past beginning of medium") +SENSE_CODE(0x3B0D, "Medium destination element full") +SENSE_CODE(0x3B0E, "Medium source element empty") +SENSE_CODE(0x3B0F, "End of medium reached") +SENSE_CODE(0x3B11, "Medium magazine not accessible") +SENSE_CODE(0x3B12, "Medium magazine removed") +SENSE_CODE(0x3B13, "Medium magazine inserted") +SENSE_CODE(0x3B14, "Medium magazine locked") +SENSE_CODE(0x3B15, "Medium magazine unlocked") +SENSE_CODE(0x3B16, "Mechanical positioning or changer error") +SENSE_CODE(0x3B17, "Read past end of user object") +SENSE_CODE(0x3B18, "Element disabled") +SENSE_CODE(0x3B19, "Element enabled") +SENSE_CODE(0x3B1A, "Data transfer device removed") +SENSE_CODE(0x3B1B, "Data transfer device inserted") +SENSE_CODE(0x3B1C, "Too many logical objects on partition to support operation") + +SENSE_CODE(0x3D00, "Invalid bits in identify message") + +SENSE_CODE(0x3E00, "Logical unit has not self-configured yet") +SENSE_CODE(0x3E01, "Logical unit failure") +SENSE_CODE(0x3E02, "Timeout on logical unit") +SENSE_CODE(0x3E03, "Logical unit failed self-test") +SENSE_CODE(0x3E04, "Logical unit unable to update self-test log") + +SENSE_CODE(0x3F00, "Target operating conditions have changed") +SENSE_CODE(0x3F01, "Microcode has been changed") +SENSE_CODE(0x3F02, "Changed operating definition") +SENSE_CODE(0x3F03, "Inquiry data has changed") +SENSE_CODE(0x3F04, "Component device attached") +SENSE_CODE(0x3F05, "Device identifier changed") +SENSE_CODE(0x3F06, "Redundancy group created or modified") +SENSE_CODE(0x3F07, "Redundancy group deleted") +SENSE_CODE(0x3F08, "Spare created or modified") +SENSE_CODE(0x3F09, "Spare deleted") +SENSE_CODE(0x3F0A, "Volume set created or modified") +SENSE_CODE(0x3F0B, "Volume set deleted") +SENSE_CODE(0x3F0C, "Volume set deassigned") +SENSE_CODE(0x3F0D, "Volume set reassigned") +SENSE_CODE(0x3F0E, "Reported luns data has changed") +SENSE_CODE(0x3F0F, "Echo buffer overwritten") +SENSE_CODE(0x3F10, "Medium loadable") +SENSE_CODE(0x3F11, "Medium auxiliary memory accessible") +SENSE_CODE(0x3F12, "iSCSI IP address added") +SENSE_CODE(0x3F13, "iSCSI IP address removed") +SENSE_CODE(0x3F14, "iSCSI IP address changed") +SENSE_CODE(0x3F15, "Inspect referrals sense descriptors") +SENSE_CODE(0x3F16, "Microcode has been changed without reset") +/* + * SENSE_CODE(0x40NN, "Ram failure") + * SENSE_CODE(0x40NN, "Diagnostic failure on component nn") + * SENSE_CODE(0x41NN, "Data path failure") + * SENSE_CODE(0x42NN, "Power-on or self-test failure") + */ +SENSE_CODE(0x4300, "Message error") + +SENSE_CODE(0x4400, "Internal target failure") +SENSE_CODE(0x4401, "Persistent reservation information lost") +SENSE_CODE(0x4471, "ATA device failed set features") + +SENSE_CODE(0x4500, "Select or reselect failure") + +SENSE_CODE(0x4600, "Unsuccessful soft reset") + +SENSE_CODE(0x4700, "Scsi parity error") +SENSE_CODE(0x4701, "Data phase CRC error detected") +SENSE_CODE(0x4702, "Scsi parity error detected during st data phase") +SENSE_CODE(0x4703, "Information unit iuCRC error detected") +SENSE_CODE(0x4704, "Asynchronous information protection error detected") +SENSE_CODE(0x4705, "Protocol service CRC error") +SENSE_CODE(0x4706, "Phy test function in progress") +SENSE_CODE(0x477f, "Some commands cleared by iSCSI Protocol event") + +SENSE_CODE(0x4800, "Initiator detected error message received") + +SENSE_CODE(0x4900, "Invalid message error") + +SENSE_CODE(0x4A00, "Command phase error") + +SENSE_CODE(0x4B00, "Data phase error") +SENSE_CODE(0x4B01, "Invalid target port transfer tag received") +SENSE_CODE(0x4B02, "Too much write data") +SENSE_CODE(0x4B03, "Ack/nak timeout") +SENSE_CODE(0x4B04, "Nak received") +SENSE_CODE(0x4B05, "Data offset error") +SENSE_CODE(0x4B06, "Initiator response timeout") +SENSE_CODE(0x4B07, "Connection lost") +SENSE_CODE(0x4B08, "Data-in buffer overflow - data buffer size") +SENSE_CODE(0x4B09, "Data-in buffer overflow - data buffer descriptor area") +SENSE_CODE(0x4B0A, "Data-in buffer error") +SENSE_CODE(0x4B0B, "Data-out buffer overflow - data buffer size") +SENSE_CODE(0x4B0C, "Data-out buffer overflow - data buffer descriptor area") +SENSE_CODE(0x4B0D, "Data-out buffer error") +SENSE_CODE(0x4B0E, "PCIe fabric error") +SENSE_CODE(0x4B0F, "PCIe completion timeout") +SENSE_CODE(0x4B10, "PCIe completer abort") +SENSE_CODE(0x4B11, "PCIe poisoned tlp received") +SENSE_CODE(0x4B12, "PCIe eCRC check failed") +SENSE_CODE(0x4B13, "PCIe unsupported request") +SENSE_CODE(0x4B14, "PCIe acs violation") +SENSE_CODE(0x4B15, "PCIe tlp prefix blocked") + +SENSE_CODE(0x4C00, "Logical unit failed self-configuration") +/* + * SENSE_CODE(0x4DNN, "Tagged overlapped commands (nn = queue tag)") + */ +SENSE_CODE(0x4E00, "Overlapped commands attempted") + +SENSE_CODE(0x5000, "Write append error") +SENSE_CODE(0x5001, "Write append position error") +SENSE_CODE(0x5002, "Position error related to timing") + +SENSE_CODE(0x5100, "Erase failure") +SENSE_CODE(0x5101, "Erase failure - incomplete erase operation detected") + +SENSE_CODE(0x5200, "Cartridge fault") + +SENSE_CODE(0x5300, "Media load or eject failed") +SENSE_CODE(0x5301, "Unload tape failure") +SENSE_CODE(0x5302, "Medium removal prevented") +SENSE_CODE(0x5303, "Medium removal prevented by data transfer element") +SENSE_CODE(0x5304, "Medium thread or unthread failure") +SENSE_CODE(0x5305, "Volume identifier invalid") +SENSE_CODE(0x5306, "Volume identifier missing") +SENSE_CODE(0x5307, "Duplicate volume identifier") +SENSE_CODE(0x5308, "Element status unknown") +SENSE_CODE(0x5309, "Data transfer device error - load failed") +SENSE_CODE(0x530a, "Data transfer device error - unload failed") +SENSE_CODE(0x530b, "Data transfer device error - unload missing") +SENSE_CODE(0x530c, "Data transfer device error - eject failed") +SENSE_CODE(0x530d, "Data transfer device error - library communication failed") + +SENSE_CODE(0x5400, "Scsi to host system interface failure") + +SENSE_CODE(0x5500, "System resource failure") +SENSE_CODE(0x5501, "System buffer full") +SENSE_CODE(0x5502, "Insufficient reservation resources") +SENSE_CODE(0x5503, "Insufficient resources") +SENSE_CODE(0x5504, "Insufficient registration resources") +SENSE_CODE(0x5505, "Insufficient access control resources") +SENSE_CODE(0x5506, "Auxiliary memory out of space") +SENSE_CODE(0x5507, "Quota error") +SENSE_CODE(0x5508, "Maximum number of supplemental decryption keys exceeded") +SENSE_CODE(0x5509, "Medium auxiliary memory not accessible") +SENSE_CODE(0x550A, "Data currently unavailable") +SENSE_CODE(0x550B, "Insufficient power for operation") +SENSE_CODE(0x550C, "Insufficient resources to create rod") +SENSE_CODE(0x550D, "Insufficient resources to create rod token") +SENSE_CODE(0x550E, "Insufficient zone resources") + +SENSE_CODE(0x5700, "Unable to recover table-of-contents") + +SENSE_CODE(0x5800, "Generation does not exist") + +SENSE_CODE(0x5900, "Updated block read") + +SENSE_CODE(0x5A00, "Operator request or state change input") +SENSE_CODE(0x5A01, "Operator medium removal request") +SENSE_CODE(0x5A02, "Operator selected write protect") +SENSE_CODE(0x5A03, "Operator selected write permit") + +SENSE_CODE(0x5B00, "Log exception") +SENSE_CODE(0x5B01, "Threshold condition met") +SENSE_CODE(0x5B02, "Log counter at maximum") +SENSE_CODE(0x5B03, "Log list codes exhausted") + +SENSE_CODE(0x5C00, "Rpl status change") +SENSE_CODE(0x5C01, "Spindles synchronized") +SENSE_CODE(0x5C02, "Spindles not synchronized") + +SENSE_CODE(0x5D00, "Failure prediction threshold exceeded") +SENSE_CODE(0x5D01, "Media failure prediction threshold exceeded") +SENSE_CODE(0x5D02, "Logical unit failure prediction threshold exceeded") +SENSE_CODE(0x5D03, "Spare area exhaustion prediction threshold exceeded") +SENSE_CODE(0x5D10, "Hardware impending failure general hard drive failure") +SENSE_CODE(0x5D11, "Hardware impending failure drive error rate too high") +SENSE_CODE(0x5D12, "Hardware impending failure data error rate too high") +SENSE_CODE(0x5D13, "Hardware impending failure seek error rate too high") +SENSE_CODE(0x5D14, "Hardware impending failure too many block reassigns") +SENSE_CODE(0x5D15, "Hardware impending failure access times too high") +SENSE_CODE(0x5D16, "Hardware impending failure start unit times too high") +SENSE_CODE(0x5D17, "Hardware impending failure channel parametrics") +SENSE_CODE(0x5D18, "Hardware impending failure controller detected") +SENSE_CODE(0x5D19, "Hardware impending failure throughput performance") +SENSE_CODE(0x5D1A, "Hardware impending failure seek time performance") +SENSE_CODE(0x5D1B, "Hardware impending failure spin-up retry count") +SENSE_CODE(0x5D1C, "Hardware impending failure drive calibration retry count") +SENSE_CODE(0x5D20, "Controller impending failure general hard drive failure") +SENSE_CODE(0x5D21, "Controller impending failure drive error rate too high") +SENSE_CODE(0x5D22, "Controller impending failure data error rate too high") +SENSE_CODE(0x5D23, "Controller impending failure seek error rate too high") +SENSE_CODE(0x5D24, "Controller impending failure too many block reassigns") +SENSE_CODE(0x5D25, "Controller impending failure access times too high") +SENSE_CODE(0x5D26, "Controller impending failure start unit times too high") +SENSE_CODE(0x5D27, "Controller impending failure channel parametrics") +SENSE_CODE(0x5D28, "Controller impending failure controller detected") +SENSE_CODE(0x5D29, "Controller impending failure throughput performance") +SENSE_CODE(0x5D2A, "Controller impending failure seek time performance") +SENSE_CODE(0x5D2B, "Controller impending failure spin-up retry count") +SENSE_CODE(0x5D2C, "Controller impending failure drive calibration retry count") +SENSE_CODE(0x5D30, "Data channel impending failure general hard drive failure") +SENSE_CODE(0x5D31, "Data channel impending failure drive error rate too high") +SENSE_CODE(0x5D32, "Data channel impending failure data error rate too high") +SENSE_CODE(0x5D33, "Data channel impending failure seek error rate too high") +SENSE_CODE(0x5D34, "Data channel impending failure too many block reassigns") +SENSE_CODE(0x5D35, "Data channel impending failure access times too high") +SENSE_CODE(0x5D36, "Data channel impending failure start unit times too high") +SENSE_CODE(0x5D37, "Data channel impending failure channel parametrics") +SENSE_CODE(0x5D38, "Data channel impending failure controller detected") +SENSE_CODE(0x5D39, "Data channel impending failure throughput performance") +SENSE_CODE(0x5D3A, "Data channel impending failure seek time performance") +SENSE_CODE(0x5D3B, "Data channel impending failure spin-up retry count") +SENSE_CODE(0x5D3C, "Data channel impending failure drive calibration retry count") +SENSE_CODE(0x5D40, "Servo impending failure general hard drive failure") +SENSE_CODE(0x5D41, "Servo impending failure drive error rate too high") +SENSE_CODE(0x5D42, "Servo impending failure data error rate too high") +SENSE_CODE(0x5D43, "Servo impending failure seek error rate too high") +SENSE_CODE(0x5D44, "Servo impending failure too many block reassigns") +SENSE_CODE(0x5D45, "Servo impending failure access times too high") +SENSE_CODE(0x5D46, "Servo impending failure start unit times too high") +SENSE_CODE(0x5D47, "Servo impending failure channel parametrics") +SENSE_CODE(0x5D48, "Servo impending failure controller detected") +SENSE_CODE(0x5D49, "Servo impending failure throughput performance") +SENSE_CODE(0x5D4A, "Servo impending failure seek time performance") +SENSE_CODE(0x5D4B, "Servo impending failure spin-up retry count") +SENSE_CODE(0x5D4C, "Servo impending failure drive calibration retry count") +SENSE_CODE(0x5D50, "Spindle impending failure general hard drive failure") +SENSE_CODE(0x5D51, "Spindle impending failure drive error rate too high") +SENSE_CODE(0x5D52, "Spindle impending failure data error rate too high") +SENSE_CODE(0x5D53, "Spindle impending failure seek error rate too high") +SENSE_CODE(0x5D54, "Spindle impending failure too many block reassigns") +SENSE_CODE(0x5D55, "Spindle impending failure access times too high") +SENSE_CODE(0x5D56, "Spindle impending failure start unit times too high") +SENSE_CODE(0x5D57, "Spindle impending failure channel parametrics") +SENSE_CODE(0x5D58, "Spindle impending failure controller detected") +SENSE_CODE(0x5D59, "Spindle impending failure throughput performance") +SENSE_CODE(0x5D5A, "Spindle impending failure seek time performance") +SENSE_CODE(0x5D5B, "Spindle impending failure spin-up retry count") +SENSE_CODE(0x5D5C, "Spindle impending failure drive calibration retry count") +SENSE_CODE(0x5D60, "Firmware impending failure general hard drive failure") +SENSE_CODE(0x5D61, "Firmware impending failure drive error rate too high") +SENSE_CODE(0x5D62, "Firmware impending failure data error rate too high") +SENSE_CODE(0x5D63, "Firmware impending failure seek error rate too high") +SENSE_CODE(0x5D64, "Firmware impending failure too many block reassigns") +SENSE_CODE(0x5D65, "Firmware impending failure access times too high") +SENSE_CODE(0x5D66, "Firmware impending failure start unit times too high") +SENSE_CODE(0x5D67, "Firmware impending failure channel parametrics") +SENSE_CODE(0x5D68, "Firmware impending failure controller detected") +SENSE_CODE(0x5D69, "Firmware impending failure throughput performance") +SENSE_CODE(0x5D6A, "Firmware impending failure seek time performance") +SENSE_CODE(0x5D6B, "Firmware impending failure spin-up retry count") +SENSE_CODE(0x5D6C, "Firmware impending failure drive calibration retry count") +SENSE_CODE(0x5DFF, "Failure prediction threshold exceeded (false)") + +SENSE_CODE(0x5E00, "Low power condition on") +SENSE_CODE(0x5E01, "Idle condition activated by timer") +SENSE_CODE(0x5E02, "Standby condition activated by timer") +SENSE_CODE(0x5E03, "Idle condition activated by command") +SENSE_CODE(0x5E04, "Standby condition activated by command") +SENSE_CODE(0x5E05, "Idle_b condition activated by timer") +SENSE_CODE(0x5E06, "Idle_b condition activated by command") +SENSE_CODE(0x5E07, "Idle_c condition activated by timer") +SENSE_CODE(0x5E08, "Idle_c condition activated by command") +SENSE_CODE(0x5E09, "Standby_y condition activated by timer") +SENSE_CODE(0x5E0A, "Standby_y condition activated by command") +SENSE_CODE(0x5E41, "Power state change to active") +SENSE_CODE(0x5E42, "Power state change to idle") +SENSE_CODE(0x5E43, "Power state change to standby") +SENSE_CODE(0x5E45, "Power state change to sleep") +SENSE_CODE(0x5E47, "Power state change to device control") + +SENSE_CODE(0x6000, "Lamp failure") + +SENSE_CODE(0x6100, "Video acquisition error") +SENSE_CODE(0x6101, "Unable to acquire video") +SENSE_CODE(0x6102, "Out of focus") + +SENSE_CODE(0x6200, "Scan head positioning error") + +SENSE_CODE(0x6300, "End of user area encountered on this track") +SENSE_CODE(0x6301, "Packet does not fit in available space") + +SENSE_CODE(0x6400, "Illegal mode for this track") +SENSE_CODE(0x6401, "Invalid packet size") + +SENSE_CODE(0x6500, "Voltage fault") + +SENSE_CODE(0x6600, "Automatic document feeder cover up") +SENSE_CODE(0x6601, "Automatic document feeder lift up") +SENSE_CODE(0x6602, "Document jam in automatic document feeder") +SENSE_CODE(0x6603, "Document miss feed automatic in document feeder") + +SENSE_CODE(0x6700, "Configuration failure") +SENSE_CODE(0x6701, "Configuration of incapable logical units failed") +SENSE_CODE(0x6702, "Add logical unit failed") +SENSE_CODE(0x6703, "Modification of logical unit failed") +SENSE_CODE(0x6704, "Exchange of logical unit failed") +SENSE_CODE(0x6705, "Remove of logical unit failed") +SENSE_CODE(0x6706, "Attachment of logical unit failed") +SENSE_CODE(0x6707, "Creation of logical unit failed") +SENSE_CODE(0x6708, "Assign failure occurred") +SENSE_CODE(0x6709, "Multiply assigned logical unit") +SENSE_CODE(0x670A, "Set target port groups command failed") +SENSE_CODE(0x670B, "ATA device feature not enabled") + +SENSE_CODE(0x6800, "Logical unit not configured") +SENSE_CODE(0x6801, "Subsidiary logical unit not configured") + +SENSE_CODE(0x6900, "Data loss on logical unit") +SENSE_CODE(0x6901, "Multiple logical unit failures") +SENSE_CODE(0x6902, "Parity/data mismatch") + +SENSE_CODE(0x6A00, "Informational, refer to log") + +SENSE_CODE(0x6B00, "State change has occurred") +SENSE_CODE(0x6B01, "Redundancy level got better") +SENSE_CODE(0x6B02, "Redundancy level got worse") + +SENSE_CODE(0x6C00, "Rebuild failure occurred") + +SENSE_CODE(0x6D00, "Recalculate failure occurred") + +SENSE_CODE(0x6E00, "Command to logical unit failed") + +SENSE_CODE(0x6F00, "Copy protection key exchange failure - authentication failure") +SENSE_CODE(0x6F01, "Copy protection key exchange failure - key not present") +SENSE_CODE(0x6F02, "Copy protection key exchange failure - key not established") +SENSE_CODE(0x6F03, "Read of scrambled sector without authentication") +SENSE_CODE(0x6F04, "Media region code is mismatched to logical unit region") +SENSE_CODE(0x6F05, "Drive region must be permanent/region reset count error") +SENSE_CODE(0x6F06, "Insufficient block count for binding nonce recording") +SENSE_CODE(0x6F07, "Conflict in binding nonce recording") +/* + * SENSE_CODE(0x70NN, "Decompression exception short algorithm id of nn") + */ +SENSE_CODE(0x7100, "Decompression exception long algorithm id") + +SENSE_CODE(0x7200, "Session fixation error") +SENSE_CODE(0x7201, "Session fixation error writing lead-in") +SENSE_CODE(0x7202, "Session fixation error writing lead-out") +SENSE_CODE(0x7203, "Session fixation error - incomplete track in session") +SENSE_CODE(0x7204, "Empty or partially written reserved track") +SENSE_CODE(0x7205, "No more track reservations allowed") +SENSE_CODE(0x7206, "RMZ extension is not allowed") +SENSE_CODE(0x7207, "No more test zone extensions are allowed") + +SENSE_CODE(0x7300, "Cd control error") +SENSE_CODE(0x7301, "Power calibration area almost full") +SENSE_CODE(0x7302, "Power calibration area is full") +SENSE_CODE(0x7303, "Power calibration area error") +SENSE_CODE(0x7304, "Program memory area update failure") +SENSE_CODE(0x7305, "Program memory area is full") +SENSE_CODE(0x7306, "RMA/PMA is almost full") +SENSE_CODE(0x7310, "Current power calibration area almost full") +SENSE_CODE(0x7311, "Current power calibration area is full") +SENSE_CODE(0x7317, "RDZ is full") + +SENSE_CODE(0x7400, "Security error") +SENSE_CODE(0x7401, "Unable to decrypt data") +SENSE_CODE(0x7402, "Unencrypted data encountered while decrypting") +SENSE_CODE(0x7403, "Incorrect data encryption key") +SENSE_CODE(0x7404, "Cryptographic integrity validation failed") +SENSE_CODE(0x7405, "Error decrypting data") +SENSE_CODE(0x7406, "Unknown signature verification key") +SENSE_CODE(0x7407, "Encryption parameters not useable") +SENSE_CODE(0x7408, "Digital signature validation failure") +SENSE_CODE(0x7409, "Encryption mode mismatch on read") +SENSE_CODE(0x740A, "Encrypted block not raw read enabled") +SENSE_CODE(0x740B, "Incorrect Encryption parameters") +SENSE_CODE(0x740C, "Unable to decrypt parameter list") +SENSE_CODE(0x740D, "Encryption algorithm disabled") +SENSE_CODE(0x7410, "SA creation parameter value invalid") +SENSE_CODE(0x7411, "SA creation parameter value rejected") +SENSE_CODE(0x7412, "Invalid SA usage") +SENSE_CODE(0x7421, "Data Encryption configuration prevented") +SENSE_CODE(0x7430, "SA creation parameter not supported") +SENSE_CODE(0x7440, "Authentication failed") +SENSE_CODE(0x7461, "External data encryption key manager access error") +SENSE_CODE(0x7462, "External data encryption key manager error") +SENSE_CODE(0x7463, "External data encryption key not found") +SENSE_CODE(0x7464, "External data encryption request not authorized") +SENSE_CODE(0x746E, "External data encryption control timeout") +SENSE_CODE(0x746F, "External data encryption control error") +SENSE_CODE(0x7471, "Logical unit access not authorized") +SENSE_CODE(0x7479, "Security conflict in translated device") From e1f0bce3a0db95007fec756225801e50477f32fd Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 22 Mar 2016 20:32:05 +0100 Subject: [PATCH 003/138] scsi: reduce CONFIG_SCSI_CONSTANTS=y impact by 8k On 64 bit, struct error_info has 6 bytes of padding, which amounts to over 4k of wasted space in the additional[] array. We could easily get rid of that by instead using separate arrays for the codes and the pointers. However, we can do even better than that and save an additional 6 bytes per entry: In the table, just store the sizeof() the corresponding string literal. The cumulative sum of these is then the appropriate offset into additional_text, which is built from the concatenation (with '\0's inbetween) of the strings. $ scripts/bloat-o-meter /tmp/vmlinux vmlinux add/remove: 0/0 grow/shrink: 1/1 up/down: 24/-8488 (-8464) function old new delta scsi_extd_sense_format 136 160 +24 additional 11312 2824 -8488 The Kconfig help text used to say that CONFIG_SCSI_CONSTANTS=y costs around 75 KB, but that was a little exaggerated. The actual number was closer to 44K, and 36K with this patch. Signed-off-by: Rasmus Villemoes Reviewed-by: Hannes Reinecke Tested-by: Douglas Gilbert Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 4 ++-- drivers/scsi/constants.c | 26 +++++++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index e80768f8e579..47611bda633f 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -202,12 +202,12 @@ config SCSI_ENCLOSURE certain enclosure conditions to be reported and is not required. config SCSI_CONSTANTS - bool "Verbose SCSI error reporting (kernel size +=75K)" + bool "Verbose SCSI error reporting (kernel size += 36K)" depends on SCSI help The error messages regarding your SCSI hardware will be easier to understand if you say Y here; it will enlarge your kernel by about - 75 KB. If in doubt, say Y. + 36 KB. If in doubt, say Y. config SCSI_LOGGING bool "SCSI logging facility" diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 6e813eec4f8d..83458f7a2824 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -292,17 +292,30 @@ bool scsi_opcode_sa_name(int opcode, int service_action, struct error_info { unsigned short code12; /* 0x0302 looks better than 0x03,0x02 */ - const char * text; + unsigned short size; }; +/* + * There are 700+ entries in this table. To save space, we don't store + * (code, pointer) pairs, which would make sizeof(struct + * error_info)==16 on 64 bits. Rather, the second element just stores + * the size (including \0) of the corresponding string, and we use the + * sum of these to get the appropriate offset into additional_text + * defined below. This approach saves 12 bytes per entry. + */ static const struct error_info additional[] = { -#define SENSE_CODE(c, s) {c, s}, +#define SENSE_CODE(c, s) {c, sizeof(s)}, #include "sense_codes.h" #undef SENSE_CODE - {0, NULL} }; +static const char *additional_text = +#define SENSE_CODE(c, s) s "\0" +#include "sense_codes.h" +#undef SENSE_CODE + ; + struct error_info2 { unsigned char code1, code2_min, code2_max; const char * str; @@ -364,11 +377,14 @@ scsi_extd_sense_format(unsigned char asc, unsigned char ascq, const char **fmt) { int i; unsigned short code = ((asc << 8) | ascq); + unsigned offset = 0; *fmt = NULL; - for (i = 0; additional[i].text; i++) + for (i = 0; i < ARRAY_SIZE(additional); i++) { if (additional[i].code12 == code) - return additional[i].text; + return additional_text + offset; + offset += additional[i].size; + } for (i = 0; additional2[i].fmt; i++) { if (additional2[i].code1 == asc && ascq >= additional2[i].code2_min && From 9d376402c80cfe2356d84577d366ca790e576bd9 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:10 +1100 Subject: [PATCH 004/138] g_ncr5380: Remove CONFIG_SCSI_GENERIC_NCR53C400 This change brings a number of improvements: fewer macros, better test coverage, simpler code and sane Kconfig options. The downside is a small chance of incompatibility (which seems unavoidable). CONFIG_SCSI_GENERIC_NCR53C400 exists to enable or inhibit pseudo DMA transfers when the driver is used with 53C400-compatible cards. Thanks to Ondrej Zary's patches, PDMA now works which means it can be enabled unconditionally. Due to bad design, CONFIG_SCSI_GENERIC_NCR53C400 ties together unrelated functionality as it sets both PSEUDO_DMA and BIOSPARAM macros. This patch effectively enables PSEUDO_DMA and disables BIOSPARAM. The defconfigs and the Kconfig default leave CONFIG_SCSI_GENERIC_NCR53C400 undefined. Red Hat 9 and CentOS 2.1 were the same. This leaves both PSEUDO_DMA and BIOSPARAM disabled. The effect of this patch should be better performance from enabling PSEUDO_DMA. On the other hand, Debian 4 and SLES 10 had CONFIG_SCSI_GENERIC_NCR53C400 enabled, so both PSEUDO_DMA and BIOSPARAM were enabled. This patch might affect configurations like this by disabling BIOSPARAM. My best guess is that this could be a problem only in the vanishingly rare case that 1) the CHS values stored in the boot device partition table are wrong and 2) a 5380 card is in use (because PDMA on 53C400 used to be broken). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 11 ------ drivers/scsi/g_NCR5380.c | 75 ++++++++++++---------------------------- drivers/scsi/g_NCR5380.h | 16 ++------- 3 files changed, 25 insertions(+), 77 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 47611bda633f..0950567e6269 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -813,17 +813,6 @@ config SCSI_GENERIC_NCR5380_MMIO To compile this driver as a module, choose M here: the module will be called g_NCR5380_mmio. -config SCSI_GENERIC_NCR53C400 - bool "Enable NCR53c400 extensions" - depends on SCSI_GENERIC_NCR5380 - help - This enables certain optimizations for the NCR53c400 SCSI cards. - You might as well try it out. Note that this driver will only probe - for the Trantor T130B in its default configuration; you might have - to pass a command line option to the kernel at boot time if it does - not detect your card. See the file - for details. - config SCSI_IPS tristate "IBM ServeRAID support" depends on PCI && SCSI diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 90091e693020..85ebe109d15d 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -57,10 +57,7 @@ */ #define AUTOPROBE_IRQ - -#ifdef CONFIG_SCSI_GENERIC_NCR53C400 #define PSEUDO_DMA -#endif #include #include @@ -270,7 +267,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #ifndef SCSI_G_NCR5380_MEM int i; int port_idx = -1; - unsigned long region_size = 16; + unsigned long region_size; #endif static unsigned int __initdata ncr_53c400a_ports[] = { 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 @@ -290,6 +287,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #ifdef SCSI_G_NCR5380_MEM unsigned long base; void __iomem *iomem; + resource_size_t iomem_size; #endif if (ncr_irq) @@ -353,9 +351,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) flags = FLAG_NO_PSEUDO_DMA; break; case BOARD_NCR53C400: -#ifdef PSEUDO_DMA flags = FLAG_NO_DMA_FIXUP; -#endif break; case BOARD_NCR53C400A: flags = FLAG_NO_DMA_FIXUP; @@ -381,20 +377,22 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) /* Disable the adapter and look for a free io port */ magic_configure(-1, 0, magic); + region_size = 16; + if (overrides[current_override].NCR5380_map_name != PORT_AUTO) for (i = 0; ports[i]; i++) { - if (!request_region(ports[i], 16, "ncr53c80")) + if (!request_region(ports[i], region_size, "ncr53c80")) continue; if (overrides[current_override].NCR5380_map_name == ports[i]) break; - release_region(ports[i], 16); + release_region(ports[i], region_size); } else for (i = 0; ports[i]; i++) { - if (!request_region(ports[i], 16, "ncr53c80")) + if (!request_region(ports[i], region_size, "ncr53c80")) continue; if (inb(ports[i]) == 0xff) break; - release_region(ports[i], 16); + release_region(ports[i], region_size); } if (ports[i]) { /* At this point we have our region reserved */ @@ -410,17 +408,19 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) else { /* Not a 53C400A style setup - just grab */ - if(!(request_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size, "ncr5380"))) + region_size = 8; + if (!request_region(overrides[current_override].NCR5380_map_name, + region_size, "ncr5380")) continue; - region_size = NCR5380_region_size; } #else base = overrides[current_override].NCR5380_map_name; - if (!request_mem_region(base, NCR5380_region_size, "ncr5380")) + iomem_size = NCR53C400_region_size; + if (!request_mem_region(base, iomem_size, "ncr5380")) continue; - iomem = ioremap(base, NCR5380_region_size); + iomem = ioremap(base, iomem_size); if (!iomem) { - release_mem_region(base, NCR5380_region_size); + release_mem_region(base, iomem_size); continue; } #endif @@ -458,6 +458,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #else instance->base = overrides[current_override].NCR5380_map_name; hostdata->iomem = iomem; + hostdata->iomem_size = iomem_size; switch (overrides[current_override].board) { case BOARD_NCR53C400: hostdata->c400_ctl_status = 0x100; @@ -524,7 +525,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) release_region(overrides[current_override].NCR5380_map_name, region_size); #else iounmap(iomem); - release_mem_region(base, NCR5380_region_size); + release_mem_region(base, iomem_size); #endif return count; } @@ -546,43 +547,16 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance) #ifndef SCSI_G_NCR5380_MEM release_region(instance->io_port, instance->n_io_port); #else - iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem); - release_mem_region(instance->base, NCR5380_region_size); + { + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + iounmap(hostdata->iomem); + release_mem_region(instance->base, hostdata->iomem_size); + } #endif return 0; } -#ifdef BIOSPARAM -/** - * generic_NCR5380_biosparam - * @disk: disk to compute geometry for - * @dev: device identifier for this disk - * @ip: sizes to fill in - * - * Generates a BIOS / DOS compatible H-C-S mapping for the specified - * device / size. - * - * XXX Most SCSI boards use this mapping, I could be incorrect. Someone - * using hard disks on a trantor should verify that this mapping - * corresponds to that used by the BIOS / ASPI driver by running the linux - * fdisk program and matching the H_C_S coordinates to what DOS uses. - * - * Locks: none - */ - -static int -generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *ip) -{ - ip[0] = 64; - ip[1] = 32; - ip[2] = capacity >> 11; - return 0; -} -#endif - -#ifdef PSEUDO_DMA - /** * NCR5380_pread - pseudo DMA read * @instance: adapter to read from @@ -756,8 +730,6 @@ static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd) return transfersize; } -#endif /* PSEUDO_DMA */ - /* * Include the NCR5380 core code that we build our driver around */ @@ -773,7 +745,6 @@ static struct scsi_host_template driver_template = { .queuecommand = generic_NCR5380_queue_command, .eh_abort_handler = generic_NCR5380_abort, .eh_bus_reset_handler = generic_NCR5380_bus_reset, - .bios_param = NCR5380_BIOSPARAM, .can_queue = 16, .this_id = 7, .sg_tablesize = SG_ALL, diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 6f3d2ac4f185..1ca3743a887e 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -14,13 +14,6 @@ #ifndef GENERIC_NCR5380_H #define GENERIC_NCR5380_H -#ifdef CONFIG_SCSI_GENERIC_NCR53C400 -#define BIOSPARAM -#define NCR5380_BIOSPARAM generic_NCR5380_biosparam -#else -#define NCR5380_BIOSPARAM NULL -#endif - #define __STRVAL(x) #x #define STRVAL(x) __STRVAL(x) @@ -30,12 +23,6 @@ #define NCR5380_map_type int #define NCR5380_map_name port -#ifdef CONFIG_SCSI_GENERIC_NCR53C400 -#define NCR5380_region_size 16 -#else -#define NCR5380_region_size 8 -#endif - #define NCR5380_read(reg) \ inb(instance->io_port + (reg)) #define NCR5380_write(reg, value) \ @@ -55,7 +42,7 @@ #define NCR5380_map_name base #define NCR53C400_mem_base 0x3880 #define NCR53C400_host_buffer 0x3900 -#define NCR5380_region_size 0x3a00 +#define NCR53C400_region_size 0x3a00 #define NCR5380_read(reg) \ readb(((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ @@ -66,6 +53,7 @@ #define NCR5380_implementation_fields \ void __iomem *iomem; \ + resource_size_t iomem_size; \ int c400_ctl_status; \ int c400_blk_cnt; \ int c400_host_buf; From 7e9ec8d9cc18a85e8a4c28aef9136867b46aba42 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:11 +1100 Subject: [PATCH 005/138] ncr5380: Remove FLAG_NO_PSEUDO_DMA where possible Drivers that define PSEUDO_DMA also define NCR5380_dma_xfer_len. The core driver must call NCR5380_dma_xfer_len which means FLAG_NO_PSEUDO_DMA can be eradicated from the core driver. dmx3191d doesn't define PSEUDO_DMA and has no use for FLAG_NO_PSEUDO_DMA, so remove it there also. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 3 +-- drivers/scsi/dmx3191d.c | 2 +- drivers/scsi/g_NCR5380.c | 7 ++++++- drivers/scsi/g_NCR5380.h | 2 +- drivers/scsi/mac_scsi.c | 15 ++++++++++++++- 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 3eff2a69fe08..98840bed05cb 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1833,8 +1833,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) transfersize = 0; - if (!cmd->device->borken && - !(hostdata->flags & FLAG_NO_PSEUDO_DMA)) + if (!cmd->device->borken) transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); if (transfersize) { diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 6c14e68b9e1a..e9e96af96104 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -93,7 +93,7 @@ static int dmx3191d_probe_one(struct pci_dev *pdev, */ shost->irq = NO_IRQ; - error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA); + error = NCR5380_init(shost, 0); if (error) goto out_host_put; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 85ebe109d15d..b8fc26d9231d 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -712,10 +712,15 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, return 0; } -static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd) +static int generic_NCR5380_dma_xfer_len(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); int transfersize = cmd->transfersize; + if (hostdata->flags & FLAG_NO_PSEUDO_DMA) + return 0; + /* Limit transfers to 32K, for xx400 & xx406 * pseudoDMA that transfers in 128 bytes blocks. */ diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 1ca3743a887e..3fb0d8529429 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -61,7 +61,7 @@ #endif #define NCR5380_dma_xfer_len(instance, cmd, phase) \ - generic_NCR5380_dma_xfer_len(cmd) + generic_NCR5380_dma_xfer_len(instance, cmd) #define NCR5380_intr generic_NCR5380_intr #define NCR5380_queue_command generic_NCR5380_queue_command diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index bb2381314a2b..a8f5433b515e 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -37,7 +37,9 @@ #define NCR5380_pread macscsi_pread #define NCR5380_pwrite macscsi_pwrite -#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) + +#define NCR5380_dma_xfer_len(instance, cmd, phase) \ + macscsi_dma_xfer_len(instance, cmd) #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command @@ -303,6 +305,17 @@ static int macscsi_pwrite(struct Scsi_Host *instance, } #endif +static int macscsi_dma_xfer_len(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + if (hostdata->flags & FLAG_NO_PSEUDO_DMA) + return 0; + + return cmd->transfersize; +} + #include "NCR5380.c" #define DRV_MODULE_NAME "mac_scsi" From e4dec6806aceca768b74c1c6402e6d31ecf3c960 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:12 +1100 Subject: [PATCH 006/138] ncr5380: Remove REAL_DMA and REAL_DMA_POLL macros For the NCR5380.c core driver, these macros are never used. If REAL_DMA were to be defined, compilation would fail. For the atari_NCR5380.c core driver, REAL_DMA is always defined. Hence these macros are pointless. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 218 ++--------------------------------- drivers/scsi/NCR5380.h | 112 ------------------ drivers/scsi/atari_NCR5380.c | 62 ++-------- drivers/scsi/atari_scsi.c | 32 +---- drivers/scsi/sun3_scsi.c | 13 +-- 5 files changed, 22 insertions(+), 415 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 98840bed05cb..826b63d1aa84 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -35,18 +35,10 @@ * code so that everything does the same thing that's done at the * end of a pseudo-DMA read operation. * - * 2. Fix REAL_DMA (interrupt driven, polled works fine) - - * basically, transfer size needs to be reduced by one - * and the last byte read as is done with PSEUDO_DMA. - * * 4. Test SCSI-II tagged queueing (I have no devices which support * tagged queueing) */ -#ifndef notyet -#undef REAL_DMA -#endif - #ifdef BOARD_REQUIRES_NO_DELAY #define io_recovery_delay(x) #else @@ -131,12 +123,6 @@ * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. * - * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. - * - * REAL_DMA_POLL - if defined, REAL DMA is used but the driver doesn't - * rely on phase mismatch and EOP interrupts to determine end - * of phase. - * * These macros MUST be defined : * * NCR5380_read(register) - read from the specified register @@ -147,15 +133,9 @@ * specific implementation of the NCR5380 * * Either real DMA *or* pseudo DMA may be implemented - * REAL functions : - * NCR5380_REAL_DMA should be defined if real DMA is to be used. * Note that the DMA setup functions should return the number of bytes * that they were able to program the controller for. * - * Also note that generic i386/PC versions of these macros are - * available as NCR5380_i386_dma_write_setup, - * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. - * * NCR5380_dma_write_setup(instance, src, count) - initialize * NCR5380_dma_read_setup(instance, dst, count) - initialize * NCR5380_dma_residual(instance); - residual count @@ -486,12 +466,6 @@ static void prepare_info(struct Scsi_Host *instance) #ifdef DIFFERENTIAL "DIFFERENTIAL " #endif -#ifdef REAL_DMA - "REAL_DMA " -#endif -#ifdef REAL_DMA_POLL - "REAL_DMA_POLL " -#endif #ifdef PARITY "PARITY " #endif @@ -551,9 +525,8 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->id_higher_mask |= i; for (i = 0; i < 8; ++i) hostdata->busy[i] = 0; -#ifdef REAL_DMA - hostdata->dmalen = 0; -#endif + hostdata->dma_len = 0; + spin_lock_init(&hostdata->lock); hostdata->connected = NULL; hostdata->sensing = NULL; @@ -850,11 +823,7 @@ static void NCR5380_main(struct work_struct *work) requeue_cmd(instance, cmd); } } - if (hostdata->connected -#ifdef REAL_DMA - && !hostdata->dmalen -#endif - ) { + if (hostdata->connected && !hostdata->dma_len) { dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n"); NCR5380_information_transfer(instance); done = 0; @@ -919,34 +888,6 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", irq, basr, sr, mr); -#if defined(REAL_DMA) - if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { - /* Probably End of DMA, Phase Mismatch or Loss of BSY. - * We ack IRQ after clearing Mode Register. Workarounds - * for End of DMA errata need to happen in DMA Mode. - */ - - dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n"); - - int transferred; - - if (!hostdata->connected) - panic("scsi%d : DMA interrupt with no connected cmd\n", - instance->hostno); - - transferred = hostdata->dmalen - NCR5380_dma_residual(instance); - hostdata->connected->SCp.this_residual -= transferred; - hostdata->connected->SCp.ptr += transferred; - hostdata->dmalen = 0; - - /* FIXME: we need to poll briefly then defer a workqueue task ! */ - NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2 * HZ); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else -#endif /* REAL_DMA */ if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { /* Probably reselected */ @@ -1495,7 +1436,7 @@ static int do_abort(struct Scsi_Host *instance) return -1; } -#if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL) +#if defined(PSEUDO_DMA) /* * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) @@ -1525,34 +1466,14 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, register unsigned char *d = *data; unsigned char tmp; int foo; -#if defined(REAL_DMA_POLL) - int cnt, toPIO; - unsigned char saved_data = 0, overrun = 0, residue; -#endif if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { *phase = tmp; return -1; } -#if defined(REAL_DMA) || defined(REAL_DMA_POLL) - if (p & SR_IO) { - if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS)) - c -= 2; - } - hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c); - - dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", - (p & SR_IO) ? "receive" : "send", c, *data); -#endif NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); -#ifdef REAL_DMA - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | - MR_ENABLE_EOP_INTR); -#elif defined(REAL_DMA_POLL) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); -#else /* * Note : on my sample board, watch-dog timeouts occurred when interrupts * were not disabled for the duration of a single DMA transfer, from @@ -1564,7 +1485,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, MR_ENABLE_EOP_INTR); else NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); -#endif /* def REAL_DMA */ dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); @@ -1584,14 +1504,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, io_recovery_delay(1); } -#if defined(REAL_DMA_POLL) - do { - tmp = NCR5380_read(BUS_AND_STATUS_REG); - } while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR | BASR_END_DMA_TRANSFER))); - /* - * At this point, either we've completed DMA, or we have a phase mismatch, - * or we've unexpectedly lost BUSY (which is a real error). + * A note regarding the DMA errata workarounds for early NMOS silicon. * * For DMA sends, we want to wait until the last byte has been * transferred out over the bus before we turn off DMA mode. Alas, there @@ -1618,79 +1532,18 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * properly, or the target switches to MESSAGE IN phase to signal a * disconnection (either operation bringing the DMA to a clean halt). * However, in order to handle scatter-receive, we must work around the - * problem. The chosen fix is to DMA N-2 bytes, then check for the + * problem. The chosen fix is to DMA fewer bytes, then check for the * condition before taking the NCR5380 out of DMA mode. One or two extra * bytes are transferred via PIO as necessary to fill out the original * request. */ - if (p & SR_IO) { - if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS)) { - udelay(10); - if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == - (BASR_PHASE_MATCH | BASR_ACK)) { - saved_data = NCR5380_read(INPUT_DATA_REGISTER); - overrun = 1; - } - } - } else { - int limit = 100; - while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) || (NCR5380_read(STATUS_REG) & SR_REQ)) { - if (!(tmp & BASR_PHASE_MATCH)) - break; - if (--limit < 0) - break; - } - } - - dsprintk(NDEBUG_DMA, "polled DMA transfer complete, basr 0x%02x, sr 0x%02x\n", - tmp, NCR5380_read(STATUS_REG)); - - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - residue = NCR5380_dma_residual(instance); - c -= residue; - *count -= c; - *data += c; - *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; - - if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS) && - *phase == p && (p & SR_IO) && residue == 0) { - if (overrun) { - dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n"); - **data = saved_data; - *data += 1; - *count -= 1; - cnt = toPIO = 1; - } else { - printk("No overrun??\n"); - cnt = toPIO = 2; - } - dprintk(NDEBUG_DMA, "Doing %d-byte PIO to 0x%X\n", cnt, *data); - NCR5380_transfer_pio(instance, phase, &cnt, data); - *count -= toPIO - cnt; - } - - dprintk(NDEBUG_DMA, "Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count)); - return 0; - -#elif defined(REAL_DMA) - return 0; -#else /* defined(REAL_DMA_POLL) */ if (p & SR_IO) { foo = NCR5380_pread(instance, d, hostdata->flags & FLAG_NO_DMA_FIXUP ? c : c - 1); if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { /* - * We can't disable DMA mode after successfully transferring - * what we plan to be the last byte, since that would open up - * a race condition where if the target asserted REQ before - * we got the DMA mode reset, the NCR5380 would have latched - * an additional byte into the INPUT DATA register and we'd - * have dropped it. - * - * The workaround was to transfer one fewer bytes than we + * The workaround was to transfer fewer bytes than we * intended to with the pseudo-DMA read function, wait for * the chip to latch the last byte, read it, and then disable * pseudo-DMA mode. @@ -1738,9 +1591,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, *count = 0; *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; return foo; -#endif /* def REAL_DMA */ } -#endif /* defined(REAL_DMA) | defined(PSEUDO_DMA) */ +#endif /* PSEUDO_DMA */ /* * Function : NCR5380_information_transfer (struct Scsi_Host *instance) @@ -1831,7 +1683,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * in an unconditional loop. */ -#if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) +#if defined(PSEUDO_DMA) transfersize = 0; if (!cmd->device->borken) transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); @@ -1855,7 +1707,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) } else cmd->SCp.this_residual -= transfersize - len; } else -#endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */ +#endif /* PSEUDO_DMA */ { /* Break up transfer into 3 ms chunks, * presuming 6 accesses per handshake. @@ -2202,52 +2054,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) scmd_id(tmp), tmp->device->lun, tmp->tag); } -/* - * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) - * - * Purpose : called by interrupt handler when DMA finishes or a phase - * mismatch occurs (which would finish the DMA transfer). - * - * Inputs : instance - this instance of the NCR5380. - * - * Returns : pointer to the scsi_cmnd structure for which the I_T_L - * nexus has been reestablished, on failure NULL is returned. - */ - -#ifdef REAL_DMA -static void NCR5380_dma_complete(NCR5380_instance * instance) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int transferred; - - /* - * XXX this might not be right. - * - * Wait for final byte to transfer, ie wait for ACK to go false. - * - * We should use the Last Byte Sent bit, unfortunately this is - * not available on the 5380/5381 (only the various CMOS chips) - * - * FIXME: timeout, and need to handle long timeout/irq case - */ - - NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, BASR_ACK, 0, 5*HZ); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - /* - * The only places we should see a phase mismatch and have to send - * data from the same set of pointers will be the data transfer - * phases. So, residual, requested length are only important here. - */ - - if (!(hostdata->connected->SCp.phase & SR_CD)) { - transferred = instance->dmalen - NCR5380_dma_residual(); - hostdata->connected->SCp.this_residual -= transferred; - hostdata->connected->SCp.ptr += transferred; - } -} -#endif /* def REAL_DMA */ - /** * list_find_cmd - test for presence of a command in a linked list * @haystack: list of commands @@ -2359,9 +2165,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) if (hostdata->connected == cmd) { dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); hostdata->connected = NULL; -#ifdef REAL_DMA hostdata->dma_len = 0; -#endif if (do_abort(instance)) { set_host_byte(cmd, DID_ERROR); complete_cmd(instance, cmd); @@ -2464,9 +2268,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) for (i = 0; i < 8; ++i) hostdata->busy[i] = 0; -#ifdef REAL_DMA hostdata->dma_len = 0; -#endif queue_work(hostdata->work_q, &hostdata->main_task); spin_unlock_irqrestore(&hostdata->lock, flags); diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index a79288682a74..0b03ba25bd66 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -239,9 +239,7 @@ struct NCR5380_hostdata { struct Scsi_Host *host; /* Host backpointer */ unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */ unsigned char busy[8]; /* index = target, bit = lun */ -#if defined(REAL_DMA) || defined(REAL_DMA_POLL) int dma_len; /* requested length of DMA */ -#endif unsigned char last_message; /* last message OUT */ struct scsi_cmnd *connected; /* currently connected cmnd */ struct scsi_cmnd *selecting; /* cmnd to be connected */ @@ -319,118 +317,8 @@ static void NCR5380_main(struct work_struct *work); static const char *NCR5380_info(struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance); static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); -#if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL) static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); -#endif static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); -#if (defined(REAL_DMA) || defined(REAL_DMA_POLL)) - -#if defined(i386) || defined(__alpha__) - -/** - * NCR5380_pc_dma_setup - setup ISA DMA - * @instance: adapter to set up - * @ptr: block to transfer (virtual address) - * @count: number of bytes to transfer - * @mode: DMA controller mode to use - * - * Program the DMA controller ready to perform an ISA DMA transfer - * on this chip. - * - * Locks: takes and releases the ISA DMA lock. - */ - -static __inline__ int NCR5380_pc_dma_setup(struct Scsi_Host *instance, unsigned char *ptr, unsigned int count, unsigned char mode) -{ - unsigned limit; - unsigned long bus_addr = virt_to_bus(ptr); - unsigned long flags; - - if (instance->dma_channel <= 3) { - if (count > 65536) - count = 65536; - limit = 65536 - (bus_addr & 0xFFFF); - } else { - if (count > 65536 * 2) - count = 65536 * 2; - limit = 65536 * 2 - (bus_addr & 0x1FFFF); - } - - if (count > limit) - count = limit; - - if ((count & 1) || (bus_addr & 1)) - panic("scsi%d : attempted unaligned DMA transfer\n", instance->host_no); - - flags=claim_dma_lock(); - disable_dma(instance->dma_channel); - clear_dma_ff(instance->dma_channel); - set_dma_addr(instance->dma_channel, bus_addr); - set_dma_count(instance->dma_channel, count); - set_dma_mode(instance->dma_channel, mode); - enable_dma(instance->dma_channel); - release_dma_lock(flags); - - return count; -} - -/** - * NCR5380_pc_dma_write_setup - setup ISA DMA write - * @instance: adapter to set up - * @ptr: block to transfer (virtual address) - * @count: number of bytes to transfer - * - * Program the DMA controller ready to perform an ISA DMA write to the - * SCSI controller. - * - * Locks: called routines take and release the ISA DMA lock. - */ - -static __inline__ int NCR5380_pc_dma_write_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count) -{ - return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_WRITE); -} - -/** - * NCR5380_pc_dma_read_setup - setup ISA DMA read - * @instance: adapter to set up - * @ptr: block to transfer (virtual address) - * @count: number of bytes to transfer - * - * Program the DMA controller ready to perform an ISA DMA read from the - * SCSI controller. - * - * Locks: called routines take and release the ISA DMA lock. - */ - -static __inline__ int NCR5380_pc_dma_read_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count) -{ - return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_READ); -} - -/** - * NCR5380_pc_dma_residual - return bytes left - * @instance: adapter - * - * Reports the number of bytes left over after the DMA was terminated. - * - * Locks: takes and releases the ISA DMA lock. - */ - -static __inline__ int NCR5380_pc_dma_residual(struct Scsi_Host *instance) -{ - unsigned long flags; - int tmp; - - flags = claim_dma_lock(); - clear_dma_ff(instance->dma_channel); - tmp = get_dma_residue(instance->dma_channel); - release_dma_lock(flags); - - return tmp; -} -#endif /* defined(i386) || defined(__alpha__) */ -#endif /* defined(REAL_DMA) */ #endif /* __KERNEL__ */ #endif /* NCR5380_H */ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 389825ba5d96..c669098e34e1 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -112,15 +112,9 @@ * specific implementation of the NCR5380 * * Either real DMA *or* pseudo DMA may be implemented - * REAL functions : - * NCR5380_REAL_DMA should be defined if real DMA is to be used. * Note that the DMA setup functions should return the number of bytes * that they were able to program the controller for. * - * Also note that generic i386/PC versions of these macros are - * available as NCR5380_i386_dma_write_setup, - * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. - * * NCR5380_dma_write_setup(instance, src, count) - initialize * NCR5380_dma_read_setup(instance, dst, count) - initialize * NCR5380_dma_residual(instance); - residual count @@ -586,9 +580,6 @@ static void prepare_info(struct Scsi_Host *instance) #ifdef DIFFERENTIAL "DIFFERENTIAL " #endif -#ifdef REAL_DMA - "REAL_DMA " -#endif #ifdef PARITY "PARITY " #endif @@ -629,9 +620,8 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) #ifdef SUPPORT_TAGS init_tags(hostdata); #endif -#if defined (REAL_DMA) hostdata->dma_len = 0; -#endif + spin_lock_init(&hostdata->lock); hostdata->connected = NULL; hostdata->sensing = NULL; @@ -974,11 +964,7 @@ static void NCR5380_main(struct work_struct *work) #endif } } - if (hostdata->connected -#ifdef REAL_DMA - && !hostdata->dma_len -#endif - ) { + if (hostdata->connected && !hostdata->dma_len) { dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n"); NCR5380_information_transfer(instance); done = 0; @@ -990,7 +976,6 @@ static void NCR5380_main(struct work_struct *work) } -#ifdef REAL_DMA /* * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) * @@ -1071,7 +1056,6 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) } } } -#endif /* REAL_DMA */ /** @@ -1126,7 +1110,6 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", irq, basr, sr, mr); -#if defined(REAL_DMA) if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { /* Probably End of DMA, Phase Mismatch or Loss of BSY. * We ack IRQ after clearing Mode Register. Workarounds @@ -1142,9 +1125,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) NCR5380_write(MODE_REG, MR_BASE); NCR5380_read(RESET_PARITY_INTERRUPT_REG); } - } else -#endif /* REAL_DMA */ - if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && + } else if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { /* Probably reselected */ NCR5380_write(SELECT_ENABLE_REG, 0); @@ -1710,7 +1691,7 @@ static int do_abort(struct Scsi_Host *instance) return -1; } -#if defined(REAL_DMA) + /* * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) @@ -1819,7 +1800,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, return 0; } -#endif /* defined(REAL_DMA) */ /* * Function : NCR5380_information_transfer (struct Scsi_Host *instance) @@ -1866,7 +1846,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) } #if defined(CONFIG_SUN3) if (phase == PHASE_CMDOUT) { -#if defined(REAL_DMA) void *d; unsigned long count; @@ -1885,7 +1864,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) sun3_dma_setup_done = cmd; } } -#endif #ifdef SUN3_SCSI_VME dregs->csr |= CSR_INTR; #endif @@ -1943,12 +1921,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * in an unconditional loop. */ - /* ++roman: I suggest, this should be - * #if def(REAL_DMA) - * instead of leaving REAL_DMA out. - */ - -#if defined(REAL_DMA) #if !defined(CONFIG_SUN3) transfersize = 0; if (!cmd->device->borken) @@ -1972,21 +1944,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) do_abort(instance); cmd->result = DID_ERROR << 16; /* XXX - need to source or sink data here, as appropriate */ - } else { -#ifdef REAL_DMA - /* ++roman: When using real DMA, - * information_transfer() should return after - * starting DMA since it has nothing more to - * do. - */ + } else return; -#else - cmd->SCp.this_residual -= transfersize - len; -#endif - } - } else -#endif /* defined(REAL_DMA) */ - { + } else { /* Break up transfer into 3 ms chunks, * presuming 6 accesses per handshake. */ @@ -1997,7 +1957,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) (unsigned char **)&cmd->SCp.ptr); cmd->SCp.this_residual -= transfersize - len; } -#if defined(CONFIG_SUN3) && defined(REAL_DMA) +#if defined(CONFIG_SUN3) /* if we had intended to dma that command clear it */ if (sun3_dma_setup_done == cmd) sun3_dma_setup_done = NULL; @@ -2305,7 +2265,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) return; } -#if defined(CONFIG_SUN3) && defined(REAL_DMA) +#if defined(CONFIG_SUN3) /* acknowledge toggle to MSGIN */ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN)); @@ -2392,7 +2352,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) return; } -#if defined(CONFIG_SUN3) && defined(REAL_DMA) +#if defined(CONFIG_SUN3) /* engage dma setup for the command we just saw */ { void *d; @@ -2555,9 +2515,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) if (hostdata->connected == cmd) { dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); hostdata->connected = NULL; -#ifdef REAL_DMA hostdata->dma_len = 0; -#endif if (do_abort(instance)) { set_host_byte(cmd, DID_ERROR); complete_cmd(instance, cmd); @@ -2664,9 +2622,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) #endif for (i = 0; i < 8; ++i) hostdata->busy[i] = 0; -#ifdef REAL_DMA hostdata->dma_len = 0; -#endif queue_work(hostdata->work_q, &hostdata->main_task); maybe_release_dma_irq(instance); diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 78d1b2963f2c..c68e895e971f 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -85,7 +85,6 @@ /* Definitions for the core NCR5380 driver. */ -#define REAL_DMA #define SUPPORT_TAGS #define MAX_TAGS 32 #define DMA_MIN_SIZE 32 @@ -159,14 +158,11 @@ static inline unsigned long SCSI_DMA_GETADR(void) return adr; } -#ifdef REAL_DMA static void atari_scsi_fetch_restbytes(void); -#endif static unsigned char (*atari_scsi_reg_read)(unsigned char reg); static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value); -#ifdef REAL_DMA static unsigned long atari_dma_residual, atari_dma_startaddr; static short atari_dma_active; /* pointer to the dribble buffer */ @@ -185,7 +181,6 @@ static char *atari_dma_orig_addr; /* mask for address bits that can't be used with the ST-DMA */ static unsigned long atari_dma_stram_mask; #define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0) -#endif static int setup_can_queue = -1; module_param(setup_can_queue, int, 0); @@ -201,8 +196,6 @@ static int setup_toshiba_delay = -1; module_param(setup_toshiba_delay, int, 0); -#if defined(REAL_DMA) - static int scsi_dma_is_ignored_buserr(unsigned char dma_stat) { int i; @@ -255,12 +248,9 @@ static void scsi_dma_buserr(int irq, void *dummy) } #endif -#endif - static irqreturn_t scsi_tt_intr(int irq, void *dev) { -#ifdef REAL_DMA struct Scsi_Host *instance = dev; struct NCR5380_hostdata *hostdata = shost_priv(instance); int dma_stat; @@ -342,8 +332,6 @@ static irqreturn_t scsi_tt_intr(int irq, void *dev) tt_scsi_dma.dma_ctrl = 0; } -#endif /* REAL_DMA */ - NCR5380_intr(irq, dev); return IRQ_HANDLED; @@ -352,7 +340,6 @@ static irqreturn_t scsi_tt_intr(int irq, void *dev) static irqreturn_t scsi_falcon_intr(int irq, void *dev) { -#ifdef REAL_DMA struct Scsi_Host *instance = dev; struct NCR5380_hostdata *hostdata = shost_priv(instance); int dma_stat; @@ -405,15 +392,12 @@ static irqreturn_t scsi_falcon_intr(int irq, void *dev) atari_dma_orig_addr = NULL; } -#endif /* REAL_DMA */ - NCR5380_intr(irq, dev); return IRQ_HANDLED; } -#ifdef REAL_DMA static void atari_scsi_fetch_restbytes(void) { int nr; @@ -436,7 +420,6 @@ static void atari_scsi_fetch_restbytes(void) *dst++ = *src++; } } -#endif /* REAL_DMA */ /* This function releases the lock on the DMA chip if there is no @@ -508,8 +491,6 @@ __setup("atascsi=", atari_scsi_setup); #endif /* !MODULE */ -#if defined(REAL_DMA) - static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, void *data, unsigned long count, int dir) @@ -703,9 +684,6 @@ static unsigned long atari_dma_xfer_len(unsigned long wanted_len, } -#endif /* REAL_DMA */ - - /* NCR5380 register access functions * * There are separate functions for TT and Falcon, because the access @@ -745,7 +723,6 @@ static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) local_irq_save(flags); -#ifdef REAL_DMA /* Abort a maybe active DMA transfer */ if (IS_A_TT()) { tt_scsi_dma.dma_ctrl = 0; @@ -754,7 +731,6 @@ static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) atari_dma_active = 0; atari_dma_orig_addr = NULL; } -#endif rv = NCR5380_bus_reset(cmd); @@ -850,8 +826,6 @@ static int __init atari_scsi_probe(struct platform_device *pdev) } } - -#ifdef REAL_DMA /* If running on a Falcon and if there's TT-Ram (i.e., more than one * memory block, since there's always ST-Ram in a Falcon), then * allocate a STRAM_BUFFER_SIZE byte dribble buffer for transfers @@ -867,7 +841,6 @@ static int __init atari_scsi_probe(struct platform_device *pdev) atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer); atari_dma_orig_addr = 0; } -#endif instance = scsi_host_alloc(&atari_scsi_template, sizeof(struct NCR5380_hostdata)); @@ -897,7 +870,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev) goto fail_irq; } tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */ -#ifdef REAL_DMA + tt_scsi_dma.dma_ctrl = 0; atari_dma_residual = 0; @@ -919,17 +892,14 @@ static int __init atari_scsi_probe(struct platform_device *pdev) hostdata->read_overruns = 4; } -#endif } else { /* Nothing to do for the interrupt: the ST-DMA is initialized * already. */ -#ifdef REAL_DMA atari_dma_residual = 0; atari_dma_active = 0; atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000); -#endif } NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index b9de487bbd31..5551b1623ed6 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -38,7 +38,6 @@ /* Definitions for the core NCR5380 driver. */ -#define REAL_DMA /* #define SUPPORT_TAGS */ /* minimum number of bytes to do dma on */ #define DMA_MIN_SIZE 129 @@ -527,15 +526,9 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) error = request_irq(instance->irq, scsi_sun3_intr, 0, "NCR5380", instance); if (error) { -#ifdef REAL_DMA pr_err(PFX "scsi%d: IRQ %d not free, bailing out\n", instance->host_no, instance->irq); goto fail_irq; -#else - pr_warn(PFX "scsi%d: IRQ %d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = NO_IRQ; -#endif } dregs->csr = 0; @@ -565,8 +558,7 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) return 0; fail_host: - if (instance->irq != NO_IRQ) - free_irq(instance->irq, instance); + free_irq(instance->irq, instance); fail_irq: NCR5380_exit(instance); fail_init: @@ -583,8 +575,7 @@ static int __exit sun3_scsi_remove(struct platform_device *pdev) struct Scsi_Host *instance = platform_get_drvdata(pdev); scsi_remove_host(instance); - if (instance->irq != NO_IRQ) - free_irq(instance->irq, instance); + free_irq(instance->irq, instance); NCR5380_exit(instance); scsi_host_put(instance); if (udc_regs) From e63449c43a58fc185ff35ace6a842817f57ec6c8 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:13 +1100 Subject: [PATCH 007/138] atari_NCR5380: Remove DMA_MIN_SIZE macro Only the atari_scsi and sun3_scsi drivers define DMA_MIN_SIZE. Both drivers also define NCR5380_dma_xfer_len, which means DMA_MIN_SIZE can be removed from the core driver. This removes another discrepancy between the two core drivers. Signed-off-by: Finn Thain Tested-by: Michael Schmitz Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_NCR5380.c | 16 ++++++++-------- drivers/scsi/atari_scsi.c | 6 +++++- drivers/scsi/sun3_scsi.c | 19 +++++++++---------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index c669098e34e1..4101d2de4333 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1857,12 +1857,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) d = cmd->SCp.ptr; } /* this command setup for dma yet? */ - if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != cmd)) { - if (cmd->request->cmd_type == REQ_TYPE_FS) { - sun3scsi_dma_setup(instance, d, count, - rq_data_dir(cmd->request)); - sun3_dma_setup_done = cmd; - } + if (sun3_dma_setup_done != cmd && + sun3scsi_dma_xfer_len(count, cmd) > 0) { + sun3scsi_dma_setup(instance, d, count, + rq_data_dir(cmd->request)); + sun3_dma_setup_done = cmd; } #ifdef SUN3_SCSI_VME dregs->csr |= CSR_INTR; @@ -1927,7 +1926,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #endif transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); - if (transfersize >= DMA_MIN_SIZE) { + if (transfersize > 0) { len = transfersize; cmd->SCp.phase = phase; if (NCR5380_transfer_dma(instance, &phase, @@ -2366,7 +2365,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) d = tmp->SCp.ptr; } /* setup this command for dma if not already */ - if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != tmp)) { + if (sun3_dma_setup_done != tmp && + sun3scsi_dma_xfer_len(count, tmp) > 0) { sun3scsi_dma_setup(instance, d, count, rq_data_dir(tmp->request)); sun3_dma_setup_done = tmp; diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index c68e895e971f..41ddd95cebe6 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -83,11 +83,12 @@ #include +#define DMA_MIN_SIZE 32 + /* Definitions for the core NCR5380 driver. */ #define SUPPORT_TAGS #define MAX_TAGS 32 -#define DMA_MIN_SIZE 32 #define NCR5380_implementation_fields /* none */ @@ -605,6 +606,9 @@ static unsigned long atari_dma_xfer_len(unsigned long wanted_len, { unsigned long possible_len, limit; + if (wanted_len < DMA_MIN_SIZE) + return 0; + if (IS_A_TT()) /* TT SCSI DMA can transfer arbitrary #bytes */ return wanted_len; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 5551b1623ed6..fd4fad816ad4 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -36,12 +36,12 @@ #include #include "sun3_scsi.h" -/* Definitions for the core NCR5380 driver. */ - -/* #define SUPPORT_TAGS */ /* minimum number of bytes to do dma on */ #define DMA_MIN_SIZE 129 +/* Definitions for the core NCR5380 driver. */ + +/* #define SUPPORT_TAGS */ /* #define MAX_TAGS 32 */ #define NCR5380_implementation_fields /* none */ @@ -61,7 +61,7 @@ #define NCR5380_dma_residual(instance) \ sun3scsi_dma_residual(instance) #define NCR5380_dma_xfer_len(instance, cmd, phase) \ - sun3scsi_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO)) + sun3scsi_dma_xfer_len(cmd->SCp.this_residual, cmd) #define NCR5380_acquire_dma_irq(instance) (1) #define NCR5380_release_dma_irq(instance) @@ -262,14 +262,13 @@ static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) return last_residual; } -static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, - struct scsi_cmnd *cmd, - int write_flag) +static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted_len, + struct scsi_cmnd *cmd) { - if (cmd->request->cmd_type == REQ_TYPE_FS) - return wanted; - else + if (wanted_len < DMA_MIN_SIZE || cmd->request->cmd_type != REQ_TYPE_FS) return 0; + + return wanted_len; } static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data) From 1bb4600245d4d40245dd505ca17528e0b9a9ba8c Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:14 +1100 Subject: [PATCH 008/138] ncr5380: Disable the DMA errata workaround flag by default The only chip that needs the workarounds enabled is an early NMOS device. That means that the common case is to disable them. Unfortunately the sense of the flag is such that it has to be set for the common case. Rename the flag so that zero can be used to mean "no errata workarounds needed". This simplifies the code. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 14 +++++++------- drivers/scsi/NCR5380.h | 2 +- drivers/scsi/arm/cumana_1.c | 2 +- drivers/scsi/arm/oak.c | 2 +- drivers/scsi/dtc.c | 2 +- drivers/scsi/g_NCR5380.c | 8 +------- drivers/scsi/pas16.c | 2 +- drivers/scsi/t128.c | 2 +- 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 826b63d1aa84..69c73c36b923 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -457,7 +457,7 @@ static void prepare_info(struct Scsi_Host *instance) instance->base, instance->irq, instance->can_queue, instance->cmd_per_lun, instance->sg_tablesize, instance->this_id, - hostdata->flags & FLAG_NO_DMA_FIXUP ? "NO_DMA_FIXUP " : "", + hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "", hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", #ifdef AUTOPROBE_IRQ @@ -1480,11 +1480,11 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * before the setting of DMA mode to after transfer of the last byte. */ - if (hostdata->flags & FLAG_NO_DMA_FIXUP) + if (hostdata->flags & FLAG_DMA_FIXUP) + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); + else NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | MR_ENABLE_EOP_INTR); - else - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); @@ -1540,8 +1540,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, if (p & SR_IO) { foo = NCR5380_pread(instance, d, - hostdata->flags & FLAG_NO_DMA_FIXUP ? c : c - 1); - if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { + hostdata->flags & FLAG_DMA_FIXUP ? c - 1 : c); + if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * The workaround was to transfer fewer bytes than we * intended to with the pseudo-DMA read function, wait for @@ -1571,7 +1571,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, } } else { foo = NCR5380_pwrite(instance, d, c); - if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { + if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * Wait for the last byte to be sent. If REQ is being asserted for * the byte we're interested, we'll ACK it and it will go false. diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 0b03ba25bd66..7b488a082462 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -220,7 +220,7 @@ #define NO_IRQ 0 #endif -#define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */ +#define FLAG_DMA_FIXUP 1 /* Use DMA errata workarounds */ #define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */ #define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */ #define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */ diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 221f18c5df93..76b2d3364d9f 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -239,7 +239,7 @@ static int cumanascsi1_probe(struct expansion_card *ec, host->irq = ec->irq; - ret = NCR5380_init(host, 0); + ret = NCR5380_init(host, FLAG_DMA_FIXUP); if (ret) goto out_unmap; diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 1fab1d1896b1..8d8426535e6d 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -143,7 +143,7 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) host->irq = NO_IRQ; host->n_io_port = 255; - ret = NCR5380_init(host, 0); + ret = NCR5380_init(host, FLAG_DMA_FIXUP); if (ret) goto out_unmap; diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 6c736b071cf4..30919f42759a 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -229,7 +229,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) instance->base = addr; ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; - if (NCR5380_init(instance, FLAG_NO_DMA_FIXUP)) + if (NCR5380_init(instance, 0)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index b8fc26d9231d..aaeb6b6b4b16 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -348,23 +348,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) flags = 0; switch (overrides[current_override].board) { case BOARD_NCR5380: - flags = FLAG_NO_PSEUDO_DMA; - break; - case BOARD_NCR53C400: - flags = FLAG_NO_DMA_FIXUP; + flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP; break; case BOARD_NCR53C400A: - flags = FLAG_NO_DMA_FIXUP; ports = ncr_53c400a_ports; magic = ncr_53c400a_magic; break; case BOARD_HP_C2502: - flags = FLAG_NO_DMA_FIXUP; ports = ncr_53c400a_ports; magic = hp_c2502_magic; break; case BOARD_DTC3181E: - flags = FLAG_NO_DMA_FIXUP; ports = dtc_3181e_ports; magic = ncr_53c400a_magic; break; diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 512037e27783..7589fea01186 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -377,7 +377,7 @@ static int __init pas16_detect(struct scsi_host_template *tpnt) instance->io_port = io_port; - if (NCR5380_init(instance, 0)) + if (NCR5380_init(instance, FLAG_DMA_FIXUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 4615fda60dbd..6cb8bdd2f4e6 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -210,7 +210,7 @@ static int __init t128_detect(struct scsi_host_template *tpnt) instance->base = base; ((struct NCR5380_hostdata *)instance->hostdata)->base = p; - if (NCR5380_init(instance, 0)) + if (NCR5380_init(instance, FLAG_DMA_FIXUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); From f825e40b235f4daf1c9017366809d34c7f5c8c7f Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:15 +1100 Subject: [PATCH 009/138] ncr5380: Remove PSEUDO_DMA macro For those wrapper drivers which only implement Programmed IO, have NCR5380_dma_xfer_len() evaluate to zero. That allows PDMA to be easily disabled at run-time and so the PSEUDO_DMA macro is no longer needed. Also remove the spin counters used for debugging pseudo DMA drivers. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 32 +------------------------------- drivers/scsi/NCR5380.h | 4 ---- drivers/scsi/arm/cumana_1.c | 2 -- drivers/scsi/arm/oak.c | 3 +-- drivers/scsi/dmx3191d.c | 4 ++++ drivers/scsi/dtc.c | 7 ------- drivers/scsi/dtc.h | 2 -- drivers/scsi/g_NCR5380.c | 1 - drivers/scsi/g_NCR5380.h | 1 - drivers/scsi/mac_scsi.c | 10 ---------- drivers/scsi/pas16.c | 10 ---------- drivers/scsi/pas16.h | 2 -- drivers/scsi/t128.c | 4 ---- drivers/scsi/t128.h | 2 -- 14 files changed, 6 insertions(+), 78 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 69c73c36b923..fc86cde2d28e 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -468,35 +468,10 @@ static void prepare_info(struct Scsi_Host *instance) #endif #ifdef PARITY "PARITY " -#endif -#ifdef PSEUDO_DMA - "PSEUDO_DMA " #endif ""); } -#ifdef PSEUDO_DMA -static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance, - char *buffer, int length) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - hostdata->spin_max_r = 0; - hostdata->spin_max_w = 0; - return 0; -} - -static int __maybe_unused NCR5380_show_info(struct seq_file *m, - struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - seq_printf(m, "Highwater I/O busy spin counts: write %d, read %d\n", - hostdata->spin_max_w, hostdata->spin_max_r); - return 0; -} -#endif - /** * NCR5380_init - initialise an NCR5380 * @instance: adapter to configure @@ -1436,7 +1411,6 @@ static int do_abort(struct Scsi_Host *instance) return -1; } -#if defined(PSEUDO_DMA) /* * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) @@ -1592,7 +1566,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; return foo; } -#endif /* PSEUDO_DMA */ /* * Function : NCR5380_information_transfer (struct Scsi_Host *instance) @@ -1683,7 +1656,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * in an unconditional loop. */ -#if defined(PSEUDO_DMA) transfersize = 0; if (!cmd->device->borken) transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); @@ -1706,9 +1678,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* XXX - need to source or sink data here, as appropriate */ } else cmd->SCp.this_residual -= transfersize - len; - } else -#endif /* PSEUDO_DMA */ - { + } else { /* Break up transfer into 3 ms chunks, * presuming 6 accesses per handshake. */ diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 7b488a082462..8adf7377de4c 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -256,10 +256,6 @@ struct NCR5380_hostdata { struct work_struct main_task; #ifdef SUPPORT_TAGS struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */ -#endif -#ifdef PSEUDO_DMA - unsigned spin_max_r; - unsigned spin_max_w; #endif struct workqueue_struct *work_q; unsigned long accesses_per_ms; /* chip register accesses per ms */ diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 76b2d3364d9f..6e9de19fc3c2 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -13,8 +13,6 @@ #include -#define PSEUDO_DMA - #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) #define NCR5380_read(reg) cumanascsi_read(instance, reg) #define NCR5380_write(reg, value) cumanascsi_write(instance, reg, value) diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 8d8426535e6d..63abd6b248a6 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -14,7 +14,6 @@ #include -/*#define PSEUDO_DMA*/ #define DONT_USE_INTR #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) @@ -24,7 +23,7 @@ #define NCR5380_write(reg, value) \ writeb(value, priv(instance)->base + ((reg) << 2)) -#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) +#define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index e9e96af96104..929bc1b618f8 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -39,6 +39,10 @@ #define NCR5380_read(reg) inb(instance->io_port + reg) #define NCR5380_write(reg, value) outb(value, instance->io_port + reg) +#define NCR5380_dma_xfer_len(instance, cmd, phase) (0) +#define NCR5380_pread(instance, dst, len) (0) +#define NCR5380_pwrite(instance, src, len) (0) + #define NCR5380_implementation_fields /* none */ #include "NCR5380.h" diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 30919f42759a..30d3e73f70ca 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -1,4 +1,3 @@ -#define PSEUDO_DMA #define DONT_USE_INTR /* @@ -352,8 +351,6 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) ++i; rtrc(0); - if (i > hostdata->spin_max_r) - hostdata->spin_max_r = i; return (0); } @@ -400,8 +397,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, rtrc(7); /* Check for parity error here. fixme. */ rtrc(0); - if (i > hostdata->spin_max_w) - hostdata->spin_max_w = i; return (0); } @@ -440,8 +435,6 @@ static struct scsi_host_template driver_template = { .detect = dtc_detect, .release = dtc_release, .proc_name = "dtc3x80", - .show_info = dtc_show_info, - .write_info = dtc_write_info, .info = dtc_info, .queuecommand = dtc_queue_command, .eh_abort_handler = dtc_abort, diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 56732cba8aba..1bc638730dda 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -27,8 +27,6 @@ #define NCR5380_abort dtc_abort #define NCR5380_bus_reset dtc_bus_reset #define NCR5380_info dtc_info -#define NCR5380_show_info dtc_show_info -#define NCR5380_write_info dtc_write_info /* 15 12 11 10 1001 1100 0000 0000 */ diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index aaeb6b6b4b16..fc7bcbcf3f43 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -57,7 +57,6 @@ */ #define AUTOPROBE_IRQ -#define PSEUDO_DMA #include #include diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 3fb0d8529429..a231a8c52d87 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -70,7 +70,6 @@ #define NCR5380_pread generic_NCR5380_pread #define NCR5380_pwrite generic_NCR5380_pwrite #define NCR5380_info generic_NCR5380_info -#define NCR5380_show_info generic_NCR5380_show_info #define BOARD_NCR5380 0 #define BOARD_NCR53C400 1 diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index a8f5433b515e..1e0d07ac83a1 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -28,8 +28,6 @@ /* Definitions for the core NCR5380 driver. */ -#define PSEUDO_DMA - #define NCR5380_implementation_fields unsigned char *pdma_base #define NCR5380_read(reg) macscsi_read(instance, reg) @@ -46,8 +44,6 @@ #define NCR5380_abort macscsi_abort #define NCR5380_bus_reset macscsi_bus_reset #define NCR5380_info macscsi_info -#define NCR5380_show_info macscsi_show_info -#define NCR5380_write_info macscsi_write_info #include "NCR5380.h" @@ -111,7 +107,6 @@ static int __init mac_scsi_setup(char *str) __setup("mac5380=", mac_scsi_setup); #endif /* !MODULE */ -#ifdef PSEUDO_DMA /* Pseudo-DMA: (Ove Edlund) The code attempts to catch bus errors that occur if one for example @@ -303,7 +298,6 @@ static int macscsi_pwrite(struct Scsi_Host *instance, return 0; } -#endif static int macscsi_dma_xfer_len(struct Scsi_Host *instance, struct scsi_cmnd *cmd) @@ -324,8 +318,6 @@ static int macscsi_dma_xfer_len(struct Scsi_Host *instance, static struct scsi_host_template mac_scsi_template = { .module = THIS_MODULE, .proc_name = DRV_MODULE_NAME, - .show_info = macscsi_show_info, - .write_info = macscsi_write_info, .name = "Macintosh NCR5380 SCSI", .info = macscsi_info, .queuecommand = macscsi_queue_command, @@ -351,9 +343,7 @@ static int __init mac_scsi_probe(struct platform_device *pdev) if (!pio_mem) return -ENODEV; -#ifdef PSEUDO_DMA pdma_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); -#endif irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 7589fea01186..9c06eb637417 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -1,5 +1,3 @@ -#define PSEUDO_DMA - /* * This driver adapted from Drew Eckhardt's Trantor T128 driver * @@ -479,7 +477,6 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, P_DATA_REG_OFFSET); register int i = len; int ii = 0; - struct NCR5380_hostdata *hostdata = shost_priv(instance); while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) ) ++ii; @@ -492,8 +489,6 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, instance->host_no); return -1; } - if (ii > hostdata->spin_max_r) - hostdata->spin_max_r = ii; return 0; } @@ -516,7 +511,6 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET); register int i = len; int ii = 0; - struct NCR5380_hostdata *hostdata = shost_priv(instance); while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) ) ++ii; @@ -529,8 +523,6 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src instance->host_no); return -1; } - if (ii > hostdata->spin_max_w) - hostdata->spin_max_w = ii; return 0; } @@ -550,8 +542,6 @@ static struct scsi_host_template driver_template = { .detect = pas16_detect, .release = pas16_release, .proc_name = "pas16", - .show_info = pas16_show_info, - .write_info = pas16_write_info, .info = pas16_info, .queuecommand = pas16_queue_command, .eh_abort_handler = pas16_abort, diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index d37527717225..1695885ce40c 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -109,8 +109,6 @@ #define NCR5380_abort pas16_abort #define NCR5380_bus_reset pas16_bus_reset #define NCR5380_info pas16_info -#define NCR5380_show_info pas16_show_info -#define NCR5380_write_info pas16_write_info /* 15 14 12 10 7 5 3 1101 0100 1010 1000 */ diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 6cb8bdd2f4e6..ce2395f3fae9 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -1,5 +1,3 @@ -#define PSEUDO_DMA - /* * Trantor T128/T128F/T228 driver * Note : architecturally, the T100 and T130 are different and won't @@ -394,8 +392,6 @@ static struct scsi_host_template driver_template = { .detect = t128_detect, .release = t128_release, .proc_name = "t128", - .show_info = t128_show_info, - .write_info = t128_write_info, .info = t128_info, .queuecommand = t128_queue_command, .eh_abort_handler = t128_abort, diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index dd16d85497e1..c369b50de746 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -83,8 +83,6 @@ #define NCR5380_abort t128_abort #define NCR5380_bus_reset t128_bus_reset #define NCR5380_info t128_info -#define NCR5380_show_info t128_show_info -#define NCR5380_write_info t128_write_info /* 15 14 12 10 7 5 3 1101 0100 1010 1000 */ From e5d55d1abcef09f7440e6211d5bd673baf547630 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:16 +1100 Subject: [PATCH 010/138] ncr5380: Remove BOARD_REQUIRES_NO_DELAY macro The io_recovery_delay macro is intended to insert a microsecond delay between the chip register accesses that begin a DMA operation. This is reportedly needed for some ISA boards. Reverse the sense of the macro test so that in the common case, where no delay is required, drivers need not define the macro. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 18 ++++++++---------- drivers/scsi/dtc.h | 2 ++ drivers/scsi/g_NCR5380.h | 2 ++ drivers/scsi/t128.h | 2 ++ 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index fc86cde2d28e..014a01f6875f 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -39,12 +39,6 @@ * tagged queueing) */ -#ifdef BOARD_REQUIRES_NO_DELAY -#define io_recovery_delay(x) -#else -#define io_recovery_delay(x) udelay(x) -#endif - /* * Design * @@ -150,6 +144,10 @@ * possible) function may be used. */ +#ifndef NCR5380_io_delay +#define NCR5380_io_delay(x) +#endif + static int do_abort(struct Scsi_Host *); static void do_reset(struct Scsi_Host *); @@ -1468,14 +1466,14 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (p & SR_IO) { - io_recovery_delay(1); + NCR5380_io_delay(1); NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); } else { - io_recovery_delay(1); + NCR5380_io_delay(1); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); - io_recovery_delay(1); + NCR5380_io_delay(1); NCR5380_write(START_DMA_SEND_REG, 0); - io_recovery_delay(1); + NCR5380_io_delay(1); } /* diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 1bc638730dda..718f95adcec6 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -28,6 +28,8 @@ #define NCR5380_bus_reset dtc_bus_reset #define NCR5380_info dtc_info +#define NCR5380_io_delay(x) udelay(x) + /* 15 12 11 10 1001 1100 0000 0000 */ diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index a231a8c52d87..637740f4c6c7 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -71,6 +71,8 @@ #define NCR5380_pwrite generic_NCR5380_pwrite #define NCR5380_info generic_NCR5380_info +#define NCR5380_io_delay(x) udelay(x) + #define BOARD_NCR5380 0 #define BOARD_NCR53C400 1 #define BOARD_NCR53C400A 2 diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index c369b50de746..4caea9d62ac4 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -84,6 +84,8 @@ #define NCR5380_bus_reset t128_bus_reset #define NCR5380_info t128_info +#define NCR5380_io_delay(x) udelay(x) + /* 15 14 12 10 7 5 3 1101 0100 1010 1000 */ From 6c4b88ca59ba1a68f707f19dba1744ed19e89fce Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:17 +1100 Subject: [PATCH 011/138] ncr5380: Use DMA hooks for PDMA Those wrapper drivers which use DMA define the REAL_DMA macro and those which use pseudo DMA define PSEUDO_DMA. These macros need to be removed for a number of reasons, not least of which is to have drivers share more code. Redefine the PDMA send and receive hooks as DMA setup hooks, so that the DMA code can be shared by all 5380 wrapper drivers. This will help to reunify the forked core driver. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 10 ++-------- drivers/scsi/arm/cumana_1.c | 10 ++++++---- drivers/scsi/arm/oak.c | 10 ++++++---- drivers/scsi/dmx3191d.c | 4 ++-- drivers/scsi/dtc.c | 6 ++++-- drivers/scsi/dtc.h | 2 ++ drivers/scsi/g_NCR5380.c | 10 ++++++---- drivers/scsi/g_NCR5380.h | 4 ++-- drivers/scsi/mac_scsi.c | 5 ++--- drivers/scsi/pas16.c | 14 ++++++++------ drivers/scsi/pas16.h | 2 ++ drivers/scsi/t128.c | 12 ++++++------ drivers/scsi/t128.h | 2 ++ 13 files changed, 50 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 014a01f6875f..b3e5b6b57d83 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -127,17 +127,11 @@ * specific implementation of the NCR5380 * * Either real DMA *or* pseudo DMA may be implemented - * Note that the DMA setup functions should return the number of bytes - * that they were able to program the controller for. * * NCR5380_dma_write_setup(instance, src, count) - initialize * NCR5380_dma_read_setup(instance, dst, count) - initialize * NCR5380_dma_residual(instance); - residual count * - * PSEUDO functions : - * NCR5380_pwrite(instance, src, count) - * NCR5380_pread(instance, dst, count); - * * The generic driver is initialized by calling NCR5380_init(instance), * after setting the appropriate host specific fields and ID. If the * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, @@ -1511,7 +1505,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (p & SR_IO) { - foo = NCR5380_pread(instance, d, + foo = NCR5380_dma_recv_setup(instance, d, hostdata->flags & FLAG_DMA_FIXUP ? c - 1 : c); if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { /* @@ -1542,7 +1536,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, d[c - 1] = NCR5380_read(INPUT_DATA_REG); } } else { - foo = NCR5380_pwrite(instance, d, c); + foo = NCR5380_dma_send_setup(instance, d, c); if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * Wait for the last byte to be sent. If REQ is being asserted for diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 6e9de19fc3c2..7bcb66893059 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -18,6 +18,8 @@ #define NCR5380_write(reg, value) cumanascsi_write(instance, reg, value) #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) +#define NCR5380_dma_recv_setup cumanascsi_pread +#define NCR5380_dma_send_setup cumanascsi_pwrite #define NCR5380_intr cumanascsi_intr #define NCR5380_queue_command cumanascsi_queue_command @@ -39,8 +41,8 @@ void cumanascsi_setup(char *str, int *ints) #define L(v) (((v)<<16)|((v) & 0x0000ffff)) #define H(v) (((v)>>16)|((v) & 0xffff0000)) -static inline int -NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, int len) +static inline int cumanascsi_pwrite(struct Scsi_Host *host, + unsigned char *addr, int len) { unsigned long *laddr; void __iomem *dma = priv(host)->dma + 0x2000; @@ -102,8 +104,8 @@ NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, int len) return len; } -static inline int -NCR5380_pread(struct Scsi_Host *host, unsigned char *addr, int len) +static inline int cumanascsi_pread(struct Scsi_Host *host, + unsigned char *addr, int len) { unsigned long *laddr; void __iomem *dma = priv(host)->dma + 0x2000; diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 63abd6b248a6..5d6e0e590638 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -24,6 +24,8 @@ writeb(value, priv(instance)->base + ((reg) << 2)) #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) +#define NCR5380_dma_recv_setup oakscsi_pread +#define NCR5380_dma_send_setup oakscsi_pwrite #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info @@ -39,8 +41,8 @@ #define STAT ((128 + 16) << 2) #define DATA ((128 + 8) << 2) -static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, - int len) +static inline int oakscsi_pwrite(struct Scsi_Host *instance, + unsigned char *addr, int len) { void __iomem *base = priv(instance)->base; @@ -54,8 +56,8 @@ printk("writing %p len %d\n",addr, len); } } -static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, - int len) +static inline int oakscsi_pread(struct Scsi_Host *instance, + unsigned char *addr, int len) { void __iomem *base = priv(instance)->base; printk("reading %p len %d\n", addr, len); diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 929bc1b618f8..4b58fa0c16fe 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -40,8 +40,8 @@ #define NCR5380_write(reg, value) outb(value, instance->io_port + reg) #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) -#define NCR5380_pread(instance, dst, len) (0) -#define NCR5380_pwrite(instance, src, len) (0) +#define NCR5380_dma_recv_setup(instance, dst, len) (0) +#define NCR5380_dma_send_setup(instance, src, len) (0) #define NCR5380_implementation_fields /* none */ diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 30d3e73f70ca..df17904bbe12 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -322,7 +322,8 @@ static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev, * timeout. */ -static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) +static inline int dtc_pread(struct Scsi_Host *instance, + unsigned char *dst, int len) { unsigned char *d = dst; int i; /* For counting time spent in the poll-loop */ @@ -367,7 +368,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, * timeout. */ -static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) +static inline int dtc_pwrite(struct Scsi_Host *instance, + unsigned char *src, int len) { int i; struct NCR5380_hostdata *hostdata = shost_priv(instance); diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 718f95adcec6..65af89e4340c 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -21,6 +21,8 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) \ dtc_dma_xfer_len(cmd) +#define NCR5380_dma_recv_setup dtc_pread +#define NCR5380_dma_send_setup dtc_pwrite #define NCR5380_intr dtc_intr #define NCR5380_queue_command dtc_queue_command diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index fc7bcbcf3f43..f8c00c96a837 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -551,7 +551,7 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance) } /** - * NCR5380_pread - pseudo DMA read + * generic_NCR5380_pread - pseudo DMA read * @instance: adapter to read from * @dst: buffer to read into * @len: buffer length @@ -560,7 +560,8 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance) * controller */ -static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) +static inline int generic_NCR5380_pread(struct Scsi_Host *instance, + unsigned char *dst, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); int blocks = len / 128; @@ -628,7 +629,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, } /** - * NCR5380_write - pseudo DMA write + * generic_NCR5380_pwrite - pseudo DMA write * @instance: adapter to read from * @dst: buffer to read into * @len: buffer length @@ -637,7 +638,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, * controller */ -static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) +static inline int generic_NCR5380_pwrite(struct Scsi_Host *instance, + unsigned char *src, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); int blocks = len / 128; diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 637740f4c6c7..7f4308705532 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -62,13 +62,13 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) \ generic_NCR5380_dma_xfer_len(instance, cmd) +#define NCR5380_dma_recv_setup generic_NCR5380_pread +#define NCR5380_dma_send_setup generic_NCR5380_pwrite #define NCR5380_intr generic_NCR5380_intr #define NCR5380_queue_command generic_NCR5380_queue_command #define NCR5380_abort generic_NCR5380_abort #define NCR5380_bus_reset generic_NCR5380_bus_reset -#define NCR5380_pread generic_NCR5380_pread -#define NCR5380_pwrite generic_NCR5380_pwrite #define NCR5380_info generic_NCR5380_info #define NCR5380_io_delay(x) udelay(x) diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 1e0d07ac83a1..99b7bbc3dd94 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -33,11 +33,10 @@ #define NCR5380_read(reg) macscsi_read(instance, reg) #define NCR5380_write(reg, value) macscsi_write(instance, reg, value) -#define NCR5380_pread macscsi_pread -#define NCR5380_pwrite macscsi_pwrite - #define NCR5380_dma_xfer_len(instance, cmd, phase) \ macscsi_dma_xfer_len(instance, cmd) +#define NCR5380_dma_recv_setup macscsi_pread +#define NCR5380_dma_send_setup macscsi_pwrite #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 9c06eb637417..c8fd2230c792 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -458,7 +458,7 @@ static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev, } /* - * Function : int NCR5380_pread (struct Scsi_Host *instance, + * Function : int pas16_pread (struct Scsi_Host *instance, * unsigned char *dst, int len) * * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to @@ -470,8 +470,9 @@ static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev, * timeout. */ -static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, - int len) { +static inline int pas16_pread(struct Scsi_Host *instance, + unsigned char *dst, int len) +{ register unsigned char *d = dst; register unsigned short reg = (unsigned short) (instance->io_port + P_DATA_REG_OFFSET); @@ -493,7 +494,7 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, } /* - * Function : int NCR5380_pwrite (struct Scsi_Host *instance, + * Function : int pas16_pwrite (struct Scsi_Host *instance, * unsigned char *src, int len) * * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from @@ -505,8 +506,9 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, * timeout. */ -static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, - int len) { +static inline int pas16_pwrite(struct Scsi_Host *instance, + unsigned char *src, int len) +{ register unsigned char *s = src; register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET); register int i = len; diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index 1695885ce40c..f56f38796bcd 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -103,6 +103,8 @@ #define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) ) #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) +#define NCR5380_dma_recv_setup pas16_pread +#define NCR5380_dma_send_setup pas16_pwrite #define NCR5380_intr pas16_intr #define NCR5380_queue_command pas16_queue_command diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index ce2395f3fae9..6cc3da8d1d69 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -292,7 +292,7 @@ static int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev, } /* - * Function : int NCR5380_pread (struct Scsi_Host *instance, + * Function : int t128_pread (struct Scsi_Host *instance, * unsigned char *dst, int len) * * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to @@ -304,8 +304,8 @@ static int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev, * timeout. */ -static inline int -NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) +static inline int t128_pread(struct Scsi_Host *instance, + unsigned char *dst, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); void __iomem *reg, *base = hostdata->base; @@ -338,7 +338,7 @@ NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) } /* - * Function : int NCR5380_pwrite (struct Scsi_Host *instance, + * Function : int t128_pwrite (struct Scsi_Host *instance, * unsigned char *src, int len) * * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from @@ -350,8 +350,8 @@ NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) * timeout. */ -static inline int -NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) +static inline int t128_pwrite(struct Scsi_Host *instance, + unsigned char *src, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); void __iomem *reg, *base = hostdata->base; diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index 4caea9d62ac4..b6fe70f0aa4b 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -77,6 +77,8 @@ #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) +#define NCR5380_dma_recv_setup t128_pread +#define NCR5380_dma_send_setup t128_pwrite #define NCR5380_intr t128_intr #define NCR5380_queue_command t128_queue_command From 438af51c642926f1c1844846bee1c3fb568dcd64 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:18 +1100 Subject: [PATCH 012/138] ncr5380: Adopt uniform DMA setup convention Standardize the DMA setup hooks so that the DMA implementation in atari_NCR5380.c can be reconciled with pseudo DMA implementation in NCR5380.c. Calls to NCR5380_dma_recv_setup() and NCR5380_dma_send_setup() return a negative value on failure, zero on PDMA transfer success and a positive byte count for DMA setup success. This convention is not entirely new, but is now applied consistently. Also remove a pointless Status Register access: the *phase assignment is redundant because after NCR5380_transfer_dma() returns control to NCR5380_information_transfer(), that routine then returns control to NCR5380_main(), which means *phase is dead. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 21 ++++++++++----------- drivers/scsi/arm/cumana_1.c | 10 ++++++++-- drivers/scsi/arm/oak.c | 4 ++-- drivers/scsi/atari_scsi.c | 3 --- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index b3e5b6b57d83..e05cf505f0d4 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1431,7 +1431,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, register unsigned char p = *phase; register unsigned char *d = *data; unsigned char tmp; - int foo; + int result; if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { *phase = tmp; @@ -1505,9 +1505,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (p & SR_IO) { - foo = NCR5380_dma_recv_setup(instance, d, + result = NCR5380_dma_recv_setup(instance, d, hostdata->flags & FLAG_DMA_FIXUP ? c - 1 : c); - if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { + if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * The workaround was to transfer fewer bytes than we * intended to with the pseudo-DMA read function, wait for @@ -1525,19 +1525,19 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, if (NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, HZ) < 0) { - foo = -1; + result = -1; shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n"); } if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, HZ) < 0) { - foo = -1; + result = -1; shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); } d[c - 1] = NCR5380_read(INPUT_DATA_REG); } } else { - foo = NCR5380_dma_send_setup(instance, d, c); - if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { + result = NCR5380_dma_send_setup(instance, d, c); + if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * Wait for the last byte to be sent. If REQ is being asserted for * the byte we're interested, we'll ACK it and it will go false. @@ -1545,7 +1545,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, if (NCR5380_poll_politely2(instance, BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) { - foo = -1; + result = -1; shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n"); } } @@ -1555,8 +1555,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, NCR5380_read(RESET_PARITY_INTERRUPT_REG); *data = d + c; *count = 0; - *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; - return foo; + return result; } /* @@ -1652,7 +1651,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) if (!cmd->device->borken) transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); - if (transfersize) { + if (transfersize > 0) { len = transfersize; if (NCR5380_transfer_dma(instance, &phase, &len, (unsigned char **)&cmd->SCp.ptr)) { diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 7bcb66893059..402d984aa088 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -101,7 +101,10 @@ static inline int cumanascsi_pwrite(struct Scsi_Host *host, } end: writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); - return len; + + if (len) + return -1; + return 0; } static inline int cumanascsi_pread(struct Scsi_Host *host, @@ -163,7 +166,10 @@ static inline int cumanascsi_pread(struct Scsi_Host *host, } end: writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); - return len; + + if (len) + return -1; + return 0; } static unsigned char cumanascsi_read(struct Scsi_Host *host, unsigned int reg) diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 5d6e0e590638..05cf874fc739 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -47,13 +47,13 @@ static inline int oakscsi_pwrite(struct Scsi_Host *instance, void __iomem *base = priv(instance)->base; printk("writing %p len %d\n",addr, len); - if(!len) return -1; while(1) { int status; while (((status = readw(base + STAT)) & 0x100)==0); } + return 0; } static inline int oakscsi_pread(struct Scsi_Host *instance, @@ -74,7 +74,7 @@ printk("reading %p len %d\n", addr, len); if(status & 0x200 || !timeout) { printk("status = %08X\n", status); - return 1; + return -1; } } diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 41ddd95cebe6..5a81cec79a59 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -527,9 +527,6 @@ static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, */ dma_cache_maintenance(addr, count, dir); - if (count == 0) - printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n"); - if (IS_A_TT()) { tt_scsi_dma.dma_ctrl = dir; SCSI_DMA_WRITE_P(dma_addr, addr); From 8053b0ee79c0129e827ce8f222398ff4b332dfd7 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:19 +1100 Subject: [PATCH 013/138] ncr5380: Merge DMA implementation from atari_NCR5380 core driver Adopt the DMA implementation from atari_NCR5380.c. This means that atari_scsi and sun3_scsi can make use of the NCR5380.c core driver and the atari_NCR5380.c driver fork can be made redundant. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 172 +++++++++++++++++++++++++++++------- drivers/scsi/arm/cumana_1.c | 3 +- drivers/scsi/arm/oak.c | 3 +- drivers/scsi/dmx3191d.c | 1 + drivers/scsi/dtc.c | 2 +- drivers/scsi/dtc.h | 1 + drivers/scsi/g_NCR5380.c | 2 +- drivers/scsi/g_NCR5380.h | 1 + drivers/scsi/mac_scsi.c | 3 +- drivers/scsi/pas16.c | 2 +- drivers/scsi/pas16.h | 1 + drivers/scsi/t128.c | 2 +- drivers/scsi/t128.h | 1 + 13 files changed, 153 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index e05cf505f0d4..fbd8a98af881 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -31,9 +31,6 @@ /* * Further development / testing that should be done : - * 1. Cleanup the NCR5380_transfer_dma function and DMA operation complete - * code so that everything does the same thing that's done at the - * end of a pseudo-DMA read operation. * * 4. Test SCSI-II tagged queueing (I have no devices which support * tagged queueing) @@ -117,6 +114,8 @@ * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. * + * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. + * * These macros MUST be defined : * * NCR5380_read(register) - read from the specified register @@ -801,6 +800,72 @@ static void NCR5380_main(struct work_struct *work) } while (!done); } +/* + * NCR5380_dma_complete - finish DMA transfer + * @instance: the scsi host instance + * + * Called by the interrupt handler when DMA finishes or a phase + * mismatch occurs (which would end the DMA transfer). + */ + +static void NCR5380_dma_complete(struct Scsi_Host *instance) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + int transferred; + unsigned char **data; + int *count; + int saved_data = 0, overrun = 0; + unsigned char p; + + if (hostdata->read_overruns) { + p = hostdata->connected->SCp.phase; + if (p & SR_IO) { + udelay(10); + if ((NCR5380_read(BUS_AND_STATUS_REG) & + (BASR_PHASE_MATCH | BASR_ACK)) == + (BASR_PHASE_MATCH | BASR_ACK)) { + saved_data = NCR5380_read(INPUT_DATA_REG); + overrun = 1; + dsprintk(NDEBUG_DMA, instance, "read overrun handled\n"); + } + } + } + + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + + transferred = hostdata->dma_len - NCR5380_dma_residual(instance); + hostdata->dma_len = 0; + + data = (unsigned char **)&hostdata->connected->SCp.ptr; + count = &hostdata->connected->SCp.this_residual; + *data += transferred; + *count -= transferred; + + if (hostdata->read_overruns) { + int cnt, toPIO; + + if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) { + cnt = toPIO = hostdata->read_overruns; + if (overrun) { + dsprintk(NDEBUG_DMA, instance, + "Got an input overrun, using saved byte\n"); + *(*data)++ = saved_data; + (*count)--; + cnt--; + toPIO--; + } + if (toPIO > 0) { + dsprintk(NDEBUG_DMA, instance, + "Doing %d byte PIO to 0x%p\n", cnt, *data); + NCR5380_transfer_pio(instance, &p, &cnt, data); + *count -= toPIO - cnt; + } + } + } +} + #ifndef DONT_USE_INTR /** @@ -855,7 +920,22 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", irq, basr, sr, mr); - if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && + if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { + /* Probably End of DMA, Phase Mismatch or Loss of BSY. + * We ack IRQ after clearing Mode Register. Workarounds + * for End of DMA errata need to happen in DMA Mode. + */ + + dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n"); + + if (hostdata->connected) { + NCR5380_dma_complete(instance); + queue_work(hostdata->work_q, &hostdata->main_task); + } else { + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } + } else if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { /* Probably reselected */ NCR5380_write(SELECT_ENABLE_REG, 0); @@ -1431,28 +1511,38 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, register unsigned char p = *phase; register unsigned char *d = *data; unsigned char tmp; - int result; + int result = 0; if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { *phase = tmp; return -1; } + hostdata->connected->SCp.phase = p; + + if (p & SR_IO) { + if (hostdata->read_overruns) + c -= hostdata->read_overruns; + else if (hostdata->flags & FLAG_DMA_FIXUP) + --c; + } + + dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", + (p & SR_IO) ? "receive" : "send", c, d); + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | + MR_ENABLE_EOP_INTR); - /* - * Note : on my sample board, watch-dog timeouts occurred when interrupts - * were not disabled for the duration of a single DMA transfer, from - * before the setting of DMA mode to after transfer of the last byte. - */ - - if (hostdata->flags & FLAG_DMA_FIXUP) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); - else - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | - MR_ENABLE_EOP_INTR); - - dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); + if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) { + /* On the Medusa, it is a must to initialize the DMA before + * starting the NCR. This is also the cleaner way for the TT. + */ + if (p & SR_IO) + result = NCR5380_dma_recv_setup(instance, d, c); + else + result = NCR5380_dma_send_setup(instance, d, c); + } /* * On the PAS16 at least I/O recovery delays are not needed here. @@ -1470,6 +1560,29 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, NCR5380_io_delay(1); } + if (hostdata->flags & FLAG_LATE_DMA_SETUP) { + /* On the Falcon, the DMA setup must be done after the last + * NCR access, else the DMA setup gets trashed! + */ + if (p & SR_IO) + result = NCR5380_dma_recv_setup(instance, d, c); + else + result = NCR5380_dma_send_setup(instance, d, c); + } + + /* On failure, NCR5380_dma_xxxx_setup() returns a negative int. */ + if (result < 0) + return result; + + /* For real DMA, result is the byte count. DMA interrupt is expected. */ + if (result > 0) { + hostdata->dma_len = result; + return 0; + } + + /* The result is zero iff pseudo DMA send/receive was completed. */ + hostdata->dma_len = c; + /* * A note regarding the DMA errata workarounds for early NMOS silicon. * @@ -1504,10 +1617,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * request. */ - if (p & SR_IO) { - result = NCR5380_dma_recv_setup(instance, d, - hostdata->flags & FLAG_DMA_FIXUP ? c - 1 : c); - if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { + if (hostdata->flags & FLAG_DMA_FIXUP) { + if (p & SR_IO) { /* * The workaround was to transfer fewer bytes than we * intended to with the pseudo-DMA read function, wait for @@ -1533,11 +1644,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, result = -1; shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); } - d[c - 1] = NCR5380_read(INPUT_DATA_REG); - } - } else { - result = NCR5380_dma_send_setup(instance, d, c); - if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { + d[*count - 1] = NCR5380_read(INPUT_DATA_REG); + } else { /* * Wait for the last byte to be sent. If REQ is being asserted for * the byte we're interested, we'll ACK it and it will go false. @@ -1550,11 +1658,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, } } } - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - *data = d + c; - *count = 0; + + NCR5380_dma_complete(instance); return result; } @@ -1667,8 +1772,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) do_abort(instance); cmd->result = DID_ERROR << 16; /* XXX - need to source or sink data here, as appropriate */ - } else - cmd->SCp.this_residual -= transfersize - len; + } } else { /* Break up transfer into 3 ms chunks, * presuming 6 accesses per handshake. diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 402d984aa088..8e9cfe8f22f5 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -20,6 +20,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) #define NCR5380_dma_recv_setup cumanascsi_pread #define NCR5380_dma_send_setup cumanascsi_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr cumanascsi_intr #define NCR5380_queue_command cumanascsi_queue_command @@ -245,7 +246,7 @@ static int cumanascsi1_probe(struct expansion_card *ec, host->irq = ec->irq; - ret = NCR5380_init(host, FLAG_DMA_FIXUP); + ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP); if (ret) goto out_unmap; diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 05cf874fc739..3aac99c21267 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -26,6 +26,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_dma_recv_setup oakscsi_pread #define NCR5380_dma_send_setup oakscsi_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info @@ -144,7 +145,7 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) host->irq = NO_IRQ; host->n_io_port = 255; - ret = NCR5380_init(host, FLAG_DMA_FIXUP); + ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP); if (ret) goto out_unmap; diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 4b58fa0c16fe..cc46d67b9f6f 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -42,6 +42,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_dma_recv_setup(instance, dst, len) (0) #define NCR5380_dma_send_setup(instance, src, len) (0) +#define NCR5380_dma_residual(instance) (0) #define NCR5380_implementation_fields /* none */ diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index df17904bbe12..e87c632234f3 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -228,7 +228,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) instance->base = addr; ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; - if (NCR5380_init(instance, 0)) + if (NCR5380_init(instance, FLAG_LATE_DMA_SETUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 65af89e4340c..fcb0a8ea7bda 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -23,6 +23,7 @@ dtc_dma_xfer_len(cmd) #define NCR5380_dma_recv_setup dtc_pread #define NCR5380_dma_send_setup dtc_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr dtc_intr #define NCR5380_queue_command dtc_queue_command diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index f8c00c96a837..09e1cf938ecf 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -466,7 +466,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) } #endif - if (NCR5380_init(instance, flags)) + if (NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP)) goto out_unregister; switch (overrides[current_override].board) { diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 7f4308705532..595177428d76 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -64,6 +64,7 @@ generic_NCR5380_dma_xfer_len(instance, cmd) #define NCR5380_dma_recv_setup generic_NCR5380_pread #define NCR5380_dma_send_setup generic_NCR5380_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr generic_NCR5380_intr #define NCR5380_queue_command generic_NCR5380_queue_command diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 99b7bbc3dd94..4de6589fdbfb 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -37,6 +37,7 @@ macscsi_dma_xfer_len(instance, cmd) #define NCR5380_dma_recv_setup macscsi_pread #define NCR5380_dma_send_setup macscsi_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command @@ -386,7 +387,7 @@ static int __init mac_scsi_probe(struct platform_device *pdev) #endif host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; - error = NCR5380_init(instance, host_flags); + error = NCR5380_init(instance, host_flags | FLAG_LATE_DMA_SETUP); if (error) goto fail_init; diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index c8fd2230c792..62eef3f6d140 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -375,7 +375,7 @@ static int __init pas16_detect(struct scsi_host_template *tpnt) instance->io_port = io_port; - if (NCR5380_init(instance, FLAG_DMA_FIXUP)) + if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index f56f38796bcd..9fe7f33660b4 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -105,6 +105,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) #define NCR5380_dma_recv_setup pas16_pread #define NCR5380_dma_send_setup pas16_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr pas16_intr #define NCR5380_queue_command pas16_queue_command diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 6cc3da8d1d69..b5beecfaa3d5 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -208,7 +208,7 @@ static int __init t128_detect(struct scsi_host_template *tpnt) instance->base = base; ((struct NCR5380_hostdata *)instance->hostdata)->base = p; - if (NCR5380_init(instance, FLAG_DMA_FIXUP)) + if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index b6fe70f0aa4b..c95bcd839109 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -79,6 +79,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) #define NCR5380_dma_recv_setup t128_pread #define NCR5380_dma_send_setup t128_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr t128_intr #define NCR5380_queue_command t128_queue_command From 52d3e561cb13df431364a69e783469ba8a9ea8eb Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:20 +1100 Subject: [PATCH 014/138] atari_scsi: Adopt NCR5380.c core driver Add support for the Atari ST DMA chip to the NCR5380.c core driver. This code is copied from atari_NCR5380.c. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 32 ++++++++++++++++++++++++++++++++ drivers/scsi/atari_scsi.c | 6 +++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index fbd8a98af881..859b32febbb4 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -29,6 +29,8 @@ * Ronald van Cuijlenborg, Alan Cox and others. */ +/* Ported to Atari by Roman Hodek and others. */ + /* * Further development / testing that should be done : * @@ -141,6 +143,14 @@ #define NCR5380_io_delay(x) #endif +#ifndef NCR5380_acquire_dma_irq +#define NCR5380_acquire_dma_irq(x) (1) +#endif + +#ifndef NCR5380_release_dma_irq +#define NCR5380_release_dma_irq(x) +#endif + static int do_abort(struct Scsi_Host *); static void do_reset(struct Scsi_Host *); @@ -658,6 +668,9 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, cmd->result = 0; + if (!NCR5380_acquire_dma_irq(instance)) + return SCSI_MLQUEUE_HOST_BUSY; + spin_lock_irqsave(&hostdata->lock, flags); /* @@ -682,6 +695,19 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, return 0; } +static inline void maybe_release_dma_irq(struct Scsi_Host *instance) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + /* Caller does the locking needed to set & test these data atomically */ + if (list_empty(&hostdata->disconnected) && + list_empty(&hostdata->unissued) && + list_empty(&hostdata->autosense) && + !hostdata->connected && + !hostdata->selecting) + NCR5380_release_dma_irq(instance); +} + /** * dequeue_next_cmd - dequeue a command for processing * @instance: the scsi host instance @@ -783,6 +809,7 @@ static void NCR5380_main(struct work_struct *work) if (!NCR5380_select(instance, cmd)) { dsprintk(NDEBUG_MAIN, instance, "main: select complete\n"); + maybe_release_dma_irq(instance); } else { dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, "main: select failed, returning %p to queue\n", cmd); @@ -1828,6 +1855,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + + maybe_release_dma_irq(instance); return; case MESSAGE_REJECT: /* Accept message by clearing ACK */ @@ -1963,6 +1992,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) hostdata->connected = NULL; cmd->result = DID_ERROR << 16; complete_cmd(instance, cmd); + maybe_release_dma_irq(instance); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return; } @@ -2256,6 +2286,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) dsprintk(NDEBUG_ABORT, instance, "abort: successfully aborted %p\n", cmd); queue_work(hostdata->work_q, &hostdata->main_task); + maybe_release_dma_irq(instance); spin_unlock_irqrestore(&hostdata->lock, flags); return result; @@ -2336,6 +2367,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) hostdata->dma_len = 0; queue_work(hostdata->work_q, &hostdata->main_task); + maybe_release_dma_irq(instance); spin_unlock_irqrestore(&hostdata->lock, flags); return SUCCESS; diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 5a81cec79a59..445c26724ba1 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -99,9 +99,9 @@ #define NCR5380_abort atari_scsi_abort #define NCR5380_info atari_scsi_info -#define NCR5380_dma_read_setup(instance, data, count) \ +#define NCR5380_dma_recv_setup(instance, data, count) \ atari_scsi_dma_setup(instance, data, count, 0) -#define NCR5380_dma_write_setup(instance, data, count) \ +#define NCR5380_dma_send_setup(instance, data, count) \ atari_scsi_dma_setup(instance, data, count, 1) #define NCR5380_dma_residual(instance) \ atari_scsi_dma_residual(instance) @@ -715,7 +715,7 @@ static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value) } -#include "atari_NCR5380.c" +#include "NCR5380.c" static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) { From e9db3198e08b6a01e2847f732e595bb8e89153c1 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:21 +1100 Subject: [PATCH 015/138] sun3_scsi: Adopt NCR5380.c core driver Add support for the custom Sun 3 DMA logic to the NCR5380.c core driver. This code is copied from atari_NCR5380.c. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 131 ++++++++++++++++++++++++++++++++++++--- drivers/scsi/sun3_scsi.c | 8 +-- 2 files changed, 124 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 859b32febbb4..a59b71f96365 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -31,6 +31,8 @@ /* Ported to Atari by Roman Hodek and others. */ +/* Adapted for the Sun 3 by Sam Creasey. */ + /* * Further development / testing that should be done : * @@ -858,6 +860,23 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) } } +#ifdef CONFIG_SUN3 + if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) { + pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n", + instance->host_no); + BUG(); + } + + if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == + (BASR_PHASE_MATCH | BASR_ACK)) { + pr_err("scsi%d: BASR %02x\n", instance->host_no, + NCR5380_read(BUS_AND_STATUS_REG)); + pr_err("scsi%d: bus stuck in data phase -- probably a single byte overrun!\n", + instance->host_no); + BUG(); + } +#endif + NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_read(RESET_PARITY_INTERRUPT_REG); @@ -981,10 +1000,16 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) NCR5380_read(RESET_PARITY_INTERRUPT_REG); dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n"); +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_DMA_ENABLE; +#endif } handled = 1; } else { shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_DMA_ENABLE; +#endif } spin_unlock_irqrestore(&hostdata->lock, flags); @@ -1274,6 +1299,10 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, hostdata->connected = cmd; hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_INTR; +#endif + initialize_SCp(cmd); cmd = NULL; @@ -1557,6 +1586,11 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", (p & SR_IO) ? "receive" : "send", c, d); +#ifdef CONFIG_SUN3 + /* send start chain */ + sun3scsi_dma_start(c, *data); +#endif + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | MR_ENABLE_EOP_INTR); @@ -1577,6 +1611,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (p & SR_IO) { + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_io_delay(1); NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); } else { @@ -1587,6 +1622,13 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, NCR5380_io_delay(1); } +#ifdef CONFIG_SUN3 +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_DMA_ENABLE; +#endif + sun3_dma_active = 1; +#endif + if (hostdata->flags & FLAG_LATE_DMA_SETUP) { /* On the Falcon, the DMA setup must be done after the last * NCR access, else the DMA setup gets trashed! @@ -1718,6 +1760,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; struct scsi_cmnd *cmd; +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_INTR; +#endif + while ((cmd = hostdata->connected)) { struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); @@ -1729,6 +1775,31 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) old_phase = phase; NCR5380_dprint_phase(NDEBUG_INFORMATION, instance); } +#ifdef CONFIG_SUN3 + if (phase == PHASE_CMDOUT) { + void *d; + unsigned long count; + + if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { + count = cmd->SCp.buffer->length; + d = sg_virt(cmd->SCp.buffer); + } else { + count = cmd->SCp.this_residual; + d = cmd->SCp.ptr; + } + + if (sun3_dma_setup_done != cmd && + sun3scsi_dma_xfer_len(count, cmd) > 0) { + sun3scsi_dma_setup(instance, d, count, + rq_data_dir(cmd->request)); + sun3_dma_setup_done = cmd; + } +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_INTR; +#endif + } +#endif /* CONFIG_SUN3 */ + if (sink && (phase != PHASE_MSGOUT)) { NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); @@ -1811,6 +1882,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) (unsigned char **)&cmd->SCp.ptr); cmd->SCp.this_residual -= transfersize - len; } +#ifdef CONFIG_SUN3 + if (sun3_dma_setup_done == cmd) + sun3_dma_setup_done = NULL; +#endif return; case PHASE_MSGIN: len = 1; @@ -1889,6 +1964,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_DMA_ENABLE; +#endif return; /* * The SCSI data pointer is *IMPLICITLY* saved on a disconnect @@ -2040,10 +2118,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char target_mask; - unsigned char lun, phase; - int len; + unsigned char lun; unsigned char msg[3]; - unsigned char *data; struct NCR5380_cmd *ncmd; struct scsi_cmnd *tmp; @@ -2085,15 +2161,26 @@ static void NCR5380_reselect(struct Scsi_Host *instance) return; } - len = 1; - data = msg; - phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); +#ifdef CONFIG_SUN3 + /* acknowledge toggle to MSGIN */ + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN)); - if (len) { - do_abort(instance); - return; + /* peek at the byte without really hitting the bus */ + msg[0] = NCR5380_read(CURRENT_SCSI_DATA_REG); +#else + { + int len = 1; + unsigned char *data = msg; + unsigned char phase = PHASE_MSGIN; + + NCR5380_transfer_pio(instance, &phase, &len, &data); + + if (len) { + do_abort(instance); + return; + } } +#endif /* CONFIG_SUN3 */ if (!(msg[0] & 0x80)) { shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got "); @@ -2141,6 +2228,30 @@ static void NCR5380_reselect(struct Scsi_Host *instance) return; } +#ifdef CONFIG_SUN3 + { + void *d; + unsigned long count; + + if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) { + count = tmp->SCp.buffer->length; + d = sg_virt(tmp->SCp.buffer); + } else { + count = tmp->SCp.this_residual; + d = tmp->SCp.ptr; + } + + if (sun3_dma_setup_done != tmp && + sun3scsi_dma_xfer_len(count, tmp) > 0) { + sun3scsi_dma_setup(instance, d, count, + rq_data_dir(tmp->request)); + sun3_dma_setup_done = tmp; + } + } + + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); +#endif /* CONFIG_SUN3 */ + /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index fd4fad816ad4..f2fc788cb08b 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -54,10 +54,8 @@ #define NCR5380_abort sun3scsi_abort #define NCR5380_info sun3scsi_info -#define NCR5380_dma_read_setup(instance, data, count) \ - sun3scsi_dma_setup(instance, data, count, 0) -#define NCR5380_dma_write_setup(instance, data, count) \ - sun3scsi_dma_setup(instance, data, count, 1) +#define NCR5380_dma_recv_setup(instance, data, count) (count) +#define NCR5380_dma_send_setup(instance, data, count) (count) #define NCR5380_dma_residual(instance) \ sun3scsi_dma_residual(instance) #define NCR5380_dma_xfer_len(instance, cmd, phase) \ @@ -406,7 +404,7 @@ static int sun3scsi_dma_finish(int write_flag) } -#include "atari_NCR5380.c" +#include "NCR5380.c" #ifdef SUN3_SCSI_VME #define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI" From c4ec6f924f0682e1f40107204152e977d6b1bd07 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:22 +1100 Subject: [PATCH 016/138] ncr5380: Remove disused atari_NCR5380.c core driver Now that atari_scsi and sun3_scsi have been converted to use the NCR5380.c core driver, remove atari_NCR5380.c. Also remove the last vestiges of its Tagged Command Queueing implementation from the wrapper drivers. The TCQ support in atari_NCR5380.c is abandoned by this patch. It is not merged into the remaining core driver because, 1) atari_scsi defines SUPPORT_TAGS but leaves FLAG_TAGGED_QUEUING disabled by default, which indicates that it is mostly undesirable. 2) I'm told that it doesn't work correctly when enabled. 3) The algorithm does not make use of block layer tags which it will have to do because scmd->tag is deprecated. 4) sun3_scsi doesn't define SUPPORT_TAGS at all, yet the the SUPPORT_TAGS macro interacts with the CONFIG_SUN3 macro in 'interesting' ways. 5) Compile-time configuration with macros like SUPPORT_TAGS caused the configuration space to explode, leading to untestable and unmaintainable code that is too hard to reason about. The merge_contiguous_buffers() code is also abandoned. This was unused by sun3_scsi. Only atari_scsi used it and then only on TT, because only TT supports scatter/gather. I suspect that the TT would work fine with ENABLE_CLUSTERING instead. If someone can benchmark the difference then perhaps the merge_contiguous_buffers() code can be be justified. Until then we are better off without the extra complexity. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 22 +- drivers/scsi/NCR5380.h | 19 - drivers/scsi/atari_NCR5380.c | 2632 ---------------------------------- drivers/scsi/atari_scsi.c | 11 +- drivers/scsi/mac_scsi.c | 8 +- drivers/scsi/sun3_scsi.c | 11 - 6 files changed, 4 insertions(+), 2699 deletions(-) delete mode 100644 drivers/scsi/atari_NCR5380.c diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index a59b71f96365..305330b26349 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -33,13 +33,6 @@ /* Adapted for the Sun 3 by Sam Creasey. */ -/* - * Further development / testing that should be done : - * - * 4. Test SCSI-II tagged queueing (I have no devices which support - * tagged queueing) - */ - /* * Design * @@ -1257,14 +1250,6 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * was true but before BSY was false during selection, the information * transfer phase should be a MESSAGE OUT phase so that we can send the * IDENTIFY message. - * - * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG - * message (2 bytes) with a tag ID that we increment with every command - * until it wraps back to 0. - * - * XXX - it turns out that there are some broken SCSI-II devices, - * which claim to support tagged queuing but fail when more than - * some number of commands are issued at once. */ /* Wait for start of REQ/ACK handshake */ @@ -1287,9 +1272,6 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun); len = 1; - cmd->tag = 0; - - /* Send message(s) */ data = tmp; phase = PHASE_MSGOUT; NCR5380_transfer_pio(instance, &phase, &len, &data); @@ -2256,8 +2238,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = tmp; - dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu, tag %d\n", - scmd_id(tmp), tmp->device->lun, tmp->tag); + dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu\n", + scmd_id(tmp), tmp->device->lun); } /** diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 8adf7377de4c..5c2411f05852 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -199,13 +199,6 @@ #define PHASE_SR_TO_TCR(phase) ((phase) >> 2) -/* - * "Special" value for the (unsigned char) command tag, to indicate - * I_T_L nexus instead of I_T_L_Q. - */ - -#define TAG_NONE 0xff - /* * These are "special" values for the irq and dma_channel fields of the * Scsi_Host structure @@ -223,17 +216,8 @@ #define FLAG_DMA_FIXUP 1 /* Use DMA errata workarounds */ #define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */ #define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */ -#define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */ #define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */ -#ifdef SUPPORT_TAGS -struct tag_alloc { - DECLARE_BITMAP(allocated, MAX_TAGS); - int nr_allocated; - int queue_size; -}; -#endif - struct NCR5380_hostdata { NCR5380_implementation_fields; /* implementation specific */ struct Scsi_Host *host; /* Host backpointer */ @@ -254,9 +238,6 @@ struct NCR5380_hostdata { int read_overruns; /* number of bytes to cut from a * transfer to handle chip overruns */ struct work_struct main_task; -#ifdef SUPPORT_TAGS - struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */ -#endif struct workqueue_struct *work_q; unsigned long accesses_per_ms; /* chip register accesses per ms */ }; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c deleted file mode 100644 index 4101d2de4333..000000000000 --- a/drivers/scsi/atari_NCR5380.c +++ /dev/null @@ -1,2632 +0,0 @@ -/* - * NCR 5380 generic driver routines. These should make it *trivial* - * to implement 5380 SCSI drivers under Linux with a non-trantor - * architecture. - * - * Note that these routines also work with NR53c400 family chips. - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* Ported to Atari by Roman Hodek and others. */ - -/* Adapted for the sun3 by Sam Creasey. */ - -/* - * Design - * - * This is a generic 5380 driver. To use it on a different platform, - * one simply writes appropriate system specific macros (ie, data - * transfer - some PC's will use the I/O bus, 68K's must use - * memory mapped) and drops this file in their 'C' wrapper. - * - * As far as command queueing, two queues are maintained for - * each 5380 in the system - commands that haven't been issued yet, - * and commands that are currently executing. This means that an - * unlimited number of commands may be queued, letting - * more commands propagate from the higher driver levels giving higher - * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported, - * allowing multiple commands to propagate all the way to a SCSI-II device - * while a command is already executing. - * - * - * Issues specific to the NCR5380 : - * - * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead - * piece of hardware that requires you to sit in a loop polling for - * the REQ signal as long as you are connected. Some devices are - * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect - * while doing long seek operations. [...] These - * broken devices are the exception rather than the rule and I'd rather - * spend my time optimizing for the normal case. - * - * Architecture : - * - * At the heart of the design is a coroutine, NCR5380_main, - * which is started from a workqueue for each NCR5380 host in the - * system. It attempts to establish I_T_L or I_T_L_Q nexuses by - * removing the commands from the issue queue and calling - * NCR5380_select() if a nexus is not established. - * - * Once a nexus is established, the NCR5380_information_transfer() - * phase goes through the various phases as instructed by the target. - * if the target goes into MSG IN and sends a DISCONNECT message, - * the command structure is placed into the per instance disconnected - * queue, and NCR5380_main tries to find more work. If the target is - * idle for too long, the system will try to sleep. - * - * If a command has disconnected, eventually an interrupt will trigger, - * calling NCR5380_intr() which will in turn call NCR5380_reselect - * to reestablish a nexus. This will run main if necessary. - * - * On command termination, the done function will be called as - * appropriate. - * - * SCSI pointers are maintained in the SCp field of SCSI command - * structures, being initialized after the command is connected - * in NCR5380_select, and set as appropriate in NCR5380_information_transfer. - * Note that in violation of the standard, an implicit SAVE POINTERS operation - * is done, since some BROKEN disks fail to issue an explicit SAVE POINTERS. - */ - -/* - * Using this file : - * This file a skeleton Linux SCSI driver for the NCR 5380 series - * of chips. To use it, you write an architecture specific functions - * and macros and include this file in your driver. - * - * These macros control options : - * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically - * for commands that return with a CHECK CONDITION status. - * - * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential - * transceivers. - * - * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. - * - * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible - * - * These macros MUST be defined : - * - * NCR5380_read(register) - read from the specified register - * - * NCR5380_write(register, value) - write to the specific register - * - * NCR5380_implementation_fields - additional fields needed for this - * specific implementation of the NCR5380 - * - * Either real DMA *or* pseudo DMA may be implemented - * Note that the DMA setup functions should return the number of bytes - * that they were able to program the controller for. - * - * NCR5380_dma_write_setup(instance, src, count) - initialize - * NCR5380_dma_read_setup(instance, dst, count) - initialize - * NCR5380_dma_residual(instance); - residual count - * - * PSEUDO functions : - * NCR5380_pwrite(instance, src, count) - * NCR5380_pread(instance, dst, count); - * - * The generic driver is initialized by calling NCR5380_init(instance), - * after setting the appropriate host specific fields and ID. If the - * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, - * possible) function may be used. - */ - -static int do_abort(struct Scsi_Host *); -static void do_reset(struct Scsi_Host *); - -#ifdef SUPPORT_TAGS - -/* - * Functions for handling tagged queuing - * ===================================== - * - * ++roman (01/96): Now I've implemented SCSI-2 tagged queuing. Some notes: - * - * Using consecutive numbers for the tags is no good idea in my eyes. There - * could be wrong re-usings if the counter (8 bit!) wraps and some early - * command has been preempted for a long time. My solution: a bitfield for - * remembering used tags. - * - * There's also the problem that each target has a certain queue size, but we - * cannot know it in advance :-( We just see a QUEUE_FULL status being - * returned. So, in this case, the driver internal queue size assumption is - * reduced to the number of active tags if QUEUE_FULL is returned by the - * target. - * - * We're also not allowed running tagged commands as long as an untagged - * command is active. And REQUEST SENSE commands after a contingent allegiance - * condition _must_ be untagged. To keep track whether an untagged command has - * been issued, the host->busy array is still employed, as it is without - * support for tagged queuing. - * - * One could suspect that there are possible race conditions between - * is_lun_busy(), cmd_get_tag() and cmd_free_tag(). But I think this isn't the - * case: is_lun_busy() and cmd_get_tag() are both called from NCR5380_main(), - * which already guaranteed to be running at most once. It is also the only - * place where tags/LUNs are allocated. So no other allocation can slip - * between that pair, there could only happen a reselection, which can free a - * tag, but that doesn't hurt. Only the sequence in cmd_free_tag() becomes - * important: the tag bit must be cleared before 'nr_allocated' is decreased. - */ - -static void __init init_tags(struct NCR5380_hostdata *hostdata) -{ - int target, lun; - struct tag_alloc *ta; - - if (!(hostdata->flags & FLAG_TAGGED_QUEUING)) - return; - - for (target = 0; target < 8; ++target) { - for (lun = 0; lun < 8; ++lun) { - ta = &hostdata->TagAlloc[target][lun]; - bitmap_zero(ta->allocated, MAX_TAGS); - ta->nr_allocated = 0; - /* At the beginning, assume the maximum queue size we could - * support (MAX_TAGS). This value will be decreased if the target - * returns QUEUE_FULL status. - */ - ta->queue_size = MAX_TAGS; - } - } -} - - -/* Check if we can issue a command to this LUN: First see if the LUN is marked - * busy by an untagged command. If the command should use tagged queuing, also - * check that there is a free tag and the target's queue won't overflow. This - * function should be called with interrupts disabled to avoid race - * conditions. - */ - -static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) -{ - u8 lun = cmd->device->lun; - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - if (hostdata->busy[cmd->device->id] & (1 << lun)) - return 1; - if (!should_be_tagged || - !(hostdata->flags & FLAG_TAGGED_QUEUING) || - !cmd->device->tagged_supported) - return 0; - if (hostdata->TagAlloc[scmd_id(cmd)][lun].nr_allocated >= - hostdata->TagAlloc[scmd_id(cmd)][lun].queue_size) { - dsprintk(NDEBUG_TAGS, instance, "target %d lun %d: no free tags\n", - scmd_id(cmd), lun); - return 1; - } - return 0; -} - - -/* Allocate a tag for a command (there are no checks anymore, check_lun_busy() - * must be called before!), or reserve the LUN in 'busy' if the command is - * untagged. - */ - -static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) -{ - u8 lun = cmd->device->lun; - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - /* If we or the target don't support tagged queuing, allocate the LUN for - * an untagged command. - */ - if (!should_be_tagged || - !(hostdata->flags & FLAG_TAGGED_QUEUING) || - !cmd->device->tagged_supported) { - cmd->tag = TAG_NONE; - hostdata->busy[cmd->device->id] |= (1 << lun); - dsprintk(NDEBUG_TAGS, instance, "target %d lun %d now allocated by untagged command\n", - scmd_id(cmd), lun); - } else { - struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun]; - - cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS); - set_bit(cmd->tag, ta->allocated); - ta->nr_allocated++; - dsprintk(NDEBUG_TAGS, instance, "using tag %d for target %d lun %d (%d tags allocated)\n", - cmd->tag, scmd_id(cmd), lun, ta->nr_allocated); - } -} - - -/* Mark the tag of command 'cmd' as free, or in case of an untagged command, - * unlock the LUN. - */ - -static void cmd_free_tag(struct scsi_cmnd *cmd) -{ - u8 lun = cmd->device->lun; - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - if (cmd->tag == TAG_NONE) { - hostdata->busy[cmd->device->id] &= ~(1 << lun); - dsprintk(NDEBUG_TAGS, instance, "target %d lun %d untagged cmd freed\n", - scmd_id(cmd), lun); - } else if (cmd->tag >= MAX_TAGS) { - shost_printk(KERN_NOTICE, instance, - "trying to free bad tag %d!\n", cmd->tag); - } else { - struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun]; - clear_bit(cmd->tag, ta->allocated); - ta->nr_allocated--; - dsprintk(NDEBUG_TAGS, instance, "freed tag %d for target %d lun %d\n", - cmd->tag, scmd_id(cmd), lun); - } -} - - -static void free_all_tags(struct NCR5380_hostdata *hostdata) -{ - int target, lun; - struct tag_alloc *ta; - - if (!(hostdata->flags & FLAG_TAGGED_QUEUING)) - return; - - for (target = 0; target < 8; ++target) { - for (lun = 0; lun < 8; ++lun) { - ta = &hostdata->TagAlloc[target][lun]; - bitmap_zero(ta->allocated, MAX_TAGS); - ta->nr_allocated = 0; - } - } -} - -#endif /* SUPPORT_TAGS */ - -/** - * merge_contiguous_buffers - coalesce scatter-gather list entries - * @cmd: command requesting IO - * - * Try to merge several scatter-gather buffers into one DMA transfer. - * This is possible if the scatter buffers lie on physically - * contiguous addresses. The first scatter-gather buffer's data are - * assumed to be already transferred into cmd->SCp.this_residual. - * Every buffer merged avoids an interrupt and a DMA setup operation. - */ - -static void merge_contiguous_buffers(struct scsi_cmnd *cmd) -{ -#if !defined(CONFIG_SUN3) - unsigned long endaddr; -#if (NDEBUG & NDEBUG_MERGING) - unsigned long oldlen = cmd->SCp.this_residual; - int cnt = 1; -#endif - - for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1; - cmd->SCp.buffers_residual && - virt_to_phys(sg_virt(&cmd->SCp.buffer[1])) == endaddr;) { - dprintk(NDEBUG_MERGING, "VTOP(%p) == %08lx -> merging\n", - page_address(sg_page(&cmd->SCp.buffer[1])), endaddr); -#if (NDEBUG & NDEBUG_MERGING) - ++cnt; -#endif - ++cmd->SCp.buffer; - --cmd->SCp.buffers_residual; - cmd->SCp.this_residual += cmd->SCp.buffer->length; - endaddr += cmd->SCp.buffer->length; - } -#if (NDEBUG & NDEBUG_MERGING) - if (oldlen != cmd->SCp.this_residual) - dprintk(NDEBUG_MERGING, "merged %d buffers from %p, new length %08x\n", - cnt, cmd->SCp.ptr, cmd->SCp.this_residual); -#endif -#endif /* !defined(CONFIG_SUN3) */ -} - -/** - * initialize_SCp - init the scsi pointer field - * @cmd: command block to set up - * - * Set up the internal fields in the SCSI command. - */ - -static inline void initialize_SCp(struct scsi_cmnd *cmd) -{ - /* - * Initialize the Scsi Pointer field so that all of the commands in the - * various queues are valid. - */ - - if (scsi_bufflen(cmd)) { - cmd->SCp.buffer = scsi_sglist(cmd); - cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1; - cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); - cmd->SCp.this_residual = cmd->SCp.buffer->length; - - merge_contiguous_buffers(cmd); - } else { - cmd->SCp.buffer = NULL; - cmd->SCp.buffers_residual = 0; - cmd->SCp.ptr = NULL; - cmd->SCp.this_residual = 0; - } - - cmd->SCp.Status = 0; - cmd->SCp.Message = 0; -} - -/** - * NCR5380_poll_politely2 - wait for two chip register values - * @instance: controller to poll - * @reg1: 5380 register to poll - * @bit1: Bitmask to check - * @val1: Expected value - * @reg2: Second 5380 register to poll - * @bit2: Second bitmask to check - * @val2: Second expected value - * @wait: Time-out in jiffies - * - * Polls the chip in a reasonably efficient manner waiting for an - * event to occur. After a short quick poll we begin to yield the CPU - * (if possible). In irq contexts the time-out is arbitrarily limited. - * Callers may hold locks as long as they are held in irq mode. - * - * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT. - */ - -static int NCR5380_poll_politely2(struct Scsi_Host *instance, - int reg1, int bit1, int val1, - int reg2, int bit2, int val2, int wait) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned long deadline = jiffies + wait; - unsigned long n; - - /* Busy-wait for up to 10 ms */ - n = min(10000U, jiffies_to_usecs(wait)); - n *= hostdata->accesses_per_ms; - n /= 2000; - do { - if ((NCR5380_read(reg1) & bit1) == val1) - return 0; - if ((NCR5380_read(reg2) & bit2) == val2) - return 0; - cpu_relax(); - } while (n--); - - if (irqs_disabled() || in_interrupt()) - return -ETIMEDOUT; - - /* Repeatedly sleep for 1 ms until deadline */ - while (time_is_after_jiffies(deadline)) { - schedule_timeout_uninterruptible(1); - if ((NCR5380_read(reg1) & bit1) == val1) - return 0; - if ((NCR5380_read(reg2) & bit2) == val2) - return 0; - } - - return -ETIMEDOUT; -} - -static inline int NCR5380_poll_politely(struct Scsi_Host *instance, - int reg, int bit, int val, int wait) -{ - return NCR5380_poll_politely2(instance, reg, bit, val, - reg, bit, val, wait); -} - -#if NDEBUG -static struct { - unsigned char mask; - const char *name; -} signals[] = { - {SR_DBP, "PARITY"}, - {SR_RST, "RST"}, - {SR_BSY, "BSY"}, - {SR_REQ, "REQ"}, - {SR_MSG, "MSG"}, - {SR_CD, "CD"}, - {SR_IO, "IO"}, - {SR_SEL, "SEL"}, - {0, NULL} -}, -basrs[] = { - {BASR_ATN, "ATN"}, - {BASR_ACK, "ACK"}, - {0, NULL} -}, -icrs[] = { - {ICR_ASSERT_RST, "ASSERT RST"}, - {ICR_ASSERT_ACK, "ASSERT ACK"}, - {ICR_ASSERT_BSY, "ASSERT BSY"}, - {ICR_ASSERT_SEL, "ASSERT SEL"}, - {ICR_ASSERT_ATN, "ASSERT ATN"}, - {ICR_ASSERT_DATA, "ASSERT DATA"}, - {0, NULL} -}, -mrs[] = { - {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, - {MR_TARGET, "MODE TARGET"}, - {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, - {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, - {MR_ENABLE_EOP_INTR, "MODE EOP INTR"}, - {MR_MONITOR_BSY, "MODE MONITOR BSY"}, - {MR_DMA_MODE, "MODE DMA"}, - {MR_ARBITRATE, "MODE ARBITRATION"}, - {0, NULL} -}; - -/** - * NCR5380_print - print scsi bus signals - * @instance: adapter state to dump - * - * Print the SCSI bus signals for debugging purposes - */ - -static void NCR5380_print(struct Scsi_Host *instance) -{ - unsigned char status, data, basr, mr, icr, i; - - data = NCR5380_read(CURRENT_SCSI_DATA_REG); - status = NCR5380_read(STATUS_REG); - mr = NCR5380_read(MODE_REG); - icr = NCR5380_read(INITIATOR_COMMAND_REG); - basr = NCR5380_read(BUS_AND_STATUS_REG); - - printk("STATUS_REG: %02x ", status); - for (i = 0; signals[i].mask; ++i) - if (status & signals[i].mask) - printk(",%s", signals[i].name); - printk("\nBASR: %02x ", basr); - for (i = 0; basrs[i].mask; ++i) - if (basr & basrs[i].mask) - printk(",%s", basrs[i].name); - printk("\nICR: %02x ", icr); - for (i = 0; icrs[i].mask; ++i) - if (icr & icrs[i].mask) - printk(",%s", icrs[i].name); - printk("\nMODE: %02x ", mr); - for (i = 0; mrs[i].mask; ++i) - if (mr & mrs[i].mask) - printk(",%s", mrs[i].name); - printk("\n"); -} - -static struct { - unsigned char value; - const char *name; -} phases[] = { - {PHASE_DATAOUT, "DATAOUT"}, - {PHASE_DATAIN, "DATAIN"}, - {PHASE_CMDOUT, "CMDOUT"}, - {PHASE_STATIN, "STATIN"}, - {PHASE_MSGOUT, "MSGOUT"}, - {PHASE_MSGIN, "MSGIN"}, - {PHASE_UNKNOWN, "UNKNOWN"} -}; - -/** - * NCR5380_print_phase - show SCSI phase - * @instance: adapter to dump - * - * Print the current SCSI phase for debugging purposes - */ - -static void NCR5380_print_phase(struct Scsi_Host *instance) -{ - unsigned char status; - int i; - - status = NCR5380_read(STATUS_REG); - if (!(status & SR_REQ)) - shost_printk(KERN_DEBUG, instance, "REQ not asserted, phase unknown.\n"); - else { - for (i = 0; (phases[i].value != PHASE_UNKNOWN) && - (phases[i].value != (status & PHASE_MASK)); ++i) - ; - shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name); - } -} -#endif - -/** - * NCR58380_info - report driver and host information - * @instance: relevant scsi host instance - * - * For use as the host template info() handler. - */ - -static const char *NCR5380_info(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - return hostdata->info; -} - -static void prepare_info(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - snprintf(hostdata->info, sizeof(hostdata->info), - "%s, io_port 0x%lx, n_io_port %d, " - "base 0x%lx, irq %d, " - "can_queue %d, cmd_per_lun %d, " - "sg_tablesize %d, this_id %d, " - "flags { %s%s}, " - "options { %s} ", - instance->hostt->name, instance->io_port, instance->n_io_port, - instance->base, instance->irq, - instance->can_queue, instance->cmd_per_lun, - instance->sg_tablesize, instance->this_id, - hostdata->flags & FLAG_TAGGED_QUEUING ? "TAGGED_QUEUING " : "", - hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", -#ifdef DIFFERENTIAL - "DIFFERENTIAL " -#endif -#ifdef PARITY - "PARITY " -#endif -#ifdef SUPPORT_TAGS - "SUPPORT_TAGS " -#endif - ""); -} - -/** - * NCR5380_init - initialise an NCR5380 - * @instance: adapter to configure - * @flags: control flags - * - * Initializes *instance and corresponding 5380 chip, - * with flags OR'd into the initial flags value. - * - * Notes : I assume that the host, hostno, and id bits have been - * set correctly. I don't care about the irq and other fields. - * - * Returns 0 for success - */ - -static int __init NCR5380_init(struct Scsi_Host *instance, int flags) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int i; - unsigned long deadline; - - hostdata->host = instance; - hostdata->id_mask = 1 << instance->this_id; - hostdata->id_higher_mask = 0; - for (i = hostdata->id_mask; i <= 0x80; i <<= 1) - if (i > hostdata->id_mask) - hostdata->id_higher_mask |= i; - for (i = 0; i < 8; ++i) - hostdata->busy[i] = 0; -#ifdef SUPPORT_TAGS - init_tags(hostdata); -#endif - hostdata->dma_len = 0; - - spin_lock_init(&hostdata->lock); - hostdata->connected = NULL; - hostdata->sensing = NULL; - INIT_LIST_HEAD(&hostdata->autosense); - INIT_LIST_HEAD(&hostdata->unissued); - INIT_LIST_HEAD(&hostdata->disconnected); - - hostdata->flags = flags; - - INIT_WORK(&hostdata->main_task, NCR5380_main); - hostdata->work_q = alloc_workqueue("ncr5380_%d", - WQ_UNBOUND | WQ_MEM_RECLAIM, - 1, instance->host_no); - if (!hostdata->work_q) - return -ENOMEM; - - prepare_info(instance); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(TARGET_COMMAND_REG, 0); - NCR5380_write(SELECT_ENABLE_REG, 0); - - /* Calibrate register polling loop */ - i = 0; - deadline = jiffies + 1; - do { - cpu_relax(); - } while (time_is_after_jiffies(deadline)); - deadline += msecs_to_jiffies(256); - do { - NCR5380_read(STATUS_REG); - ++i; - cpu_relax(); - } while (time_is_after_jiffies(deadline)); - hostdata->accesses_per_ms = i / 256; - - return 0; -} - -/** - * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems. - * @instance: adapter to check - * - * If the system crashed, it may have crashed with a connected target and - * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the - * currently established nexus, which we know nothing about. Failing that - * do a bus reset. - * - * Note that a bus reset will cause the chip to assert IRQ. - * - * Returns 0 if successful, otherwise -ENXIO. - */ - -static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int pass; - - for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) { - switch (pass) { - case 1: - case 3: - case 5: - shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n"); - NCR5380_poll_politely(instance, - STATUS_REG, SR_BSY, 0, 5 * HZ); - break; - case 2: - shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n"); - do_abort(instance); - break; - case 4: - shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n"); - do_reset(instance); - /* Wait after a reset; the SCSI standard calls for - * 250ms, we wait 500ms to be on the safe side. - * But some Toshiba CD-ROMs need ten times that. - */ - if (hostdata->flags & FLAG_TOSHIBA_DELAY) - msleep(2500); - else - msleep(500); - break; - case 6: - shost_printk(KERN_ERR, instance, "bus locked solid\n"); - return -ENXIO; - } - } - return 0; -} - -/** - * NCR5380_exit - remove an NCR5380 - * @instance: adapter to remove - * - * Assumes that no more work can be queued (e.g. by NCR5380_intr). - */ - -static void NCR5380_exit(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - cancel_work_sync(&hostdata->main_task); - destroy_workqueue(hostdata->work_q); -} - -/** - * complete_cmd - finish processing a command and return it to the SCSI ML - * @instance: the host instance - * @cmd: command to complete - */ - -static void complete_cmd(struct Scsi_Host *instance, - struct scsi_cmnd *cmd) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - dsprintk(NDEBUG_QUEUES, instance, "complete_cmd: cmd %p\n", cmd); - - if (hostdata->sensing == cmd) { - /* Autosense processing ends here */ - if ((cmd->result & 0xff) != SAM_STAT_GOOD) { - scsi_eh_restore_cmnd(cmd, &hostdata->ses); - set_host_byte(cmd, DID_ERROR); - } else - scsi_eh_restore_cmnd(cmd, &hostdata->ses); - hostdata->sensing = NULL; - } - -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); -#else - hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); -#endif - cmd->scsi_done(cmd); -} - -/** - * NCR5380_queue_command - queue a command - * @instance: the relevant SCSI adapter - * @cmd: SCSI command - * - * cmd is added to the per-instance issue queue, with minor - * twiddling done to the host specific fields of cmd. If the - * main coroutine is not running, it is restarted. - */ - -static int NCR5380_queue_command(struct Scsi_Host *instance, - struct scsi_cmnd *cmd) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - unsigned long flags; - -#if (NDEBUG & NDEBUG_NO_WRITE) - switch (cmd->cmnd[0]) { - case WRITE_6: - case WRITE_10: - shost_printk(KERN_DEBUG, instance, "WRITE attempted with NDEBUG_NO_WRITE set\n"); - cmd->result = (DID_ERROR << 16); - cmd->scsi_done(cmd); - return 0; - } -#endif /* (NDEBUG & NDEBUG_NO_WRITE) */ - - cmd->result = 0; - - /* - * ++roman: Just disabling the NCR interrupt isn't sufficient here, - * because also a timer int can trigger an abort or reset, which would - * alter queues and touch the lock. - */ - if (!NCR5380_acquire_dma_irq(instance)) - return SCSI_MLQUEUE_HOST_BUSY; - - spin_lock_irqsave(&hostdata->lock, flags); - - /* - * Insert the cmd into the issue queue. Note that REQUEST SENSE - * commands are added to the head of the queue since any command will - * clear the contingent allegiance condition that exists and the - * sense data is only guaranteed to be valid while the condition exists. - */ - - if (cmd->cmnd[0] == REQUEST_SENSE) - list_add(&ncmd->list, &hostdata->unissued); - else - list_add_tail(&ncmd->list, &hostdata->unissued); - - spin_unlock_irqrestore(&hostdata->lock, flags); - - dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", - cmd, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); - - /* Kick off command processing */ - queue_work(hostdata->work_q, &hostdata->main_task); - return 0; -} - -static inline void maybe_release_dma_irq(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - /* Caller does the locking needed to set & test these data atomically */ - if (list_empty(&hostdata->disconnected) && - list_empty(&hostdata->unissued) && - list_empty(&hostdata->autosense) && - !hostdata->connected && - !hostdata->selecting) - NCR5380_release_dma_irq(instance); -} - -/** - * dequeue_next_cmd - dequeue a command for processing - * @instance: the scsi host instance - * - * Priority is given to commands on the autosense queue. These commands - * need autosense because of a CHECK CONDITION result. - * - * Returns a command pointer if a command is found for a target that is - * not already busy. Otherwise returns NULL. - */ - -static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct NCR5380_cmd *ncmd; - struct scsi_cmnd *cmd; - - if (hostdata->sensing || list_empty(&hostdata->autosense)) { - list_for_each_entry(ncmd, &hostdata->unissued, list) { - cmd = NCR5380_to_scmd(ncmd); - dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n", - cmd, scmd_id(cmd), hostdata->busy[scmd_id(cmd)], cmd->device->lun); - - if ( -#ifdef SUPPORT_TAGS - !is_lun_busy(cmd, 1) -#else - !(hostdata->busy[scmd_id(cmd)] & (1 << cmd->device->lun)) -#endif - ) { - list_del(&ncmd->list); - dsprintk(NDEBUG_QUEUES, instance, - "dequeue: removed %p from issue queue\n", cmd); - return cmd; - } - } - } else { - /* Autosense processing begins here */ - ncmd = list_first_entry(&hostdata->autosense, - struct NCR5380_cmd, list); - list_del(&ncmd->list); - cmd = NCR5380_to_scmd(ncmd); - dsprintk(NDEBUG_QUEUES, instance, - "dequeue: removed %p from autosense queue\n", cmd); - scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); - hostdata->sensing = cmd; - return cmd; - } - return NULL; -} - -static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - - if (hostdata->sensing == cmd) { - scsi_eh_restore_cmnd(cmd, &hostdata->ses); - list_add(&ncmd->list, &hostdata->autosense); - hostdata->sensing = NULL; - } else - list_add(&ncmd->list, &hostdata->unissued); -} - -/** - * NCR5380_main - NCR state machines - * - * NCR5380_main is a coroutine that runs as long as more work can - * be done on the NCR5380 host adapters in a system. Both - * NCR5380_queue_command() and NCR5380_intr() will try to start it - * in case it is not running. - */ - -static void NCR5380_main(struct work_struct *work) -{ - struct NCR5380_hostdata *hostdata = - container_of(work, struct NCR5380_hostdata, main_task); - struct Scsi_Host *instance = hostdata->host; - int done; - - /* - * ++roman: Just disabling the NCR interrupt isn't sufficient here, - * because also a timer int can trigger an abort or reset, which can - * alter queues and touch the Falcon lock. - */ - - do { - done = 1; - - spin_lock_irq(&hostdata->lock); - while (!hostdata->connected && !hostdata->selecting) { - struct scsi_cmnd *cmd = dequeue_next_cmd(instance); - - if (!cmd) - break; - - dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd); - - /* - * Attempt to establish an I_T_L nexus here. - * On success, instance->hostdata->connected is set. - * On failure, we must add the command back to the - * issue queue so we can keep trying. - */ - /* - * REQUEST SENSE commands are issued without tagged - * queueing, even on SCSI-II devices because the - * contingent allegiance condition exists for the - * entire unit. - */ - /* ++roman: ...and the standard also requires that - * REQUEST SENSE command are untagged. - */ - -#ifdef SUPPORT_TAGS - cmd_get_tag(cmd, cmd->cmnd[0] != REQUEST_SENSE); -#endif - if (!NCR5380_select(instance, cmd)) { - dsprintk(NDEBUG_MAIN, instance, "main: select complete\n"); - maybe_release_dma_irq(instance); - } else { - dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, - "main: select failed, returning %p to queue\n", cmd); - requeue_cmd(instance, cmd); -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); -#endif - } - } - if (hostdata->connected && !hostdata->dma_len) { - dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n"); - NCR5380_information_transfer(instance); - done = 0; - } - spin_unlock_irq(&hostdata->lock); - if (!done) - cond_resched(); - } while (!done); -} - - -/* - * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) - * - * Purpose : Called by interrupt handler when DMA finishes or a phase - * mismatch occurs (which would finish the DMA transfer). - * - * Inputs : instance - this instance of the NCR5380. - */ - -static void NCR5380_dma_complete(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int transferred; - unsigned char **data; - int *count; - int saved_data = 0, overrun = 0; - unsigned char p; - - if (hostdata->read_overruns) { - p = hostdata->connected->SCp.phase; - if (p & SR_IO) { - udelay(10); - if ((NCR5380_read(BUS_AND_STATUS_REG) & - (BASR_PHASE_MATCH|BASR_ACK)) == - (BASR_PHASE_MATCH|BASR_ACK)) { - saved_data = NCR5380_read(INPUT_DATA_REG); - overrun = 1; - dsprintk(NDEBUG_DMA, instance, "read overrun handled\n"); - } - } - } - -#if defined(CONFIG_SUN3) - if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) { - pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n", - instance->host_no); - BUG(); - } - - /* make sure we're not stuck in a data phase */ - if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == - (BASR_PHASE_MATCH | BASR_ACK)) { - pr_err("scsi%d: BASR %02x\n", instance->host_no, - NCR5380_read(BUS_AND_STATUS_REG)); - pr_err("scsi%d: bus stuck in data phase -- probably a single byte overrun!\n", - instance->host_no); - BUG(); - } -#endif - - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - - transferred = hostdata->dma_len - NCR5380_dma_residual(instance); - hostdata->dma_len = 0; - - data = (unsigned char **)&hostdata->connected->SCp.ptr; - count = &hostdata->connected->SCp.this_residual; - *data += transferred; - *count -= transferred; - - if (hostdata->read_overruns) { - int cnt, toPIO; - - if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) { - cnt = toPIO = hostdata->read_overruns; - if (overrun) { - dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n"); - *(*data)++ = saved_data; - (*count)--; - cnt--; - toPIO--; - } - dprintk(NDEBUG_DMA, "Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data); - NCR5380_transfer_pio(instance, &p, &cnt, data); - *count -= toPIO - cnt; - } - } -} - - -/** - * NCR5380_intr - generic NCR5380 irq handler - * @irq: interrupt number - * @dev_id: device info - * - * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses - * from the disconnected queue, and restarting NCR5380_main() - * as required. - * - * The chip can assert IRQ in any of six different conditions. The IRQ flag - * is then cleared by reading the Reset Parity/Interrupt Register (RPIR). - * Three of these six conditions are latched in the Bus and Status Register: - * - End of DMA (cleared by ending DMA Mode) - * - Parity error (cleared by reading RPIR) - * - Loss of BSY (cleared by reading RPIR) - * Two conditions have flag bits that are not latched: - * - Bus phase mismatch (non-maskable in DMA Mode, cleared by ending DMA Mode) - * - Bus reset (non-maskable) - * The remaining condition has no flag bit at all: - * - Selection/reselection - * - * Hence, establishing the cause(s) of any interrupt is partly guesswork. - * In "The DP8490 and DP5380 Comparison Guide", National Semiconductor - * claimed that "the design of the [DP8490] interrupt logic ensures - * interrupts will not be lost (they can be on the DP5380)." - * The L5380/53C80 datasheet from LOGIC Devices has more details. - * - * Checking for bus reset by reading RST is futile because of interrupt - * latency, but a bus reset will reset chip logic. Checking for parity error - * is unnecessary because that interrupt is never enabled. A Loss of BSY - * condition will clear DMA Mode. We can tell when this occurs because the - * the Busy Monitor interrupt is enabled together with DMA Mode. - */ - -static irqreturn_t NCR5380_intr(int irq, void *dev_id) -{ - struct Scsi_Host *instance = dev_id; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int handled = 0; - unsigned char basr; - unsigned long flags; - - spin_lock_irqsave(&hostdata->lock, flags); - - basr = NCR5380_read(BUS_AND_STATUS_REG); - if (basr & BASR_IRQ) { - unsigned char mr = NCR5380_read(MODE_REG); - unsigned char sr = NCR5380_read(STATUS_REG); - - dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", - irq, basr, sr, mr); - - if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { - /* Probably End of DMA, Phase Mismatch or Loss of BSY. - * We ack IRQ after clearing Mode Register. Workarounds - * for End of DMA errata need to happen in DMA Mode. - */ - - dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n"); - - if (hostdata->connected) { - NCR5380_dma_complete(instance); - queue_work(hostdata->work_q, &hostdata->main_task); - } else { - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } - } else if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && - (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { - /* Probably reselected */ - NCR5380_write(SELECT_ENABLE_REG, 0); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - - dsprintk(NDEBUG_INTR, instance, "interrupt with SEL and IO\n"); - - if (!hostdata->connected) { - NCR5380_reselect(instance); - queue_work(hostdata->work_q, &hostdata->main_task); - } - if (!hostdata->connected) - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - } else { - /* Probably Bus Reset */ - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - - dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n"); -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_DMA_ENABLE; -#endif - } - handled = 1; - } else { - shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_DMA_ENABLE; -#endif - } - - spin_unlock_irqrestore(&hostdata->lock, flags); - - return IRQ_RETVAL(handled); -} - -/* - * Function : int NCR5380_select(struct Scsi_Host *instance, - * struct scsi_cmnd *cmd) - * - * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, - * including ARBITRATION, SELECTION, and initial message out for - * IDENTIFY and queue messages. - * - * Inputs : instance - instantiation of the 5380 driver on which this - * target lives, cmd - SCSI command to execute. - * - * Returns cmd if selection failed but should be retried, - * NULL if selection failed and should not be retried, or - * NULL if selection succeeded (hostdata->connected == cmd). - * - * Side effects : - * If bus busy, arbitration failed, etc, NCR5380_select() will exit - * with registers as they should have been on entry - ie - * SELECT_ENABLE will be set appropriately, the NCR5380 - * will cease to drive any SCSI bus signals. - * - * If successful : I_T_L or I_T_L_Q nexus will be established, - * instance->connected will be set to cmd. - * SELECT interrupt will be disabled. - * - * If failed (no target) : cmd->scsi_done() will be called, and the - * cmd->result host byte set to DID_BAD_TARGET. - */ - -static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, - struct scsi_cmnd *cmd) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char tmp[3], phase; - unsigned char *data; - int len; - int err; - - NCR5380_dprint(NDEBUG_ARBITRATION, instance); - dsprintk(NDEBUG_ARBITRATION, instance, "starting arbitration, id = %d\n", - instance->this_id); - - /* - * Arbitration and selection phases are slow and involve dropping the - * lock, so we have to watch out for EH. An exception handler may - * change 'selecting' to NULL. This function will then return NULL - * so that the caller will forget about 'cmd'. (During information - * transfer phases, EH may change 'connected' to NULL.) - */ - hostdata->selecting = cmd; - - /* - * Set the phase bits to 0, otherwise the NCR5380 won't drive the - * data bus during SELECTION. - */ - - NCR5380_write(TARGET_COMMAND_REG, 0); - - /* - * Start arbitration. - */ - - NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); - NCR5380_write(MODE_REG, MR_ARBITRATE); - - /* The chip now waits for BUS FREE phase. Then after the 800 ns - * Bus Free Delay, arbitration will begin. - */ - - spin_unlock_irq(&hostdata->lock); - err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0, - INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, - ICR_ARBITRATION_PROGRESS, HZ); - spin_lock_irq(&hostdata->lock); - if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { - /* Reselection interrupt */ - goto out; - } - if (!hostdata->selecting) { - /* Command was aborted */ - NCR5380_write(MODE_REG, MR_BASE); - goto out; - } - if (err < 0) { - NCR5380_write(MODE_REG, MR_BASE); - shost_printk(KERN_ERR, instance, - "select: arbitration timeout\n"); - goto out; - } - spin_unlock_irq(&hostdata->lock); - - /* The SCSI-2 arbitration delay is 2.4 us */ - udelay(3); - - /* Check for lost arbitration */ - if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || - (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || - (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { - NCR5380_write(MODE_REG, MR_BASE); - dsprintk(NDEBUG_ARBITRATION, instance, "lost arbitration, deasserting MR_ARBITRATE\n"); - spin_lock_irq(&hostdata->lock); - goto out; - } - - /* After/during arbitration, BSY should be asserted. - * IBM DPES-31080 Version S31Q works now - * Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) - */ - NCR5380_write(INITIATOR_COMMAND_REG, - ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY); - - /* - * Again, bus clear + bus settle time is 1.2us, however, this is - * a minimum so we'll udelay ceil(1.2) - */ - - if (hostdata->flags & FLAG_TOSHIBA_DELAY) - udelay(15); - else - udelay(2); - - spin_lock_irq(&hostdata->lock); - - /* NCR5380_reselect() clears MODE_REG after a reselection interrupt */ - if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) - goto out; - - if (!hostdata->selecting) { - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - goto out; - } - - dsprintk(NDEBUG_ARBITRATION, instance, "won arbitration\n"); - - /* - * Now that we have won arbitration, start Selection process, asserting - * the host and target ID's on the SCSI bus. - */ - - NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask | (1 << scmd_id(cmd))); - - /* - * Raise ATN while SEL is true before BSY goes false from arbitration, - * since this is the only way to guarantee that we'll get a MESSAGE OUT - * phase immediately after selection. - */ - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY | - ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL); - NCR5380_write(MODE_REG, MR_BASE); - - /* - * Reselect interrupts must be turned off prior to the dropping of BSY, - * otherwise we will trigger an interrupt. - */ - NCR5380_write(SELECT_ENABLE_REG, 0); - - spin_unlock_irq(&hostdata->lock); - - /* - * The initiator shall then wait at least two deskew delays and release - * the BSY signal. - */ - udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ - - /* Reset BSY */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | - ICR_ASSERT_ATN | ICR_ASSERT_SEL); - - /* - * Something weird happens when we cease to drive BSY - looks - * like the board/chip is letting us do another read before the - * appropriate propagation delay has expired, and we're confusing - * a BSY signal from ourselves as the target's response to SELECTION. - * - * A small delay (the 'C++' frontend breaks the pipeline with an - * unnecessary jump, making it work on my 386-33/Trantor T128, the - * tighter 'C' code breaks and requires this) solves the problem - - * the 1 us delay is arbitrary, and only used because this delay will - * be the same on other platforms and since it works here, it should - * work there. - * - * wingel suggests that this could be due to failing to wait - * one deskew delay. - */ - - udelay(1); - - dsprintk(NDEBUG_SELECTION, instance, "selecting target %d\n", scmd_id(cmd)); - - /* - * The SCSI specification calls for a 250 ms timeout for the actual - * selection. - */ - - err = NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, SR_BSY, - msecs_to_jiffies(250)); - - if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { - spin_lock_irq(&hostdata->lock); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_reselect(instance); - if (!hostdata->connected) - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - shost_printk(KERN_ERR, instance, "reselection after won arbitration?\n"); - goto out; - } - - if (err < 0) { - spin_lock_irq(&hostdata->lock); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - /* Can't touch cmd if it has been reclaimed by the scsi ML */ - if (hostdata->selecting) { - cmd->result = DID_BAD_TARGET << 16; - complete_cmd(instance, cmd); - dsprintk(NDEBUG_SELECTION, instance, "target did not respond within 250ms\n"); - cmd = NULL; - } - goto out; - } - - /* - * No less than two deskew delays after the initiator detects the - * BSY signal is true, it shall release the SEL signal and may - * change the DATA BUS. -wingel - */ - - udelay(1); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - - /* - * Since we followed the SCSI spec, and raised ATN while SEL - * was true but before BSY was false during selection, the information - * transfer phase should be a MESSAGE OUT phase so that we can send the - * IDENTIFY message. - * - * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG - * message (2 bytes) with a tag ID that we increment with every command - * until it wraps back to 0. - * - * XXX - it turns out that there are some broken SCSI-II devices, - * which claim to support tagged queuing but fail when more than - * some number of commands are issued at once. - */ - - /* Wait for start of REQ/ACK handshake */ - - err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); - spin_lock_irq(&hostdata->lock); - if (err < 0) { - shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - goto out; - } - if (!hostdata->selecting) { - do_abort(instance); - goto out; - } - - dsprintk(NDEBUG_SELECTION, instance, "target %d selected, going into MESSAGE OUT phase.\n", - scmd_id(cmd)); - tmp[0] = IDENTIFY(1, cmd->device->lun); - -#ifdef SUPPORT_TAGS - if (cmd->tag != TAG_NONE) { - tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG; - tmp[2] = cmd->tag; - len = 3; - } else - len = 1; -#else - len = 1; - cmd->tag = 0; -#endif /* SUPPORT_TAGS */ - - /* Send message(s) */ - data = tmp; - phase = PHASE_MSGOUT; - NCR5380_transfer_pio(instance, &phase, &len, &data); - dsprintk(NDEBUG_SELECTION, instance, "nexus established.\n"); - /* XXX need to handle errors here */ - - hostdata->connected = cmd; -#ifndef SUPPORT_TAGS - hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; -#endif -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_INTR; -#endif - - initialize_SCp(cmd); - - cmd = NULL; - -out: - if (!hostdata->selecting) - return NULL; - hostdata->selecting = NULL; - return cmd; -} - -/* - * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) - * - * Purpose : transfers data in given phase using polled I/O - * - * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. - * - * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes are transferred or exit - * is in same phase. - * - * Also, *phase, *count, *data are modified in place. - * - * XXX Note : handling for bus free may be useful. - */ - -/* - * Note : this code is not as quick as it could be, however it - * IS 100% reliable, and for the actual data transfer where speed - * counts, we will always do a pseudo DMA or DMA transfer. - */ - -static int NCR5380_transfer_pio(struct Scsi_Host *instance, - unsigned char *phase, int *count, - unsigned char **data) -{ - unsigned char p = *phase, tmp; - int c = *count; - unsigned char *d = *data; - - /* - * The NCR5380 chip will only drive the SCSI bus when the - * phase specified in the appropriate bits of the TARGET COMMAND - * REGISTER match the STATUS REGISTER - */ - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - - do { - /* - * Wait for assertion of REQ, after which the phase bits will be - * valid - */ - - if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) - break; - - dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n"); - - /* Check for phase mismatch */ - if ((NCR5380_read(STATUS_REG) & PHASE_MASK) != p) { - dsprintk(NDEBUG_PIO, instance, "phase mismatch\n"); - NCR5380_dprint_phase(NDEBUG_PIO, instance); - break; - } - - /* Do actual transfer from SCSI bus to / from memory */ - if (!(p & SR_IO)) - NCR5380_write(OUTPUT_DATA_REG, *d); - else - *d = NCR5380_read(CURRENT_SCSI_DATA_REG); - - ++d; - - /* - * The SCSI standard suggests that in MSGOUT phase, the initiator - * should drop ATN on the last byte of the message phase - * after REQ has been asserted for the handshake but before - * the initiator raises ACK. - */ - - if (!(p & SR_IO)) { - if (!((p & SR_MSG) && c > 1)) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); - NCR5380_dprint(NDEBUG_PIO, instance); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ACK); - } else { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ATN); - NCR5380_dprint(NDEBUG_PIO, instance); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - } - } else { - NCR5380_dprint(NDEBUG_PIO, instance); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); - } - - if (NCR5380_poll_politely(instance, - STATUS_REG, SR_REQ, 0, 5 * HZ) < 0) - break; - - dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n"); - -/* - * We have several special cases to consider during REQ/ACK handshaking : - * 1. We were in MSGOUT phase, and we are on the last byte of the - * message. ATN must be dropped as ACK is dropped. - * - * 2. We are in a MSGIN phase, and we are on the last byte of the - * message. We must exit with ACK asserted, so that the calling - * code may raise ATN before dropping ACK to reject the message. - * - * 3. ACK and ATN are clear and the target may proceed as normal. - */ - if (!(p == PHASE_MSGIN && c == 1)) { - if (p == PHASE_MSGOUT && c > 1) - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - else - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - } - } while (--c); - - dsprintk(NDEBUG_PIO, instance, "residual %d\n", c); - - *count = c; - *data = d; - tmp = NCR5380_read(STATUS_REG); - /* The phase read from the bus is valid if either REQ is (already) - * asserted or if ACK hasn't been released yet. The latter applies if - * we're in MSG IN, DATA IN or STATUS and all bytes have been received. - */ - if ((tmp & SR_REQ) || ((tmp & SR_IO) && c == 0)) - *phase = tmp & PHASE_MASK; - else - *phase = PHASE_UNKNOWN; - - if (!c || (*phase == p)) - return 0; - else - return -1; -} - -/** - * do_reset - issue a reset command - * @instance: adapter to reset - * - * Issue a reset sequence to the NCR5380 and try and get the bus - * back into sane shape. - * - * This clears the reset interrupt flag because there may be no handler for - * it. When the driver is initialized, the NCR5380_intr() handler has not yet - * been installed. And when in EH we may have released the ST DMA interrupt. - */ - -static void do_reset(struct Scsi_Host *instance) -{ - unsigned long flags; - - local_irq_save(flags); - NCR5380_write(TARGET_COMMAND_REG, - PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK)); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); - udelay(50); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); - local_irq_restore(flags); -} - -/** - * do_abort - abort the currently established nexus by going to - * MESSAGE OUT phase and sending an ABORT message. - * @instance: relevant scsi host instance - * - * Returns 0 on success, -1 on failure. - */ - -static int do_abort(struct Scsi_Host *instance) -{ - unsigned char *msgptr, phase, tmp; - int len; - int rc; - - /* Request message out phase */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - - /* - * Wait for the target to indicate a valid phase by asserting - * REQ. Once this happens, we'll have either a MSGOUT phase - * and can immediately send the ABORT message, or we'll have some - * other phase and will have to source/sink data. - * - * We really don't care what value was on the bus or what value - * the target sees, so we just handshake. - */ - - rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ); - if (rc < 0) - goto timeout; - - tmp = NCR5380_read(STATUS_REG) & PHASE_MASK; - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); - - if (tmp != PHASE_MSGOUT) { - NCR5380_write(INITIATOR_COMMAND_REG, - ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ); - if (rc < 0) - goto timeout; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - } - - tmp = ABORT; - msgptr = &tmp; - len = 1; - phase = PHASE_MSGOUT; - NCR5380_transfer_pio(instance, &phase, &len, &msgptr); - - /* - * If we got here, and the command completed successfully, - * we're about to go into bus free state. - */ - - return len ? -1 : 0; - -timeout: - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - return -1; -} - - -/* - * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) - * - * Purpose : transfers data in given phase using either real - * or pseudo DMA. - * - * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. - * - * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transferred or exit - * is in same phase. - * - * Also, *phase, *count, *data are modified in place. - */ - - -static int NCR5380_transfer_dma(struct Scsi_Host *instance, - unsigned char *phase, int *count, - unsigned char **data) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - register int c = *count; - register unsigned char p = *phase; - -#if defined(CONFIG_SUN3) - /* sanity check */ - if (!sun3_dma_setup_done) { - pr_err("scsi%d: transfer_dma without setup!\n", - instance->host_no); - BUG(); - } - hostdata->dma_len = c; - - dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", - (p & SR_IO) ? "receive" : "send", c, *data); - - /* netbsd turns off ints here, why not be safe and do it too */ - - /* send start chain */ - sun3scsi_dma_start(c, *data); - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | - MR_ENABLE_EOP_INTR); - if (p & SR_IO) { - NCR5380_write(INITIATOR_COMMAND_REG, 0); - NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); - } else { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_DATA); - NCR5380_write(START_DMA_SEND_REG, 0); - } - -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_DMA_ENABLE; -#endif - - sun3_dma_active = 1; - -#else /* !defined(CONFIG_SUN3) */ - register unsigned char *d = *data; - unsigned char tmp; - - if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { - *phase = tmp; - return -1; - } - - if (hostdata->read_overruns && (p & SR_IO)) - c -= hostdata->read_overruns; - - dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", - (p & SR_IO) ? "receive" : "send", c, d); - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | - MR_ENABLE_EOP_INTR); - - if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) { - /* On the Medusa, it is a must to initialize the DMA before - * starting the NCR. This is also the cleaner way for the TT. - */ - hostdata->dma_len = (p & SR_IO) ? - NCR5380_dma_read_setup(instance, d, c) : - NCR5380_dma_write_setup(instance, d, c); - } - - if (p & SR_IO) - NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); - else { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); - NCR5380_write(START_DMA_SEND_REG, 0); - } - - if (hostdata->flags & FLAG_LATE_DMA_SETUP) { - /* On the Falcon, the DMA setup must be done after the last */ - /* NCR access, else the DMA setup gets trashed! - */ - hostdata->dma_len = (p & SR_IO) ? - NCR5380_dma_read_setup(instance, d, c) : - NCR5380_dma_write_setup(instance, d, c); - } -#endif /* !defined(CONFIG_SUN3) */ - - return 0; -} - -/* - * Function : NCR5380_information_transfer (struct Scsi_Host *instance) - * - * Purpose : run through the various SCSI phases and do as the target - * directs us to. Operates on the currently connected command, - * instance->connected. - * - * Inputs : instance, instance for which we are doing commands - * - * Side effects : SCSI things happen, the disconnected queue will be - * modified if a command disconnects, *instance->connected will - * change. - * - * XXX Note : we need to watch for bus free or a reset condition here - * to recover from an unexpected bus free condition. - */ - -static void NCR5380_information_transfer(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char msgout = NOP; - int sink = 0; - int len; - int transfersize; - unsigned char *data; - unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; - struct scsi_cmnd *cmd; - -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_INTR; -#endif - - while ((cmd = hostdata->connected)) { - struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - - tmp = NCR5380_read(STATUS_REG); - /* We only have a valid SCSI phase when REQ is asserted */ - if (tmp & SR_REQ) { - phase = (tmp & PHASE_MASK); - if (phase != old_phase) { - old_phase = phase; - NCR5380_dprint_phase(NDEBUG_INFORMATION, instance); - } -#if defined(CONFIG_SUN3) - if (phase == PHASE_CMDOUT) { - void *d; - unsigned long count; - - if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { - count = cmd->SCp.buffer->length; - d = sg_virt(cmd->SCp.buffer); - } else { - count = cmd->SCp.this_residual; - d = cmd->SCp.ptr; - } - /* this command setup for dma yet? */ - if (sun3_dma_setup_done != cmd && - sun3scsi_dma_xfer_len(count, cmd) > 0) { - sun3scsi_dma_setup(instance, d, count, - rq_data_dir(cmd->request)); - sun3_dma_setup_done = cmd; - } -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_INTR; -#endif - } -#endif /* CONFIG_SUN3 */ - - if (sink && (phase != PHASE_MSGOUT)) { - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | - ICR_ASSERT_ACK); - while (NCR5380_read(STATUS_REG) & SR_REQ) - ; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_ATN); - sink = 0; - continue; - } - - switch (phase) { - case PHASE_DATAOUT: -#if (NDEBUG & NDEBUG_NO_DATAOUT) - shost_printk(KERN_DEBUG, instance, "NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n"); - sink = 1; - do_abort(instance); - cmd->result = DID_ERROR << 16; - complete_cmd(instance, cmd); - hostdata->connected = NULL; - return; -#endif - case PHASE_DATAIN: - /* - * If there is no room left in the current buffer in the - * scatter-gather list, move onto the next one. - */ - - if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { - ++cmd->SCp.buffer; - --cmd->SCp.buffers_residual; - cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); - merge_contiguous_buffers(cmd); - dsprintk(NDEBUG_INFORMATION, instance, "%d bytes and %d buffers left\n", - cmd->SCp.this_residual, - cmd->SCp.buffers_residual); - } - - /* - * The preferred transfer method is going to be - * PSEUDO-DMA for systems that are strictly PIO, - * since we can let the hardware do the handshaking. - * - * For this to work, we need to know the transfersize - * ahead of time, since the pseudo-DMA code will sit - * in an unconditional loop. - */ - -#if !defined(CONFIG_SUN3) - transfersize = 0; - if (!cmd->device->borken) -#endif - transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); - - if (transfersize > 0) { - len = transfersize; - cmd->SCp.phase = phase; - if (NCR5380_transfer_dma(instance, &phase, - &len, (unsigned char **)&cmd->SCp.ptr)) { - /* - * If the watchdog timer fires, all future - * accesses to this device will use the - * polled-IO. - */ - scmd_printk(KERN_INFO, cmd, - "switching to slow handshake\n"); - cmd->device->borken = 1; - sink = 1; - do_abort(instance); - cmd->result = DID_ERROR << 16; - /* XXX - need to source or sink data here, as appropriate */ - } else - return; - } else { - /* Break up transfer into 3 ms chunks, - * presuming 6 accesses per handshake. - */ - transfersize = min((unsigned long)cmd->SCp.this_residual, - hostdata->accesses_per_ms / 2); - len = transfersize; - NCR5380_transfer_pio(instance, &phase, &len, - (unsigned char **)&cmd->SCp.ptr); - cmd->SCp.this_residual -= transfersize - len; - } -#if defined(CONFIG_SUN3) - /* if we had intended to dma that command clear it */ - if (sun3_dma_setup_done == cmd) - sun3_dma_setup_done = NULL; -#endif - return; - case PHASE_MSGIN: - len = 1; - data = &tmp; - NCR5380_transfer_pio(instance, &phase, &len, &data); - cmd->SCp.Message = tmp; - - switch (tmp) { - case ABORT: - case COMMAND_COMPLETE: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dsprintk(NDEBUG_QUEUES, instance, - "COMMAND COMPLETE %p target %d lun %llu\n", - cmd, scmd_id(cmd), cmd->device->lun); - - hostdata->connected = NULL; -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); - if (status_byte(cmd->SCp.Status) == QUEUE_FULL) { - u8 lun = cmd->device->lun; - struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun]; - - dsprintk(NDEBUG_TAGS, instance, - "QUEUE_FULL %p target %d lun %d nr_allocated %d\n", - cmd, scmd_id(cmd), lun, ta->nr_allocated); - if (ta->queue_size > ta->nr_allocated) - ta->queue_size = ta->nr_allocated; - } -#endif - - cmd->result &= ~0xffff; - cmd->result |= cmd->SCp.Status; - cmd->result |= cmd->SCp.Message << 8; - - if (cmd->cmnd[0] == REQUEST_SENSE) - complete_cmd(instance, cmd); - else { - if (cmd->SCp.Status == SAM_STAT_CHECK_CONDITION || - cmd->SCp.Status == SAM_STAT_COMMAND_TERMINATED) { - dsprintk(NDEBUG_QUEUES, instance, "autosense: adding cmd %p to tail of autosense queue\n", - cmd); - list_add_tail(&ncmd->list, - &hostdata->autosense); - } else - complete_cmd(instance, cmd); - } - - /* - * Restore phase bits to 0 so an interrupted selection, - * arbitration can resume. - */ - NCR5380_write(TARGET_COMMAND_REG, 0); - - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - - maybe_release_dma_irq(instance); - return; - case MESSAGE_REJECT: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - switch (hostdata->last_message) { - case HEAD_OF_QUEUE_TAG: - case ORDERED_QUEUE_TAG: - case SIMPLE_QUEUE_TAG: - /* The target obviously doesn't support tagged - * queuing, even though it announced this ability in - * its INQUIRY data ?!? (maybe only this LUN?) Ok, - * clear 'tagged_supported' and lock the LUN, since - * the command is treated as untagged further on. - */ - cmd->device->tagged_supported = 0; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); - cmd->tag = TAG_NONE; - dsprintk(NDEBUG_TAGS, instance, "target %d lun %llu rejected QUEUE_TAG message; tagged queuing disabled\n", - scmd_id(cmd), cmd->device->lun); - break; - } - break; - case DISCONNECT: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - hostdata->connected = NULL; - list_add(&ncmd->list, &hostdata->disconnected); - dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, - instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", - cmd, scmd_id(cmd), cmd->device->lun); - - /* - * Restore phase bits to 0 so an interrupted selection, - * arbitration can resume. - */ - NCR5380_write(TARGET_COMMAND_REG, 0); - - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_DMA_ENABLE; -#endif - return; - /* - * The SCSI data pointer is *IMPLICITLY* saved on a disconnect - * operation, in violation of the SCSI spec so we can safely - * ignore SAVE/RESTORE pointers calls. - * - * Unfortunately, some disks violate the SCSI spec and - * don't issue the required SAVE_POINTERS message before - * disconnecting, and we have to break spec to remain - * compatible. - */ - case SAVE_POINTERS: - case RESTORE_POINTERS: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - break; - case EXTENDED_MESSAGE: - /* - * Start the message buffer with the EXTENDED_MESSAGE - * byte, since spi_print_msg() wants the whole thing. - */ - extended_msg[0] = EXTENDED_MESSAGE; - /* Accept first byte by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - spin_unlock_irq(&hostdata->lock); - - dsprintk(NDEBUG_EXTENDED, instance, "receiving extended message\n"); - - len = 2; - data = extended_msg + 1; - phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); - dsprintk(NDEBUG_EXTENDED, instance, "length %d, code 0x%02x\n", - (int)extended_msg[1], - (int)extended_msg[2]); - - if (!len && extended_msg[1] > 0 && - extended_msg[1] <= sizeof(extended_msg) - 2) { - /* Accept third byte by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - len = extended_msg[1] - 1; - data = extended_msg + 3; - phase = PHASE_MSGIN; - - NCR5380_transfer_pio(instance, &phase, &len, &data); - dsprintk(NDEBUG_EXTENDED, instance, "message received, residual %d\n", - len); - - switch (extended_msg[2]) { - case EXTENDED_SDTR: - case EXTENDED_WDTR: - case EXTENDED_MODIFY_DATA_POINTER: - case EXTENDED_EXTENDED_IDENTIFY: - tmp = 0; - } - } else if (len) { - shost_printk(KERN_ERR, instance, "error receiving extended message\n"); - tmp = 0; - } else { - shost_printk(KERN_NOTICE, instance, "extended message code %02x length %d is too long\n", - extended_msg[2], extended_msg[1]); - tmp = 0; - } - - spin_lock_irq(&hostdata->lock); - if (!hostdata->connected) - return; - - /* Fall through to reject message */ - - /* - * If we get something weird that we aren't expecting, - * reject it. - */ - default: - if (!tmp) { - shost_printk(KERN_ERR, instance, "rejecting message "); - spi_print_msg(extended_msg); - printk("\n"); - } else if (tmp != EXTENDED_MESSAGE) - scmd_printk(KERN_INFO, cmd, - "rejecting unknown message %02x\n", - tmp); - else - scmd_printk(KERN_INFO, cmd, - "rejecting unknown extended message code %02x, length %d\n", - extended_msg[1], extended_msg[0]); - - msgout = MESSAGE_REJECT; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - break; - } /* switch (tmp) */ - break; - case PHASE_MSGOUT: - len = 1; - data = &msgout; - hostdata->last_message = msgout; - NCR5380_transfer_pio(instance, &phase, &len, &data); - if (msgout == ABORT) { - hostdata->connected = NULL; - cmd->result = DID_ERROR << 16; - complete_cmd(instance, cmd); - maybe_release_dma_irq(instance); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return; - } - msgout = NOP; - break; - case PHASE_CMDOUT: - len = cmd->cmd_len; - data = cmd->cmnd; - /* - * XXX for performance reasons, on machines with a - * PSEUDO-DMA architecture we should probably - * use the dma transfer function. - */ - NCR5380_transfer_pio(instance, &phase, &len, &data); - break; - case PHASE_STATIN: - len = 1; - data = &tmp; - NCR5380_transfer_pio(instance, &phase, &len, &data); - cmd->SCp.Status = tmp; - break; - default: - shost_printk(KERN_ERR, instance, "unknown phase\n"); - NCR5380_dprint(NDEBUG_ANY, instance); - } /* switch(phase) */ - } else { - spin_unlock_irq(&hostdata->lock); - NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); - spin_lock_irq(&hostdata->lock); - } - } -} - -/* - * Function : void NCR5380_reselect (struct Scsi_Host *instance) - * - * Purpose : does reselection, initializing the instance->connected - * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q - * nexus has been reestablished, - * - * Inputs : instance - this instance of the NCR5380. - */ - - -/* it might eventually prove necessary to do a dma setup on - reselection, but it doesn't seem to be needed now -- sam */ - -static void NCR5380_reselect(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char target_mask; - unsigned char lun; -#ifdef SUPPORT_TAGS - unsigned char tag; -#endif - unsigned char msg[3]; - int __maybe_unused len; - unsigned char __maybe_unused *data, __maybe_unused phase; - struct NCR5380_cmd *ncmd; - struct scsi_cmnd *tmp; - - /* - * Disable arbitration, etc. since the host adapter obviously - * lost, and tell an interrupted NCR5380_select() to restart. - */ - - NCR5380_write(MODE_REG, MR_BASE); - - target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); - - dsprintk(NDEBUG_RESELECTION, instance, "reselect\n"); - - /* - * At this point, we have detected that our SCSI ID is on the bus, - * SEL is true and BSY was false for at least one bus settle delay - * (400 ns). - * - * We must assert BSY ourselves, until the target drops the SEL - * signal. - */ - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); - if (NCR5380_poll_politely(instance, - STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - return; - } - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - /* - * Wait for target to go into MSGIN. - */ - - if (NCR5380_poll_politely(instance, - STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) { - do_abort(instance); - return; - } - -#if defined(CONFIG_SUN3) - /* acknowledge toggle to MSGIN */ - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN)); - - /* peek at the byte without really hitting the bus */ - msg[0] = NCR5380_read(CURRENT_SCSI_DATA_REG); -#else - len = 1; - data = msg; - phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); - - if (len) { - do_abort(instance); - return; - } -#endif - - if (!(msg[0] & 0x80)) { - shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got "); - spi_print_msg(msg); - printk("\n"); - do_abort(instance); - return; - } - lun = msg[0] & 0x07; - -#if defined(SUPPORT_TAGS) && !defined(CONFIG_SUN3) - /* If the phase is still MSGIN, the target wants to send some more - * messages. In case it supports tagged queuing, this is probably a - * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus. - */ - tag = TAG_NONE; - if (phase == PHASE_MSGIN && (hostdata->flags & FLAG_TAGGED_QUEUING)) { - /* Accept previous IDENTIFY message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - len = 2; - data = msg + 1; - if (!NCR5380_transfer_pio(instance, &phase, &len, &data) && - msg[1] == SIMPLE_QUEUE_TAG) - tag = msg[2]; - dsprintk(NDEBUG_TAGS, instance, "reselect: target mask %02x, lun %d sent tag %d\n", - target_mask, lun, tag); - } -#endif - - /* - * Find the command corresponding to the I_T_L or I_T_L_Q nexus we - * just reestablished, and remove it from the disconnected queue. - */ - - tmp = NULL; - list_for_each_entry(ncmd, &hostdata->disconnected, list) { - struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); - - if (target_mask == (1 << scmd_id(cmd)) && - lun == (u8)cmd->device->lun -#ifdef SUPPORT_TAGS - && (tag == cmd->tag) -#endif - ) { - list_del(&ncmd->list); - tmp = cmd; - break; - } - } - - if (tmp) { - dsprintk(NDEBUG_RESELECTION | NDEBUG_QUEUES, instance, - "reselect: removed %p from disconnected queue\n", tmp); - } else { - -#ifdef SUPPORT_TAGS - shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d tag %d not in disconnected queue.\n", - target_mask, lun, tag); -#else - shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n", - target_mask, lun); -#endif - /* - * Since we have an established nexus that we can't do anything - * with, we must abort it. - */ - do_abort(instance); - return; - } - -#if defined(CONFIG_SUN3) - /* engage dma setup for the command we just saw */ - { - void *d; - unsigned long count; - - if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) { - count = tmp->SCp.buffer->length; - d = sg_virt(tmp->SCp.buffer); - } else { - count = tmp->SCp.this_residual; - d = tmp->SCp.ptr; - } - /* setup this command for dma if not already */ - if (sun3_dma_setup_done != tmp && - sun3scsi_dma_xfer_len(count, tmp) > 0) { - sun3scsi_dma_setup(instance, d, count, - rq_data_dir(tmp->request)); - sun3_dma_setup_done = tmp; - } - } - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); -#endif - - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - -#if defined(SUPPORT_TAGS) && defined(CONFIG_SUN3) - /* If the phase is still MSGIN, the target wants to send some more - * messages. In case it supports tagged queuing, this is probably a - * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus. - */ - tag = TAG_NONE; - if (phase == PHASE_MSGIN && setup_use_tagged_queuing) { - /* Accept previous IDENTIFY message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - len = 2; - data = msg + 1; - if (!NCR5380_transfer_pio(instance, &phase, &len, &data) && - msg[1] == SIMPLE_QUEUE_TAG) - tag = msg[2]; - dsprintk(NDEBUG_TAGS, instance, "reselect: target mask %02x, lun %d sent tag %d\n" - target_mask, lun, tag); - } -#endif - - hostdata->connected = tmp; - dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu, tag %d\n", - scmd_id(tmp), tmp->device->lun, tmp->tag); -} - - -/** - * list_find_cmd - test for presence of a command in a linked list - * @haystack: list of commands - * @needle: command to search for - */ - -static bool list_find_cmd(struct list_head *haystack, - struct scsi_cmnd *needle) -{ - struct NCR5380_cmd *ncmd; - - list_for_each_entry(ncmd, haystack, list) - if (NCR5380_to_scmd(ncmd) == needle) - return true; - return false; -} - -/** - * list_remove_cmd - remove a command from linked list - * @haystack: list of commands - * @needle: command to remove - */ - -static bool list_del_cmd(struct list_head *haystack, - struct scsi_cmnd *needle) -{ - if (list_find_cmd(haystack, needle)) { - struct NCR5380_cmd *ncmd = scsi_cmd_priv(needle); - - list_del(&ncmd->list); - return true; - } - return false; -} - -/** - * NCR5380_abort - scsi host eh_abort_handler() method - * @cmd: the command to be aborted - * - * Try to abort a given command by removing it from queues and/or sending - * the target an abort message. This may not succeed in causing a target - * to abort the command. Nonetheless, the low-level driver must forget about - * the command because the mid-layer reclaims it and it may be re-issued. - * - * The normal path taken by a command is as follows. For EH we trace this - * same path to locate and abort the command. - * - * unissued -> selecting -> [unissued -> selecting ->]... connected -> - * [disconnected -> connected ->]... - * [autosense -> connected ->] done - * - * If cmd was not found at all then presumably it has already been completed, - * in which case return SUCCESS to try to avoid further EH measures. - * - * If the command has not completed yet, we must not fail to find it. - * We have no option but to forget the aborted command (even if it still - * lacks sense data). The mid-layer may re-issue a command that is in error - * recovery (see scsi_send_eh_cmnd), but the logic and data structures in - * this driver are such that a command can appear on one queue only. - * - * The lock protects driver data structures, but EH handlers also use it - * to serialize their own execution and prevent their own re-entry. - */ - -static int NCR5380_abort(struct scsi_cmnd *cmd) -{ - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned long flags; - int result = SUCCESS; - - spin_lock_irqsave(&hostdata->lock, flags); - -#if (NDEBUG & NDEBUG_ANY) - scmd_printk(KERN_INFO, cmd, __func__); -#endif - NCR5380_dprint(NDEBUG_ANY, instance); - NCR5380_dprint_phase(NDEBUG_ANY, instance); - - if (list_del_cmd(&hostdata->unissued, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: removed %p from issue queue\n", cmd); - cmd->result = DID_ABORT << 16; - cmd->scsi_done(cmd); /* No tag or busy flag to worry about */ - goto out; - } - - if (hostdata->selecting == cmd) { - dsprintk(NDEBUG_ABORT, instance, - "abort: cmd %p == selecting\n", cmd); - hostdata->selecting = NULL; - cmd->result = DID_ABORT << 16; - complete_cmd(instance, cmd); - goto out; - } - - if (list_del_cmd(&hostdata->disconnected, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: removed %p from disconnected list\n", cmd); - /* Can't call NCR5380_select() and send ABORT because that - * means releasing the lock. Need a bus reset. - */ - set_host_byte(cmd, DID_ERROR); - complete_cmd(instance, cmd); - result = FAILED; - goto out; - } - - if (hostdata->connected == cmd) { - dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); - hostdata->connected = NULL; - hostdata->dma_len = 0; - if (do_abort(instance)) { - set_host_byte(cmd, DID_ERROR); - complete_cmd(instance, cmd); - result = FAILED; - goto out; - } - set_host_byte(cmd, DID_ABORT); - complete_cmd(instance, cmd); - goto out; - } - - if (list_del_cmd(&hostdata->autosense, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: removed %p from sense queue\n", cmd); - set_host_byte(cmd, DID_ERROR); - complete_cmd(instance, cmd); - } - -out: - if (result == FAILED) - dsprintk(NDEBUG_ABORT, instance, "abort: failed to abort %p\n", cmd); - else - dsprintk(NDEBUG_ABORT, instance, "abort: successfully aborted %p\n", cmd); - - queue_work(hostdata->work_q, &hostdata->main_task); - maybe_release_dma_irq(instance); - spin_unlock_irqrestore(&hostdata->lock, flags); - - return result; -} - - -/** - * NCR5380_bus_reset - reset the SCSI bus - * @cmd: SCSI command undergoing EH - * - * Returns SUCCESS - */ - -static int NCR5380_bus_reset(struct scsi_cmnd *cmd) -{ - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int i; - unsigned long flags; - struct NCR5380_cmd *ncmd; - - spin_lock_irqsave(&hostdata->lock, flags); - -#if (NDEBUG & NDEBUG_ANY) - scmd_printk(KERN_INFO, cmd, __func__); -#endif - NCR5380_dprint(NDEBUG_ANY, instance); - NCR5380_dprint_phase(NDEBUG_ANY, instance); - - do_reset(instance); - - /* reset NCR registers */ - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(TARGET_COMMAND_REG, 0); - NCR5380_write(SELECT_ENABLE_REG, 0); - - /* After the reset, there are no more connected or disconnected commands - * and no busy units; so clear the low-level status here to avoid - * conflicts when the mid-level code tries to wake up the affected - * commands! - */ - - if (list_del_cmd(&hostdata->unissued, cmd)) { - cmd->result = DID_RESET << 16; - cmd->scsi_done(cmd); - } - - if (hostdata->selecting) { - hostdata->selecting->result = DID_RESET << 16; - complete_cmd(instance, hostdata->selecting); - hostdata->selecting = NULL; - } - - list_for_each_entry(ncmd, &hostdata->disconnected, list) { - struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); - - set_host_byte(cmd, DID_RESET); - cmd->scsi_done(cmd); - } - INIT_LIST_HEAD(&hostdata->disconnected); - - list_for_each_entry(ncmd, &hostdata->autosense, list) { - struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); - - set_host_byte(cmd, DID_RESET); - cmd->scsi_done(cmd); - } - INIT_LIST_HEAD(&hostdata->autosense); - - if (hostdata->connected) { - set_host_byte(hostdata->connected, DID_RESET); - complete_cmd(instance, hostdata->connected); - hostdata->connected = NULL; - } - -#ifdef SUPPORT_TAGS - free_all_tags(hostdata); -#endif - for (i = 0; i < 8; ++i) - hostdata->busy[i] = 0; - hostdata->dma_len = 0; - - queue_work(hostdata->work_q, &hostdata->main_task); - maybe_release_dma_irq(instance); - spin_unlock_irqrestore(&hostdata->lock, flags); - - return SUCCESS; -} diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 445c26724ba1..49b7b14e8913 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -87,9 +87,6 @@ /* Definitions for the core NCR5380 driver. */ -#define SUPPORT_TAGS -#define MAX_TAGS 32 - #define NCR5380_implementation_fields /* none */ #define NCR5380_read(reg) atari_scsi_reg_read(reg) @@ -189,8 +186,6 @@ static int setup_cmd_per_lun = -1; module_param(setup_cmd_per_lun, int, 0); static int setup_sg_tablesize = -1; module_param(setup_sg_tablesize, int, 0); -static int setup_use_tagged_queuing = -1; -module_param(setup_use_tagged_queuing, int, 0); static int setup_hostid = -1; module_param(setup_hostid, int, 0); static int setup_toshiba_delay = -1; @@ -479,8 +474,7 @@ static int __init atari_scsi_setup(char *str) setup_sg_tablesize = ints[3]; if (ints[0] >= 4) setup_hostid = ints[4]; - if (ints[0] >= 5) - setup_use_tagged_queuing = ints[5]; + /* ints[5] (use_tagged_queuing) is ignored */ /* ints[6] (use_pdma) is ignored */ if (ints[0] >= 7) setup_toshiba_delay = ints[7]; @@ -853,9 +847,6 @@ static int __init atari_scsi_probe(struct platform_device *pdev) instance->irq = irq->start; host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP; -#ifdef SUPPORT_TAGS - host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0; -#endif host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; error = NCR5380_init(instance, host_flags); diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 4de6589fdbfb..42feba7e350b 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -55,8 +55,6 @@ static int setup_sg_tablesize = -1; module_param(setup_sg_tablesize, int, 0); static int setup_use_pdma = -1; module_param(setup_use_pdma, int, 0); -static int setup_use_tagged_queuing = -1; -module_param(setup_use_tagged_queuing, int, 0); static int setup_hostid = -1; module_param(setup_hostid, int, 0); static int setup_toshiba_delay = -1; @@ -95,8 +93,7 @@ static int __init mac_scsi_setup(char *str) setup_sg_tablesize = ints[3]; if (ints[0] >= 4) setup_hostid = ints[4]; - if (ints[0] >= 5) - setup_use_tagged_queuing = ints[5]; + /* ints[5] (use_tagged_queuing) is ignored */ if (ints[0] >= 6) setup_use_pdma = ints[6]; if (ints[0] >= 7) @@ -382,9 +379,6 @@ static int __init mac_scsi_probe(struct platform_device *pdev) } else host_flags |= FLAG_NO_PSEUDO_DMA; -#ifdef SUPPORT_TAGS - host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0; -#endif host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; error = NCR5380_init(instance, host_flags | FLAG_LATE_DMA_SETUP); diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index f2fc788cb08b..3c4c07038948 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -41,9 +41,6 @@ /* Definitions for the core NCR5380 driver. */ -/* #define SUPPORT_TAGS */ -/* #define MAX_TAGS 32 */ - #define NCR5380_implementation_fields /* none */ #define NCR5380_read(reg) sun3scsi_read(reg) @@ -75,10 +72,6 @@ static int setup_cmd_per_lun = -1; module_param(setup_cmd_per_lun, int, 0); static int setup_sg_tablesize = -1; module_param(setup_sg_tablesize, int, 0); -#ifdef SUPPORT_TAGS -static int setup_use_tagged_queuing = -1; -module_param(setup_use_tagged_queuing, int, 0); -#endif static int setup_hostid = -1; module_param(setup_hostid, int, 0); @@ -512,10 +505,6 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) instance->io_port = (unsigned long)ioaddr; instance->irq = irq->start; -#ifdef SUPPORT_TAGS - host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0; -#endif - error = NCR5380_init(instance, host_flags); if (error) goto fail_init; From ae5e33af42eb1f1262cfc8722072561b908bf914 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:23 +1100 Subject: [PATCH 017/138] ncr5380: Reduce max_lun limit The driver has a limit of eight LUs because of the byte-sized bitfield that is used for busy flags. That means the maximum LUN is 7. The default is 8. Signed-off-by: Finn Thain Tested-by: Michael Schmitz Tested-by: Ondrej Zary Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 305330b26349..5187c31a48be 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -488,6 +488,8 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) int i; unsigned long deadline; + instance->max_lun = 7; + hostdata->host = instance; hostdata->id_mask = 1 << instance->this_id; hostdata->id_higher_mask = 0; From 4712bd8d473da5e99d2328654bdba565de8b43ce Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:24 +1100 Subject: [PATCH 018/138] dmx3191d: Drop max_sectors limit The dmx3191d driver is not capable of DMA or PDMA so all transfers use PIO. Now that large slow PIO transfers periodically stop and call cond_resched(), the max_sectors limit can go away. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/dmx3191d.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index cc46d67b9f6f..f8d9bd8eaa6f 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -67,7 +67,6 @@ static struct scsi_host_template dmx3191d_driver_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, - .max_sectors = 128, }; static int dmx3191d_probe_one(struct pci_dev *pdev, From 12866b99e57cf9eba809503c687fc1a25c529c4a Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:25 +1100 Subject: [PATCH 019/138] ncr5380: Fix register decoding for debugging Decode all bits in the chip registers. They are all useful at times. Fix printk severity so that this output can be suppressed along with the other debugging output. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 5187c31a48be..c93d207dafc8 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -256,12 +256,20 @@ static struct { {0, NULL} }, basrs[] = { + {BASR_END_DMA_TRANSFER, "END OF DMA"}, + {BASR_DRQ, "DRQ"}, + {BASR_PARITY_ERROR, "PARITY ERROR"}, + {BASR_IRQ, "IRQ"}, + {BASR_PHASE_MATCH, "PHASE MATCH"}, + {BASR_BUSY_ERROR, "BUSY ERROR"}, {BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL} }, icrs[] = { {ICR_ASSERT_RST, "ASSERT RST"}, + {ICR_ARBITRATION_PROGRESS, "ARB. IN PROGRESS"}, + {ICR_ARBITRATION_LOST, "LOST ARB."}, {ICR_ASSERT_ACK, "ASSERT ACK"}, {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, @@ -270,14 +278,14 @@ icrs[] = { {0, NULL} }, mrs[] = { - {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, - {MR_TARGET, "MODE TARGET"}, - {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, - {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, - {MR_ENABLE_EOP_INTR, "MODE EOP INTR"}, - {MR_MONITOR_BSY, "MODE MONITOR BSY"}, - {MR_DMA_MODE, "MODE DMA"}, - {MR_ARBITRATE, "MODE ARBITRATION"}, + {MR_BLOCK_DMA_MODE, "BLOCK DMA MODE"}, + {MR_TARGET, "TARGET"}, + {MR_ENABLE_PAR_CHECK, "PARITY CHECK"}, + {MR_ENABLE_PAR_INTR, "PARITY INTR"}, + {MR_ENABLE_EOP_INTR, "EOP INTR"}, + {MR_MONITOR_BSY, "MONITOR BSY"}, + {MR_DMA_MODE, "DMA MODE"}, + {MR_ARBITRATE, "ARBITRATE"}, {0, NULL} }; @@ -298,23 +306,23 @@ static void NCR5380_print(struct Scsi_Host *instance) icr = NCR5380_read(INITIATOR_COMMAND_REG); basr = NCR5380_read(BUS_AND_STATUS_REG); - printk("STATUS_REG: %02x ", status); + printk(KERN_DEBUG "SR = 0x%02x : ", status); for (i = 0; signals[i].mask; ++i) if (status & signals[i].mask) - printk(",%s", signals[i].name); - printk("\nBASR: %02x ", basr); + printk(KERN_CONT "%s, ", signals[i].name); + printk(KERN_CONT "\nBASR = 0x%02x : ", basr); for (i = 0; basrs[i].mask; ++i) if (basr & basrs[i].mask) - printk(",%s", basrs[i].name); - printk("\nICR: %02x ", icr); + printk(KERN_CONT "%s, ", basrs[i].name); + printk(KERN_CONT "\nICR = 0x%02x : ", icr); for (i = 0; icrs[i].mask; ++i) if (icr & icrs[i].mask) - printk(",%s", icrs[i].name); - printk("\nMODE: %02x ", mr); + printk(KERN_CONT "%s, ", icrs[i].name); + printk(KERN_CONT "\nMR = 0x%02x : ", mr); for (i = 0; mrs[i].mask; ++i) if (mr & mrs[i].mask) - printk(",%s", mrs[i].name); - printk("\n"); + printk(KERN_CONT "%s, ", mrs[i].name); + printk(KERN_CONT "\n"); } static struct { From f0ea73a4ef4ad86cc8430b6a0463a61b90472718 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:26 +1100 Subject: [PATCH 020/138] ncr5380: Remove remaining register storage qualifiers Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index c93d207dafc8..69a0d9d154fe 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1555,9 +1555,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char **data) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - register int c = *count; - register unsigned char p = *phase; - register unsigned char *d = *data; + int c = *count; + unsigned char p = *phase; + unsigned char *d = *data; unsigned char tmp; int result = 0; From a46865dcf1f7166808664ab096678f81d4fbb853 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:27 +1100 Subject: [PATCH 021/138] ncr5380: Remove DONT_USE_INTR and AUTOPROBE_IRQ macros Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 12 +----------- drivers/scsi/NCR5380.h | 4 ---- drivers/scsi/arm/oak.c | 2 -- drivers/scsi/dmx3191d.c | 2 -- drivers/scsi/dtc.c | 12 +++--------- drivers/scsi/g_NCR5380.c | 2 -- drivers/scsi/pas16.c | 1 - drivers/scsi/t128.c | 1 - 8 files changed, 4 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 69a0d9d154fe..52e7d2b57902 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -106,9 +106,6 @@ * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential * transceivers. * - * DONT_USE_INTR - if defined, never use interrupts, even if we probe or - * override-configure an IRQ. - * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. * * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. @@ -464,9 +461,6 @@ static void prepare_info(struct Scsi_Host *instance) hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "", hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", -#ifdef AUTOPROBE_IRQ - "AUTOPROBE_IRQ " -#endif #ifdef DIFFERENTIAL "DIFFERENTIAL " #endif @@ -915,8 +909,6 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) } } -#ifndef DONT_USE_INTR - /** * NCR5380_intr - generic NCR5380 irq handler * @irq: interrupt number @@ -951,7 +943,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) * the Busy Monitor interrupt is enabled together with DMA Mode. */ -static irqreturn_t NCR5380_intr(int irq, void *dev_id) +static irqreturn_t __maybe_unused NCR5380_intr(int irq, void *dev_id) { struct Scsi_Host *instance = dev_id; struct NCR5380_hostdata *hostdata = shost_priv(instance); @@ -1020,8 +1012,6 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) return IRQ_RETVAL(handled); } -#endif - /* * Function : int NCR5380_select(struct Scsi_Host *instance, * struct scsi_cmnd *cmd) diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 5c2411f05852..076f8969dd22 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -280,16 +280,12 @@ static void NCR5380_print(struct Scsi_Host *instance); #define NCR5380_dprint_phase(flg, arg) do {} while (0) #endif -#if defined(AUTOPROBE_IRQ) static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible); -#endif static int NCR5380_init(struct Scsi_Host *instance, int flags); static int NCR5380_maybe_reset_bus(struct Scsi_Host *); static void NCR5380_exit(struct Scsi_Host *instance); static void NCR5380_information_transfer(struct Scsi_Host *instance); -#ifndef DONT_USE_INTR static irqreturn_t NCR5380_intr(int irq, void *dev_id); -#endif static void NCR5380_main(struct work_struct *work); static const char *NCR5380_info(struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance); diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 3aac99c21267..a396024a3cae 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -14,8 +14,6 @@ #include -#define DONT_USE_INTR - #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) #define NCR5380_read(reg) \ diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index f8d9bd8eaa6f..9b5a457d4bca 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -34,8 +34,6 @@ * Definitions for the generic 5380 driver. */ -#define DONT_USE_INTR - #define NCR5380_read(reg) inb(instance->io_port + reg) #define NCR5380_write(reg, value) outb(value, instance->io_port + reg) diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index e87c632234f3..459863f94e46 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -1,5 +1,3 @@ -#define DONT_USE_INTR - /* * DTC 3180/3280 driver, by * Ray Van Tassle rayvt@comm.mot.com @@ -53,7 +51,6 @@ #include #include "dtc.h" -#define AUTOPROBE_IRQ #include "NCR5380.h" /* @@ -243,9 +240,10 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) if (instance->irq == 255) instance->irq = NO_IRQ; -#ifndef DONT_USE_INTR /* With interrupts enabled, it will sometimes hang when doing heavy * reads. So better not enable them until I finger it out. */ + instance->irq = NO_IRQ; + if (instance->irq != NO_IRQ) if (request_irq(instance->irq, dtc_intr, 0, "dtc", instance)) { @@ -257,11 +255,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); } -#else - if (instance->irq != NO_IRQ) - printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no); - instance->irq = NO_IRQ; -#endif + dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n", instance->host_no, instance->irq); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 09e1cf938ecf..18f4a4f99336 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -56,8 +56,6 @@ * */ -#define AUTOPROBE_IRQ - #include #include #include diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 62eef3f6d140..2f689ae7a803 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -75,7 +75,6 @@ #include #include "pas16.h" -#define AUTOPROBE_IRQ #include "NCR5380.h" diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index b5beecfaa3d5..8a8608ac62e6 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -74,7 +74,6 @@ #include #include "t128.h" -#define AUTOPROBE_IRQ #include "NCR5380.h" static struct override { From 9c41ab27e3fe0cfec16d3ac23f2067a516e337a4 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:28 +1100 Subject: [PATCH 022/138] ncr5380: Update usage documentation Update kernel parameter documentation for atari_scsi, mac_scsi and g_NCR5380 drivers. Remove duplication. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- Documentation/scsi/g_NCR5380.txt | 17 +++++------- Documentation/scsi/scsi-parameters.txt | 11 +++++--- drivers/scsi/g_NCR5380.c | 36 +------------------------- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/Documentation/scsi/g_NCR5380.txt b/Documentation/scsi/g_NCR5380.txt index 3b80f567f818..fd880150aeea 100644 --- a/Documentation/scsi/g_NCR5380.txt +++ b/Documentation/scsi/g_NCR5380.txt @@ -23,11 +23,10 @@ supported by the driver. If the default configuration does not work for you, you can use the kernel command lines (eg using the lilo append command): - ncr5380=port,irq,dma - ncr53c400=port,irq -or - ncr5380=base,irq,dma - ncr53c400=base,irq + ncr5380=addr,irq + ncr53c400=addr,irq + ncr53c400a=addr,irq + dtc3181e=addr,irq The driver does not probe for any addresses or ports other than those in the OVERRIDE or given to the kernel as above. @@ -36,19 +35,17 @@ This driver provides some information on what it has detected in /proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot time. More info to come in the future. -When NCR53c400 support is compiled in, BIOS parameters will be returned by -the driver (the raw 5380 driver does not and I don't plan to fiddle with -it!). - This driver works as a module. When included as a module, parameters can be passed on the insmod/modprobe command line: ncr_irq=xx the interrupt ncr_addr=xx the port or base address (for port or memory mapped, resp.) - ncr_dma=xx the DMA ncr_5380=1 to set up for a NCR5380 board ncr_53c400=1 to set up for a NCR53C400 board + ncr_53c400a=1 to set up for a NCR53C400A board + dtc_3181e=1 to set up for a Domex Technology Corp 3181E board + hp_c2502=1 to set up for a Hewlett Packard C2502 board e.g. modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1 for a port mapped NCR5380 board or diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 2bfd6f6d2d3d..1241ac11edb1 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -27,13 +27,15 @@ parameters may be changed at runtime by the command aic79xx= [HW,SCSI] See Documentation/scsi/aic79xx.txt. - atascsi= [HW,SCSI] Atari SCSI + atascsi= [HW,SCSI] + See drivers/scsi/atari_scsi.c. BusLogic= [HW,SCSI] See drivers/scsi/BusLogic.c, comment before function BusLogic_ParseDriverOptions(). dtc3181e= [HW,SCSI] + See Documentation/scsi/g_NCR5380.txt. eata= [HW,SCSI] @@ -51,8 +53,8 @@ parameters may be changed at runtime by the command ips= [HW,SCSI] Adaptec / IBM ServeRAID controller See header of drivers/scsi/ips.c. - mac5380= [HW,SCSI] Format: - ,,,, + mac5380= [HW,SCSI] + See drivers/scsi/mac_scsi.c. max_luns= [SCSI] Maximum number of LUNs to probe. Should be between 1 and 2^32-1. @@ -65,10 +67,13 @@ parameters may be changed at runtime by the command See header of drivers/scsi/NCR_D700.c. ncr5380= [HW,SCSI] + See Documentation/scsi/g_NCR5380.txt. ncr53c400= [HW,SCSI] + See Documentation/scsi/g_NCR5380.txt. ncr53c400a= [HW,SCSI] + See Documentation/scsi/g_NCR5380.txt. ncr53c406a= [HW,SCSI] diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 18f4a4f99336..516bd6c4f442 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -18,42 +18,8 @@ * * Added ISAPNP support for DTC436 adapters, * Thomas Sailer, sailer@ife.ee.ethz.ch - */ - -/* - * TODO : flesh out DMA support, find some one actually using this (I have - * a memory mapped Trantor board that works fine) - */ - -/* - * The card is detected and initialized in one of several ways : - * 1. With command line overrides - NCR5380=port,irq may be - * used on the LILO command line to override the defaults. * - * 2. With the GENERIC_NCR5380_OVERRIDE compile time define. This is - * specified as an array of address, irq, dma, board tuples. Ie, for - * one board at 0x350, IRQ5, no dma, I could say - * -DGENERIC_NCR5380_OVERRIDE={{0xcc000, 5, DMA_NONE, BOARD_NCR5380}} - * - * -1 should be specified for no or DMA interrupt, -2 to autoprobe for an - * IRQ line if overridden on the command line. - * - * 3. When included as a module, with arguments passed on the command line: - * ncr_irq=xx the interrupt - * ncr_addr=xx the port or base address (for port or memory - * mapped, resp.) - * ncr_dma=xx the DMA - * ncr_5380=1 to set up for a NCR5380 board - * ncr_53c400=1 to set up for a NCR53C400 board - * e.g. - * modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1 - * for a port mapped NCR5380 board or - * modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1 - * for a memory mapped NCR53C400 board with interrupts disabled. - * - * 255 should be specified for no or DMA interrupt, 254 to autoprobe for an - * IRQ line if overridden on the command line. - * + * See Documentation/scsi/g_NCR5380.txt for more info. */ #include From a5217a86369083af1f9630d17e9bb9e41ae7405a Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:29 +1100 Subject: [PATCH 023/138] atari_scsi: Set a reasonable default for cmd_per_lun This setting does not need to be conditional on Atari ST or TT. Signed-off-by: Finn Thain Tested-by: Michael Schmitz Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_scsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 49b7b14e8913..65af08139787 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -752,6 +752,7 @@ static struct scsi_host_template atari_scsi_template = { .eh_abort_handler = atari_scsi_abort, .eh_bus_reset_handler = atari_scsi_bus_reset, .this_id = 7, + .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, }; @@ -788,11 +789,9 @@ static int __init atari_scsi_probe(struct platform_device *pdev) */ if (ATARIHW_PRESENT(TT_SCSI)) { atari_scsi_template.can_queue = 16; - atari_scsi_template.cmd_per_lun = 8; atari_scsi_template.sg_tablesize = SG_ALL; } else { atari_scsi_template.can_queue = 8; - atari_scsi_template.cmd_per_lun = 1; atari_scsi_template.sg_tablesize = SG_NONE; } From ded155b5e4e735bdd654306145dff6491ce85766 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:30 +1100 Subject: [PATCH 024/138] atari_scsi: Allow can_queue to be increased for Falcon The benefit of limiting can_queue to 1 is that atari_scsi shares the ST DMA chip more fairly with other drivers (e.g. falcon-ide). Unfortunately, this can limit SCSI bus utilization. On systems without IDE, atari_scsi should issue SCSI commands whenever it can arbitrate for the bus. Make that possible by making can_queue configurable. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_scsi.c | 83 +++++++++++---------------------------- 1 file changed, 22 insertions(+), 61 deletions(-) diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 65af08139787..a59ad94ea52b 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -14,55 +14,23 @@ * */ - -/**************************************************************************/ -/* */ -/* Notes for Falcon SCSI: */ -/* ---------------------- */ -/* */ -/* Since the Falcon SCSI uses the ST-DMA chip, that is shared among */ -/* several device drivers, locking and unlocking the access to this */ -/* chip is required. But locking is not possible from an interrupt, */ -/* since it puts the process to sleep if the lock is not available. */ -/* This prevents "late" locking of the DMA chip, i.e. locking it just */ -/* before using it, since in case of disconnection-reconnection */ -/* commands, the DMA is started from the reselection interrupt. */ -/* */ -/* Two possible schemes for ST-DMA-locking would be: */ -/* 1) The lock is taken for each command separately and disconnecting */ -/* is forbidden (i.e. can_queue = 1). */ -/* 2) The DMA chip is locked when the first command comes in and */ -/* released when the last command is finished and all queues are */ -/* empty. */ -/* The first alternative would result in bad performance, since the */ -/* interleaving of commands would not be used. The second is unfair to */ -/* other drivers using the ST-DMA, because the queues will seldom be */ -/* totally empty if there is a lot of disk traffic. */ -/* */ -/* For this reasons I decided to employ a more elaborate scheme: */ -/* - First, we give up the lock every time we can (for fairness), this */ -/* means every time a command finishes and there are no other commands */ -/* on the disconnected queue. */ -/* - If there are others waiting to lock the DMA chip, we stop */ -/* issuing commands, i.e. moving them onto the issue queue. */ -/* Because of that, the disconnected queue will run empty in a */ -/* while. Instead we go to sleep on a 'fairness_queue'. */ -/* - If the lock is released, all processes waiting on the fairness */ -/* queue will be woken. The first of them tries to re-lock the DMA, */ -/* the others wait for the first to finish this task. After that, */ -/* they can all run on and do their commands... */ -/* This sounds complicated (and it is it :-(), but it seems to be a */ -/* good compromise between fairness and performance: As long as no one */ -/* else wants to work with the ST-DMA chip, SCSI can go along as */ -/* usual. If now someone else comes, this behaviour is changed to a */ -/* "fairness mode": just already initiated commands are finished and */ -/* then the lock is released. The other one waiting will probably win */ -/* the race for locking the DMA, since it was waiting for longer. And */ -/* after it has finished, SCSI can go ahead again. Finally: I hope I */ -/* have not produced any deadlock possibilities! */ -/* */ -/**************************************************************************/ - +/* + * Notes for Falcon SCSI DMA + * + * The 5380 device is one of several that all share the DMA chip. Hence + * "locking" and "unlocking" access to this chip is required. + * + * Two possible schemes for ST DMA acquisition by atari_scsi are: + * 1) The lock is taken for each command separately (i.e. can_queue == 1). + * 2) The lock is taken when the first command arrives and released + * when the last command is finished (i.e. can_queue > 1). + * + * The first alternative limits SCSI bus utilization, since interleaving + * commands is not possible. The second gives better performance but is + * unfair to other drivers needing to use the ST DMA chip. In order to + * allow the IDE and floppy drivers equal access to the ST DMA chip + * the default is can_queue == 1. + */ #include #include @@ -443,6 +411,10 @@ static int falcon_get_lock(struct Scsi_Host *instance) if (IS_A_TT()) return 1; + if (stdma_is_locked_by(scsi_falcon_intr) && + instance->hostt->can_queue > 1) + return 1; + if (in_interrupt()) return stdma_try_lock(scsi_falcon_intr, instance); @@ -776,22 +748,11 @@ static int __init atari_scsi_probe(struct platform_device *pdev) atari_scsi_reg_write = atari_scsi_falcon_reg_write; } - /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. - * Higher values should work, too; try it! - * (But cmd_per_lun costs memory!) - * - * But there seems to be a bug somewhere that requires CAN_QUEUE to be - * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since - * changed CMD_PER_LUN... - * - * Note: The Falcon currently uses 8/1 setting due to unsolved problems - * with cmd_per_lun != 1 - */ if (ATARIHW_PRESENT(TT_SCSI)) { atari_scsi_template.can_queue = 16; atari_scsi_template.sg_tablesize = SG_ALL; } else { - atari_scsi_template.can_queue = 8; + atari_scsi_template.can_queue = 1; atari_scsi_template.sg_tablesize = SG_NONE; } From 3a0f64bfa90700c4fa9db0ed2d701300edd9a0b3 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:31 +1100 Subject: [PATCH 025/138] mac_scsi: Fix pseudo DMA implementation Fix various issues: Comments about bus errors are incorrect. The PDMA asm must return the size of the memory access that faulted so the transfer count can be adjusted accordingly. A phase change may cause a bus error but should not be treated as failure. A bus error does not always imply a phase change and generally the transfer may continue. Scatter/gather doesn't seem to work with PDMA due to overruns. This is a pity because peak throughput seems to double with SG_ALL. Tested on a Mac LC III and a PowerBook 520. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.h | 2 + drivers/scsi/mac_scsi.c | 194 ++++++++++++++++++++++------------------ 2 files changed, 110 insertions(+), 86 deletions(-) diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 076f8969dd22..c60728785d89 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -292,6 +292,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance); static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); +static int NCR5380_poll_politely(struct Scsi_Host *, int, int, int, int); +static int NCR5380_poll_politely2(struct Scsi_Host *, int, int, int, int, int, int, int); #endif /* __KERNEL__ */ #endif /* NCR5380_H */ diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 42feba7e350b..a590089b9397 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -28,7 +28,8 @@ /* Definitions for the core NCR5380 driver. */ -#define NCR5380_implementation_fields unsigned char *pdma_base +#define NCR5380_implementation_fields unsigned char *pdma_base; \ + int pdma_residual #define NCR5380_read(reg) macscsi_read(instance, reg) #define NCR5380_write(reg, value) macscsi_write(instance, reg, value) @@ -37,7 +38,7 @@ macscsi_dma_xfer_len(instance, cmd) #define NCR5380_dma_recv_setup macscsi_pread #define NCR5380_dma_send_setup macscsi_pwrite -#define NCR5380_dma_residual(instance) (0) +#define NCR5380_dma_residual(instance) (hostdata->pdma_residual) #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command @@ -104,18 +105,9 @@ static int __init mac_scsi_setup(char *str) __setup("mac5380=", mac_scsi_setup); #endif /* !MODULE */ -/* - Pseudo-DMA: (Ove Edlund) - The code attempts to catch bus errors that occur if one for example - "trips over the cable". - XXX: Since bus errors in the PDMA routines never happen on my - computer, the bus error code is untested. - If the code works as intended, a bus error results in Pseudo-DMA - being disabled, meaning that the driver switches to slow handshake. - If bus errors are NOT extremely rare, this has to be changed. -*/ +/* Pseudo DMA asm originally by Ove Edlund */ -#define CP_IO_TO_MEM(s,d,len) \ +#define CP_IO_TO_MEM(s,d,n) \ __asm__ __volatile__ \ (" cmp.w #4,%2\n" \ " bls 8f\n" \ @@ -152,61 +144,73 @@ __asm__ __volatile__ \ " 9: \n" \ ".section .fixup,\"ax\"\n" \ " .even\n" \ - "90: moveq.l #1, %2\n" \ + "91: moveq.l #1, %2\n" \ + " jra 9b\n" \ + "94: moveq.l #4, %2\n" \ " jra 9b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 4\n" \ - " .long 1b,90b\n" \ - " .long 3b,90b\n" \ - " .long 31b,90b\n" \ - " .long 32b,90b\n" \ - " .long 33b,90b\n" \ - " .long 34b,90b\n" \ - " .long 35b,90b\n" \ - " .long 36b,90b\n" \ - " .long 37b,90b\n" \ - " .long 5b,90b\n" \ - " .long 7b,90b\n" \ + " .long 1b,91b\n" \ + " .long 3b,94b\n" \ + " .long 31b,94b\n" \ + " .long 32b,94b\n" \ + " .long 33b,94b\n" \ + " .long 34b,94b\n" \ + " .long 35b,94b\n" \ + " .long 36b,94b\n" \ + " .long 37b,94b\n" \ + " .long 5b,94b\n" \ + " .long 7b,91b\n" \ ".previous" \ - : "=a"(s), "=a"(d), "=d"(len) \ - : "0"(s), "1"(d), "2"(len) \ + : "=a"(s), "=a"(d), "=d"(n) \ + : "0"(s), "1"(d), "2"(n) \ : "d0") static int macscsi_pread(struct Scsi_Host *instance, unsigned char *dst, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char *d; - unsigned char *s; + unsigned char *s = hostdata->pdma_base + (INPUT_DATA_REG << 4); + unsigned char *d = dst; + int n = len; + int transferred; - s = hostdata->pdma_base + (INPUT_DATA_REG << 4); - d = dst; + while (!NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, + BASR_DRQ | BASR_PHASE_MATCH, + BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { + CP_IO_TO_MEM(s, d, n); - /* These conditions are derived from MacOS */ + transferred = d - dst - n; + hostdata->pdma_residual = len - transferred; - while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && - !(NCR5380_read(STATUS_REG) & SR_REQ)) - ; + /* No bus error. */ + if (n == 0) + return 0; - if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && - (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) { - pr_err("Error in macscsi_pread\n"); - return -1; + /* Target changed phase early? */ + if (NCR5380_poll_politely2(instance, STATUS_REG, SR_REQ, SR_REQ, + BUS_AND_STATUS_REG, BASR_ACK, BASR_ACK, HZ / 64) < 0) + scmd_printk(KERN_ERR, hostdata->connected, + "%s: !REQ and !ACK\n", __func__); + if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) + return 0; + + dsprintk(NDEBUG_PSEUDO_DMA, instance, + "%s: bus error (%d/%d)\n", __func__, transferred, len); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + d = dst + transferred; + n = len - transferred; } - CP_IO_TO_MEM(s, d, len); - - if (len != 0) { - pr_notice("Bus error in macscsi_pread\n"); - return -1; - } - - return 0; + scmd_printk(KERN_ERR, hostdata->connected, + "%s: phase mismatch or !DRQ\n", __func__); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + return -1; } -#define CP_MEM_TO_IO(s,d,len) \ +#define CP_MEM_TO_IO(s,d,n) \ __asm__ __volatile__ \ (" cmp.w #4,%2\n" \ " bls 8f\n" \ @@ -243,57 +247,76 @@ __asm__ __volatile__ \ " 9: \n" \ ".section .fixup,\"ax\"\n" \ " .even\n" \ - "90: moveq.l #1, %2\n" \ + "91: moveq.l #1, %2\n" \ + " jra 9b\n" \ + "94: moveq.l #4, %2\n" \ " jra 9b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 4\n" \ - " .long 1b,90b\n" \ - " .long 3b,90b\n" \ - " .long 31b,90b\n" \ - " .long 32b,90b\n" \ - " .long 33b,90b\n" \ - " .long 34b,90b\n" \ - " .long 35b,90b\n" \ - " .long 36b,90b\n" \ - " .long 37b,90b\n" \ - " .long 5b,90b\n" \ - " .long 7b,90b\n" \ + " .long 1b,91b\n" \ + " .long 3b,94b\n" \ + " .long 31b,94b\n" \ + " .long 32b,94b\n" \ + " .long 33b,94b\n" \ + " .long 34b,94b\n" \ + " .long 35b,94b\n" \ + " .long 36b,94b\n" \ + " .long 37b,94b\n" \ + " .long 5b,94b\n" \ + " .long 7b,91b\n" \ ".previous" \ - : "=a"(s), "=a"(d), "=d"(len) \ - : "0"(s), "1"(d), "2"(len) \ + : "=a"(s), "=a"(d), "=d"(n) \ + : "0"(s), "1"(d), "2"(n) \ : "d0") static int macscsi_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char *s; - unsigned char *d; + unsigned char *s = src; + unsigned char *d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4); + int n = len; + int transferred; - s = src; - d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4); + while (!NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, + BASR_DRQ | BASR_PHASE_MATCH, + BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { + CP_MEM_TO_IO(s, d, n); - /* These conditions are derived from MacOS */ + transferred = s - src - n; + hostdata->pdma_residual = len - transferred; - while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && - (!(NCR5380_read(STATUS_REG) & SR_REQ) || - (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))) - ; + /* Target changed phase early? */ + if (NCR5380_poll_politely2(instance, STATUS_REG, SR_REQ, SR_REQ, + BUS_AND_STATUS_REG, BASR_ACK, BASR_ACK, HZ / 64) < 0) + scmd_printk(KERN_ERR, hostdata->connected, + "%s: !REQ and !ACK\n", __func__); + if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) + return 0; - if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) { - pr_err("Error in macscsi_pwrite\n"); - return -1; + /* No bus error. */ + if (n == 0) { + if (NCR5380_poll_politely(instance, TARGET_COMMAND_REG, + TCR_LAST_BYTE_SENT, + TCR_LAST_BYTE_SENT, HZ / 64) < 0) + scmd_printk(KERN_ERR, hostdata->connected, + "%s: Last Byte Sent timeout\n", __func__); + return 0; + } + + dsprintk(NDEBUG_PSEUDO_DMA, instance, + "%s: bus error (%d/%d)\n", __func__, transferred, len); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + s = src + transferred; + n = len - transferred; } - CP_MEM_TO_IO(s, d, len); + scmd_printk(KERN_ERR, hostdata->connected, + "%s: phase mismatch or !DRQ\n", __func__); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); - if (len != 0) { - pr_notice("Bus error in macscsi_pwrite\n"); - return -1; - } - - return 0; + return -1; } static int macscsi_dma_xfer_len(struct Scsi_Host *instance, @@ -301,10 +324,11 @@ static int macscsi_dma_xfer_len(struct Scsi_Host *instance, { struct NCR5380_hostdata *hostdata = shost_priv(instance); - if (hostdata->flags & FLAG_NO_PSEUDO_DMA) + if (hostdata->flags & FLAG_NO_PSEUDO_DMA || + cmd->SCp.this_residual < 16) return 0; - return cmd->transfersize; + return cmd->SCp.this_residual; } #include "NCR5380.c" @@ -322,7 +346,7 @@ static struct scsi_host_template mac_scsi_template = { .eh_bus_reset_handler = macscsi_bus_reset, .can_queue = 16, .this_id = 7, - .sg_tablesize = SG_ALL, + .sg_tablesize = 1, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, @@ -358,8 +382,6 @@ static int __init mac_scsi_probe(struct platform_device *pdev) mac_scsi_template.sg_tablesize = setup_sg_tablesize; if (setup_hostid >= 0) mac_scsi_template.this_id = setup_hostid & 7; - if (setup_use_pdma < 0) - setup_use_pdma = 0; instance = scsi_host_alloc(&mac_scsi_template, sizeof(struct NCR5380_hostdata)); From 216fad91387aab7c9e69fe0854d843f012968748 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:32 +1100 Subject: [PATCH 026/138] ncr5380: Call complete_cmd() for disconnected commands on bus reset I'm told that some targets are liable to disconnect a REQUEST SENSE command. Theoretically this would cause a command undergoing autosense to be moved onto the disconnected list. The bus reset handler must call complete_cmd() for these commands, otherwise the hostdata->sensing pointer will not get cleared. That would cause autosense processing to stall and a timeout or an incorrect scsi_eh_restore_cmnd() would eventually follow. Signed-off-by: Finn Thain Reported-by: Michael Schmitz Tested-by: Ondrej Zary Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 52e7d2b57902..43908bbb3b23 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -2437,7 +2437,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); set_host_byte(cmd, DID_RESET); - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); } INIT_LIST_HEAD(&hostdata->disconnected); From 1d64508810d8d15867251c75a68d7250278ce2bd Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 17 Mar 2016 08:39:45 +0100 Subject: [PATCH 027/138] scsi: disable automatic target scan On larger installations it is useful to disable automatic LUN scanning, and only add the required LUNs via udev rules. This can speed up bootup dramatically. This patch introduces a new scan module parameter value 'manual', which works like 'none', but can be overridden by setting the 'rescan' value from scsi_scan_target to 'SCSI_SCAN_MANUAL'. And it updates all relevant callers to set the 'rescan' value to 'SCSI_SCAN_MANUAL' if invoked via the 'scan' option in sysfs. Signed-off-by: Hannes Reinecke Reviewed-by: Ewan D. Milne Tested-by: Laurence Oberman Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/srp/ib_srp.c | 2 +- drivers/message/fusion/mptspi.c | 2 +- drivers/s390/scsi/zfcp_unit.c | 3 +- drivers/scsi/scsi_priv.h | 2 +- drivers/scsi/scsi_proc.c | 3 +- drivers/scsi/scsi_scan.c | 44 ++++++++++++++++++++--------- drivers/scsi/scsi_sysfs.c | 3 +- drivers/scsi/scsi_transport_fc.c | 6 ++-- drivers/scsi/scsi_transport_iscsi.c | 5 +++- drivers/scsi/scsi_transport_sas.c | 7 +++-- drivers/scsi/snic/snic_disc.c | 2 +- include/scsi/scsi_device.h | 9 +++++- 12 files changed, 60 insertions(+), 28 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index b6bf20496021..ff21597aa54d 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -2819,7 +2819,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) spin_unlock(&host->target_lock); scsi_scan_target(&target->scsi_host->shost_gendev, - 0, target->scsi_id, SCAN_WILD_CARD, 0); + 0, target->scsi_id, SCAN_WILD_CARD, SCSI_SCAN_INITIAL); if (srp_connected_ch(target) < target->ch_count || target->qp_in_error) { diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 613231c16194..031e088edb5e 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -1150,7 +1150,7 @@ static void mpt_work_wrapper(struct work_struct *work) } shost_printk(KERN_INFO, shost, MYIOC_s_FMT "Integrated RAID detects new device %d\n", ioc->name, disk); - scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, 1); + scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, SCSI_SCAN_RESCAN); } diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 157d3d203ba1..08bba7ce7cef 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -26,7 +26,8 @@ void zfcp_unit_scsi_scan(struct zfcp_unit *unit) lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); if (rport && rport->port_state == FC_PORTSTATE_ONLINE) - scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 1); + scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, + SCSI_SCAN_RESCAN); } static void zfcp_unit_scsi_scan_work(struct work_struct *work) diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 27b4d0a6a01d..57a4b9973320 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -116,7 +116,7 @@ extern void scsi_exit_procfs(void); extern char scsi_scan_type[]; extern int scsi_complete_async_scans(void); extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, - unsigned int, u64, int); + unsigned int, u64, enum scsi_scan_mode); extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_rescan_device(struct device *); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 251598eb3547..7a74b82e8973 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -251,7 +251,8 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) if (shost->transportt->user_scan) error = shost->transportt->user_scan(shost, channel, id, lun); else - error = scsi_scan_host_selected(shost, channel, id, lun, 1); + error = scsi_scan_host_selected(shost, channel, id, lun, + SCSI_SCAN_MANUAL); scsi_host_put(shost); return error; } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 97074c91e328..6c8ad36560d1 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -96,10 +96,13 @@ MODULE_PARM_DESC(max_luns, #define SCSI_SCAN_TYPE_DEFAULT "sync" #endif -char scsi_scan_type[6] = SCSI_SCAN_TYPE_DEFAULT; +char scsi_scan_type[7] = SCSI_SCAN_TYPE_DEFAULT; -module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); -MODULE_PARM_DESC(scan, "sync, async or none"); +module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), + S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(scan, "sync, async, manual, or none. " + "Setting to 'manual' disables automatic scanning, but allows " + "for manual device scan via the 'scan' sysfs attribute."); static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ + 18; @@ -1040,7 +1043,8 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, * @lun: LUN of target device * @bflagsp: store bflags here if not NULL * @sdevp: probe the LUN corresponding to this scsi_device - * @rescan: if nonzero skip some code only needed on first scan + * @rescan: if not equal to SCSI_SCAN_INITIAL skip some code only + * needed on first scan * @hostdata: passed to scsi_alloc_sdev() * * Description: @@ -1055,7 +1059,8 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, **/ static int scsi_probe_and_add_lun(struct scsi_target *starget, u64 lun, int *bflagsp, - struct scsi_device **sdevp, int rescan, + struct scsi_device **sdevp, + enum scsi_scan_mode rescan, void *hostdata) { struct scsi_device *sdev; @@ -1069,7 +1074,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, */ sdev = scsi_device_lookup_by_target(starget, lun); if (sdev) { - if (rescan || !scsi_device_created(sdev)) { + if (rescan != SCSI_SCAN_INITIAL || !scsi_device_created(sdev)) { SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, "scsi scan: device exists on %s\n", dev_name(&sdev->sdev_gendev))); @@ -1205,7 +1210,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * Modifies sdevscan->lun. **/ static void scsi_sequential_lun_scan(struct scsi_target *starget, - int bflags, int scsi_level, int rescan) + int bflags, int scsi_level, + enum scsi_scan_mode rescan) { uint max_dev_lun; u64 sparse_lun, lun; @@ -1300,7 +1306,7 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, * 1: could not scan with REPORT LUN **/ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, - int rescan) + enum scsi_scan_mode rescan) { char devname[64]; unsigned char scsi_cmd[MAX_COMMAND_SIZE]; @@ -1546,7 +1552,7 @@ void scsi_rescan_device(struct device *dev) EXPORT_SYMBOL(scsi_rescan_device); static void __scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, enum scsi_scan_mode rescan) { struct Scsi_Host *shost = dev_to_shost(parent); int bflags = 0; @@ -1604,7 +1610,10 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * @channel: channel to scan * @id: target id to scan * @lun: Specific LUN to scan or SCAN_WILD_CARD - * @rescan: passed to LUN scanning routines + * @rescan: passed to LUN scanning routines; SCSI_SCAN_INITIAL for + * no rescan, SCSI_SCAN_RESCAN to rescan existing LUNs, + * and SCSI_SCAN_MANUAL to force scanning even if + * 'scan=manual' is set. * * Description: * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, @@ -1614,13 +1623,17 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * sequential scan of LUNs on the target id. **/ void scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, enum scsi_scan_mode rescan) { struct Scsi_Host *shost = dev_to_shost(parent); if (strncmp(scsi_scan_type, "none", 4) == 0) return; + if (rescan != SCSI_SCAN_MANUAL && + strncmp(scsi_scan_type, "manual", 6) == 0) + return; + mutex_lock(&shost->scan_mutex); if (!shost->async_scan) scsi_complete_async_scans(); @@ -1634,7 +1647,8 @@ void scsi_scan_target(struct device *parent, unsigned int channel, EXPORT_SYMBOL(scsi_scan_target); static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, + enum scsi_scan_mode rescan) { uint order_id; @@ -1665,7 +1679,8 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, } int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, + enum scsi_scan_mode rescan) { SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost, "%s: <%u:%u:%llu>\n", @@ -1844,7 +1859,8 @@ void scsi_scan_host(struct Scsi_Host *shost) { struct async_scan_data *data; - if (strncmp(scsi_scan_type, "none", 4) == 0) + if (strncmp(scsi_scan_type, "none", 4) == 0 || + strncmp(scsi_scan_type, "manual", 6) == 0) return; if (scsi_autopm_get_host(shost) < 0) return; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 2b642b145be1..b36544162f2f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -145,7 +145,8 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str) if (shost->transportt->user_scan) res = shost->transportt->user_scan(shost, channel, id, lun); else - res = scsi_scan_host_selected(shost, channel, id, lun, 1); + res = scsi_scan_host_selected(shost, channel, id, lun, + SCSI_SCAN_MANUAL); return res; } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 8a8822641b26..bf28c688c72a 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2110,7 +2110,8 @@ fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, u64 lun) if ((channel == rport->channel) && (id == rport->scsi_target_id)) { spin_unlock_irqrestore(shost->host_lock, flags); - scsi_scan_target(&rport->dev, channel, id, lun, 1); + scsi_scan_target(&rport->dev, channel, id, lun, + SCSI_SCAN_MANUAL); return; } } @@ -3277,7 +3278,8 @@ fc_scsi_scan_rport(struct work_struct *work) (rport->roles & FC_PORT_ROLE_FCP_TARGET) && !(i->f->disable_target_scan)) { scsi_scan_target(&rport->dev, rport->channel, - rport->scsi_target_id, SCAN_WILD_CARD, 1); + rport->scsi_target_id, SCAN_WILD_CARD, + SCSI_SCAN_RESCAN); } spin_lock_irqsave(shost->host_lock, flags); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 441481623fb9..7a759a9257ea 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1783,6 +1783,7 @@ struct iscsi_scan_data { unsigned int channel; unsigned int id; u64 lun; + enum scsi_scan_mode rescan; }; static int iscsi_user_scan_session(struct device *dev, void *data) @@ -1819,7 +1820,7 @@ static int iscsi_user_scan_session(struct device *dev, void *data) (scan_data->id == SCAN_WILD_CARD || scan_data->id == id)) scsi_scan_target(&session->dev, 0, id, - scan_data->lun, 1); + scan_data->lun, scan_data->rescan); } user_scan_exit: @@ -1836,6 +1837,7 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, scan_data.channel = channel; scan_data.id = id; scan_data.lun = lun; + scan_data.rescan = SCSI_SCAN_MANUAL; return device_for_each_child(&shost->shost_gendev, &scan_data, iscsi_user_scan_session); @@ -1852,6 +1854,7 @@ static void iscsi_scan_session(struct work_struct *work) scan_data.channel = 0; scan_data.id = SCAN_WILD_CARD; scan_data.lun = SCAN_WILD_CARD; + scan_data.rescan = SCSI_SCAN_RESCAN; iscsi_user_scan_session(&session->dev, &scan_data); atomic_dec(&ihost->nr_scans); diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index b6f958193dad..3f0ff072184b 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1614,7 +1614,8 @@ int sas_rphy_add(struct sas_rphy *rphy) else lun = 0; - scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, 0); + scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, + SCSI_SCAN_INITIAL); } return 0; @@ -1739,8 +1740,8 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, if ((channel == SCAN_WILD_CARD || channel == 0) && (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { - scsi_scan_target(&rphy->dev, 0, - rphy->scsi_target_id, lun, 1); + scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, + lun, SCSI_SCAN_MANUAL); } } mutex_unlock(&sas_host->lock); diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c index 5f6321759ad9..5f48795767bd 100644 --- a/drivers/scsi/snic/snic_disc.c +++ b/drivers/scsi/snic/snic_disc.c @@ -171,7 +171,7 @@ snic_scsi_scan_tgt(struct work_struct *work) tgt->channel, tgt->scsi_tgt_id, SCAN_WILD_CARD, - 1); + SCSI_SCAN_RESCAN); spin_lock_irqsave(shost->host_lock, flags); tgt->flags &= ~SNIC_TGT_SCAN_PENDING; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 74d79bde7075..1d4a3297559e 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -50,6 +50,12 @@ enum scsi_device_state { SDEV_CREATED_BLOCK, /* same as above but for created devices */ }; +enum scsi_scan_mode { + SCSI_SCAN_INITIAL = 0, + SCSI_SCAN_RESCAN, + SCSI_SCAN_MANUAL, +}; + enum scsi_device_event { SDEV_EVT_MEDIA_CHANGE = 1, /* media has changed */ SDEV_EVT_INQUIRY_CHANGE_REPORTED, /* 3F 03 UA reported */ @@ -391,7 +397,8 @@ extern void scsi_device_resume(struct scsi_device *sdev); extern void scsi_target_quiesce(struct scsi_target *); extern void scsi_target_resume(struct scsi_target *); extern void scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, int rescan); + unsigned int id, u64 lun, + enum scsi_scan_mode rescan); extern void scsi_target_reap(struct scsi_target *); extern void scsi_target_block(struct device *); extern void scsi_target_unblock(struct device *, enum scsi_device_state); From b3bc891eab51c98ec83458e2d7f0db629169ad80 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 24 Mar 2016 15:21:18 +0100 Subject: [PATCH 028/138] scsi-trace: remove service action definitions scsi_opcode_name() is displaying the opcode, not the service action. Reviewed-by: Ewan D. Milne Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- include/trace/events/scsi.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/trace/events/scsi.h b/include/trace/events/scsi.h index 079bd10a01b4..5c0d91f16c74 100644 --- a/include/trace/events/scsi.h +++ b/include/trace/events/scsi.h @@ -95,10 +95,6 @@ scsi_opcode_name(VERIFY_16), \ scsi_opcode_name(WRITE_SAME_16), \ scsi_opcode_name(SERVICE_ACTION_IN_16), \ - scsi_opcode_name(SAI_READ_CAPACITY_16), \ - scsi_opcode_name(SAI_GET_LBA_STATUS), \ - scsi_opcode_name(MI_REPORT_TARGET_PGS), \ - scsi_opcode_name(MO_SET_TARGET_PGS), \ scsi_opcode_name(READ_32), \ scsi_opcode_name(WRITE_32), \ scsi_opcode_name(WRITE_SAME_32), \ From 5141f16a8a944f14e4b0348e8cd9e4dd1acb1a86 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 24 Mar 2016 15:21:19 +0100 Subject: [PATCH 029/138] scsi-trace: Decode MAINTENANCE_IN and MAINTENANCE_OUT commands Reviewed-by: Ewan D. Milne Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_trace.c | 91 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c index 08bb47b53bc3..76d4e6fd9dc1 100644 --- a/drivers/scsi/scsi_trace.c +++ b/drivers/scsi/scsi_trace.c @@ -17,6 +17,7 @@ */ #include #include +#include #include #define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f) @@ -230,6 +231,92 @@ scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len) return ret; } +static const char * +scsi_trace_maintenance_in(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = trace_seq_buffer_ptr(p), *cmd; + u32 alloc_len; + + switch (SERVICE_ACTION16(cdb)) { + case MI_REPORT_IDENTIFYING_INFORMATION: + cmd = "REPORT_IDENTIFYING_INFORMATION"; + break; + case MI_REPORT_TARGET_PGS: + cmd = "REPORT_TARGET_PORT_GROUPS"; + break; + case MI_REPORT_ALIASES: + cmd = "REPORT_ALIASES"; + break; + case MI_REPORT_SUPPORTED_OPERATION_CODES: + cmd = "REPORT_SUPPORTED_OPERATION_CODES"; + break; + case MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS: + cmd = "REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS"; + break; + case MI_REPORT_PRIORITY: + cmd = "REPORT_PRIORITY"; + break; + case MI_REPORT_TIMESTAMP: + cmd = "REPORT_TIMESTAMP"; + break; + case MI_MANAGEMENT_PROTOCOL_IN: + cmd = "MANAGEMENT_PROTOCOL_IN"; + break; + default: + trace_seq_puts(p, "UNKNOWN"); + goto out; + } + + alloc_len = get_unaligned_be32(&cdb[6]); + + trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len); + +out: + trace_seq_putc(p, 0); + + return ret; +} + +static const char * +scsi_trace_maintenance_out(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = trace_seq_buffer_ptr(p), *cmd; + u32 alloc_len; + + switch (SERVICE_ACTION16(cdb)) { + case MO_SET_IDENTIFYING_INFORMATION: + cmd = "SET_IDENTIFYING_INFORMATION"; + break; + case MO_SET_TARGET_PGS: + cmd = "SET_TARGET_PORT_GROUPS"; + break; + case MO_CHANGE_ALIASES: + cmd = "CHANGE_ALIASES"; + break; + case MO_SET_PRIORITY: + cmd = "SET_PRIORITY"; + break; + case MO_SET_TIMESTAMP: + cmd = "SET_TIMESTAMP"; + break; + case MO_MANAGEMENT_PROTOCOL_OUT: + cmd = "MANAGEMENT_PROTOCOL_OUT"; + break; + default: + trace_seq_puts(p, "UNKNOWN"); + goto out; + } + + alloc_len = get_unaligned_be32(&cdb[6]); + + trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len); + +out: + trace_seq_putc(p, 0); + + return ret; +} + static const char * scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len) { @@ -282,6 +369,10 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) return scsi_trace_service_action_in(p, cdb, len); case VARIABLE_LENGTH_CMD: return scsi_trace_varlen(p, cdb, len); + case MAINTENANCE_IN: + return scsi_trace_maintenance_in(p, cdb, len); + case MAINTENANCE_OUT: + return scsi_trace_maintenance_out(p, cdb, len); default: return scsi_trace_misc(p, cdb, len); } From 0008f1e7230b16989f72042e44bc078e44a69536 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 24 Mar 2016 17:23:56 +0100 Subject: [PATCH 030/138] scsi-trace: define ZBC_IN and ZBC_OUT Add new trace functions for ZBC_IN and ZBC_OUT. Reviewed-by: Doug Gilbert Reviewed-by: Ewan D. Milne Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_trace.c | 70 +++++++++++++++++++++++++++++++++++++ include/scsi/scsi_proto.h | 9 +++++ include/trace/events/scsi.h | 2 ++ 3 files changed, 81 insertions(+) diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c index 76d4e6fd9dc1..0ff083bbf5b1 100644 --- a/drivers/scsi/scsi_trace.c +++ b/drivers/scsi/scsi_trace.c @@ -317,6 +317,72 @@ scsi_trace_maintenance_out(struct trace_seq *p, unsigned char *cdb, int len) return ret; } +static const char * +scsi_trace_zbc_in(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = trace_seq_buffer_ptr(p), *cmd; + u64 zone_id; + u32 alloc_len; + u8 options; + + switch (SERVICE_ACTION16(cdb)) { + case ZI_REPORT_ZONES: + cmd = "REPORT_ZONES"; + break; + default: + trace_seq_puts(p, "UNKNOWN"); + goto out; + } + + zone_id = get_unaligned_be64(&cdb[2]); + alloc_len = get_unaligned_be32(&cdb[10]); + options = cdb[14] & 0x3f; + + trace_seq_printf(p, "%s zone=%llu alloc_len=%u options=%u partial=%u", + cmd, (unsigned long long)zone_id, alloc_len, + options, (cdb[14] >> 7) & 1); + +out: + trace_seq_putc(p, 0); + + return ret; +} + +static const char * +scsi_trace_zbc_out(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = trace_seq_buffer_ptr(p), *cmd; + u64 zone_id; + + switch (SERVICE_ACTION16(cdb)) { + case ZO_CLOSE_ZONE: + cmd = "CLOSE_ZONE"; + break; + case ZO_FINISH_ZONE: + cmd = "FINISH_ZONE"; + break; + case ZO_OPEN_ZONE: + cmd = "OPEN_ZONE"; + break; + case ZO_RESET_WRITE_POINTER: + cmd = "RESET_WRITE_POINTER"; + break; + default: + trace_seq_puts(p, "UNKNOWN"); + goto out; + } + + zone_id = get_unaligned_be64(&cdb[2]); + + trace_seq_printf(p, "%s zone=%llu all=%u", cmd, + (unsigned long long)zone_id, cdb[14] & 1); + +out: + trace_seq_putc(p, 0); + + return ret; +} + static const char * scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len) { @@ -373,6 +439,10 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) return scsi_trace_maintenance_in(p, cdb, len); case MAINTENANCE_OUT: return scsi_trace_maintenance_out(p, cdb, len); + case ZBC_IN: + return scsi_trace_zbc_in(p, cdb, len); + case ZBC_OUT: + return scsi_trace_zbc_out(p, cdb, len); default: return scsi_trace_misc(p, cdb, len); } diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h index c2ae21cbaa2c..d1defd1ebd95 100644 --- a/include/scsi/scsi_proto.h +++ b/include/scsi/scsi_proto.h @@ -115,6 +115,8 @@ #define VERIFY_16 0x8f #define SYNCHRONIZE_CACHE_16 0x91 #define WRITE_SAME_16 0x93 +#define ZBC_OUT 0x94 +#define ZBC_IN 0x95 #define SERVICE_ACTION_BIDIRECTIONAL 0x9d #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f @@ -143,6 +145,13 @@ #define MO_SET_PRIORITY 0x0e #define MO_SET_TIMESTAMP 0x0f #define MO_MANAGEMENT_PROTOCOL_OUT 0x10 +/* values for ZBC_IN */ +#define ZI_REPORT_ZONES 0x00 +/* values for ZBC_OUT */ +#define ZO_CLOSE_ZONE 0x01 +#define ZO_FINISH_ZONE 0x02 +#define ZO_OPEN_ZONE 0x03 +#define ZO_RESET_WRITE_POINTER 0x04 /* values for variable length command */ #define XDREAD_32 0x03 #define XDWRITE_32 0x04 diff --git a/include/trace/events/scsi.h b/include/trace/events/scsi.h index 5c0d91f16c74..9a9b3e2550af 100644 --- a/include/trace/events/scsi.h +++ b/include/trace/events/scsi.h @@ -94,6 +94,8 @@ scsi_opcode_name(WRITE_16), \ scsi_opcode_name(VERIFY_16), \ scsi_opcode_name(WRITE_SAME_16), \ + scsi_opcode_name(ZBC_OUT), \ + scsi_opcode_name(ZBC_IN), \ scsi_opcode_name(SERVICE_ACTION_IN_16), \ scsi_opcode_name(READ_32), \ scsi_opcode_name(WRITE_32), \ From 691a837c20df0f4eacd49596a4d57fc566a40545 Mon Sep 17 00:00:00 2001 From: Satish Kharat Date: Fri, 18 Mar 2016 11:22:48 -0700 Subject: [PATCH 031/138] fnic: Fix to cleanup aborted IO to avoid device being offlined by mid-layer If an I/O times out and an abort issued by host, if the abort is successful we need to set scsi status as DID_ABORT. Or else the mid-layer error handler which looks for this error code, will offline the device. Also if the original I/O is not found in fnic firmware, we will consider the abort as successful. The start_time assignment is moved because of the new goto. Fnic driver version changed from 1.6.0.17a to 1.6.0.19, version 1.6.0.18 has been skipped [mkp: Fixed checkpatch warning] Signed-off-by: Satish Kharat Signed-off-by: Sesidhar Baddela Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_scsi.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index ce129e595b55..52a53f8a907a 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.17a" +#define DRV_VERSION "1.6.0.19" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index f3032ca5051b..01b480d33d75 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -1091,6 +1091,11 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, atomic64_inc( &term_stats->terminate_fw_timeouts); break; + case FCPIO_ITMF_REJECTED: + FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, + "abort reject recd. id %d\n", + (int)(id & FNIC_TAG_MASK)); + break; case FCPIO_IO_NOT_FOUND: if (CMD_FLAGS(sc) & FNIC_IO_ABTS_ISSUED) atomic64_inc(&abts_stats->abort_io_not_found); @@ -1111,9 +1116,15 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, spin_unlock_irqrestore(io_lock, flags); return; } - CMD_ABTS_STATUS(sc) = hdr_status; + CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_DONE; + /* If the status is IO not found consider it as success */ + if (hdr_status == FCPIO_IO_NOT_FOUND) + CMD_ABTS_STATUS(sc) = FCPIO_SUCCESS; + else + CMD_ABTS_STATUS(sc) = hdr_status; + atomic64_dec(&fnic_stats->io_stats.active_ios); if (atomic64_read(&fnic->io_cmpl_skip)) atomic64_dec(&fnic->io_cmpl_skip); @@ -1926,21 +1937,31 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE; + start_time = io_req->start_time; /* * firmware completed the abort, check the status, - * free the io_req irrespective of failure or success + * free the io_req if successful. If abort fails, + * Device reset will clean the I/O. */ - if (CMD_ABTS_STATUS(sc) != FCPIO_SUCCESS) + if (CMD_ABTS_STATUS(sc) == FCPIO_SUCCESS) + CMD_SP(sc) = NULL; + else { ret = FAILED; - - CMD_SP(sc) = NULL; + spin_unlock_irqrestore(io_lock, flags); + goto fnic_abort_cmd_end; + } spin_unlock_irqrestore(io_lock, flags); - start_time = io_req->start_time; fnic_release_ioreq_buf(fnic, io_req, sc); mempool_free(io_req, fnic->io_req_pool); + if (sc->scsi_done) { + /* Call SCSI completion function to complete the IO */ + sc->result = (DID_ABORT << 16); + sc->scsi_done(sc); + } + fnic_abort_cmd_end: FNIC_TRACE(fnic_abort_cmd, sc->device->host->host_no, sc->request->tag, sc, From a36f5dd07dd9098d43d1137ec7a2d6b92aa6d591 Mon Sep 17 00:00:00 2001 From: Satish Kharat Date: Fri, 18 Mar 2016 11:22:49 -0700 Subject: [PATCH 032/138] fnic: Cleanup the I/O pending with fw and has timed out and is used to issue LUN reset In case of LUN reset, the device reset command is issued with one of the I/Os that has timed out on that LUN. The change is to also return this I/O with error status set to DID_RESET. In case when the reset is issued using the sg_reset tool (from sg3_utils) it is a new command and new_sc is set to 1. Fnic driver version changed from 1.6.0.19 to 1.6.0.20 [mkp: Fixed checkpatch warning] Signed-off-by: Satish Kharat Signed-off-by: Sesidhar Baddela Reviewed-by: Ewan Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_scsi.c | 38 ++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 52a53f8a907a..1023eaea17f3 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.19" +#define DRV_VERSION "1.6.0.20" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 01b480d33d75..588ffd9a33d6 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -2039,7 +2039,9 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, * successfully aborted, 1 otherwise */ static int fnic_clean_pending_aborts(struct fnic *fnic, - struct scsi_cmnd *lr_sc) + struct scsi_cmnd *lr_sc, + bool new_sc) + { int tag, abt_tag; struct fnic_io_req *io_req; @@ -2057,10 +2059,10 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, spin_lock_irqsave(io_lock, flags); sc = scsi_host_find_tag(fnic->lport->host, tag); /* - * ignore this lun reset cmd or cmds that do not belong to - * this lun + * ignore this lun reset cmd if issued using new SC + * or cmds that do not belong to this lun */ - if (!sc || sc == lr_sc || sc->device != lun_dev) { + if (!sc || ((sc == lr_sc) && new_sc) || sc->device != lun_dev) { spin_unlock_irqrestore(io_lock, flags); continue; } @@ -2166,11 +2168,27 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, goto clean_pending_aborts_end; } CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE; - CMD_SP(sc) = NULL; + + /* original sc used for lr is handled by dev reset code */ + if (sc != lr_sc) + CMD_SP(sc) = NULL; spin_unlock_irqrestore(io_lock, flags); - fnic_release_ioreq_buf(fnic, io_req, sc); - mempool_free(io_req, fnic->io_req_pool); + /* original sc used for lr is handled by dev reset code */ + if (sc != lr_sc) { + fnic_release_ioreq_buf(fnic, io_req, sc); + mempool_free(io_req, fnic->io_req_pool); + } + + /* + * Any IO is returned during reset, it needs to call scsi_done + * to return the scsi_cmnd to upper layer. + */ + if (sc->scsi_done) { + /* Set result to let upper SCSI layer retry */ + sc->result = DID_RESET << 16; + sc->scsi_done(sc); + } } schedule_timeout(msecs_to_jiffies(2 * fnic->config.ed_tov)); @@ -2264,6 +2282,7 @@ int fnic_device_reset(struct scsi_cmnd *sc) int tag = 0; DECLARE_COMPLETION_ONSTACK(tm_done); int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/ + bool new_sc = 0; /* Wait for rport to unblock */ fc_block_scsi_eh(sc); @@ -2309,13 +2328,12 @@ int fnic_device_reset(struct scsi_cmnd *sc) * fix the way the EH ioctls work for real, but until * that happens we fail these explicit requests here. */ - if (shost_use_blk_mq(sc->device->host)) - goto fnic_device_reset_end; tag = fnic_scsi_host_start_tag(fnic, sc); if (unlikely(tag == SCSI_NO_TAG)) goto fnic_device_reset_end; tag_gen_flag = 1; + new_sc = 1; } io_lock = fnic_io_lock_hash(fnic, sc); spin_lock_irqsave(io_lock, flags); @@ -2450,7 +2468,7 @@ int fnic_device_reset(struct scsi_cmnd *sc) * the lun reset cmd. If all cmds get cleaned, the lun reset * succeeds */ - if (fnic_clean_pending_aborts(fnic, sc)) { + if (fnic_clean_pending_aborts(fnic, sc, new_sc)) { spin_lock_irqsave(io_lock, flags); io_req = (struct fnic_io_req *)CMD_SP(sc); FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, From 1b6ac5e3ff354652ca59240e1ba8b2d22539df07 Mon Sep 17 00:00:00 2001 From: Satish Kharat Date: Fri, 18 Mar 2016 11:22:50 -0700 Subject: [PATCH 033/138] fnic: Using rport->dd_data to check rport online instead of rport_lookup. When issuing I/O we check if rport is online through libfc rport_lookup() function which needs to be protected by mutex lock that cannot acquired in I/O context. The change is to use midlayer remote port s dd_data which is preserved until its devloss timeout and no protection is required. The the scsi_cmnd error code is expected to be in the left 16 bits of the result field. Changed to correct this. Fnic driver version changed from 1.6.0.20 to 1.6.0.21 Signed-off-by: Satish Kharat Signed-off-by: Sesidhar Baddela Reviewed-by: Ewan Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_scsi.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 1023eaea17f3..9ddc9200e0a4 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.20" +#define DRV_VERSION "1.6.0.21" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 588ffd9a33d6..d9fd2f841585 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -439,7 +439,6 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ int sg_count = 0; unsigned long flags = 0; unsigned long ptr; - struct fc_rport_priv *rdata; spinlock_t *io_lock = NULL; int io_lock_acquired = 0; @@ -455,14 +454,17 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ return 0; } - rdata = lp->tt.rport_lookup(lp, rport->port_id); - if (!rdata || (rdata->rp_state == RPORT_ST_DELETE)) { - FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, - "returning IO as rport is removed\n"); - atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); - sc->result = DID_NO_CONNECT; - done(sc); - return 0; + if (rport) { + struct fc_rport_libfc_priv *rp = rport->dd_data; + + if (!rp || rp->rp_state != RPORT_ST_READY) { + FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, + "returning DID_NO_CONNECT for IO as rport is removed\n"); + atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); + sc->result = DID_NO_CONNECT<<16; + done(sc); + return 0; + } } if (lp->state != LPORT_ST_READY || !(lp->link_up)) From 62055172fbcd6055a10b010c6be65088fd7046b3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 28 Mar 2016 14:37:28 -0700 Subject: [PATCH 034/138] scsi_transport_fc: Unexport scsi_is_fc_vport() Running the command "git grep -nHw scsi_is_fc_vport" shows that this function is only called from inside scsi_transport_fc.c. Hence unexport this function. Signed-off-by: Bart Van Assche Cc: Hannes Reinecke Cc: James Smart Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_fc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index bf28c688c72a..0f3a3869524b 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2027,11 +2027,10 @@ static void fc_vport_dev_release(struct device *dev) kfree(vport); } -int scsi_is_fc_vport(const struct device *dev) +static int scsi_is_fc_vport(const struct device *dev) { return dev->release == fc_vport_dev_release; } -EXPORT_SYMBOL(scsi_is_fc_vport); static int fc_vport_match(struct attribute_container *cont, struct device *dev) From 5cfe8d5b4c6f359a23738bbdc54a6007c6d6bdb1 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 16:25:21 -0700 Subject: [PATCH 035/138] qla2xxx: Indicate out-of-memory with -ENOMEM In the Linux kernel it is preferred to return a meaningful error code instead of -1. This patch does not change the behavior of the caller of qla82xx_pinit_from_rom(). Signed-off-by: Bart Van Assche Cc: Quinn Tran Cc: Himanshu Madhani Cc: Christoph Hellwig Reviewed-by: Johannes Thumshirn Acked-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index b6b4cfdd7620..54380b434b30 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1229,7 +1229,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha) if (buf == NULL) { ql_log(ql_log_fatal, vha, 0x010c, "Unable to allocate memory.\n"); - return -1; + return -ENOMEM; } for (i = 0; i < n; i++) { From 3907adf67a1559d455f90b0de4c977dd456fe311 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:26:46 -0700 Subject: [PATCH 036/138] libiscsi: Unexport iscsi_eh_target_reset() Running "git grep -nHw iscsi_eh_target_reset" shows that this function is only called from inside the drivers/scsi/libiscsi.c source file. Hence unexport this function. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libiscsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 6bffd91b973a..120150a25dc3 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2423,7 +2423,7 @@ static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) * * This will attempt to send a warm target reset. */ -int iscsi_eh_target_reset(struct scsi_cmnd *sc) +static int iscsi_eh_target_reset(struct scsi_cmnd *sc) { struct iscsi_cls_session *cls_session; struct iscsi_session *session; @@ -2495,7 +2495,6 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc) mutex_unlock(&session->eh_mutex); return rc; } -EXPORT_SYMBOL_GPL(iscsi_eh_target_reset); /** * iscsi_eh_recover_target - reset target and possibly the session From e9e410e8e8537b383b0325f3d03c522aba36fa0b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:27:08 -0700 Subject: [PATCH 037/138] libiscsi: Remove set-but-not-used variables Avoid that building with W=1 causes gcc to report warnings about set-but-not-used variables. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libiscsi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 120150a25dc3..c051694bfcb0 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2127,7 +2127,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) struct iscsi_conn *conn; struct iscsi_task *task; struct iscsi_tm *hdr; - int rc, age; + int age; cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; @@ -2188,10 +2188,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) hdr = &conn->tmhdr; iscsi_prep_abort_task_pdu(task, hdr); - if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) { - rc = FAILED; + if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) goto failed; - } switch (conn->tmf_state) { case TMF_SUCCESS: From 6fe3ed88fe12aeb4ace4877ce1457993ecc196c3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:27:27 -0700 Subject: [PATCH 038/138] scsi_transport_iscsi: Remove set-but-not-used variables Avoid that building with W=1 causes gcc to report warnings about set-but-not-used variables. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 7a759a9257ea..5a7be7ee9f5d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2070,13 +2070,10 @@ EXPORT_SYMBOL_GPL(iscsi_alloc_session); int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) { - struct Scsi_Host *shost = iscsi_session_to_shost(session); - struct iscsi_cls_host *ihost; unsigned long flags; int id = 0; int err; - ihost = shost->shost_data; session->sid = atomic_add_return(1, &iscsi_session_nr); if (target_id == ISCSI_MAX_TARGET) { From 7a15fdfab012dddc00ee2c859cf50669e3dae3df Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:27:47 -0700 Subject: [PATCH 039/138] scsi_transport_iscsi: Unexport iscsi_is_flashnode_conn_dev() The output of "git grep -nHw iscsi_is_flashnode_conn_dev" shows that this function is only called from inside source file drivers/scsi/scsi_transport_iscsi.c. Hence unexport this function. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 5a7be7ee9f5d..ea5a9f37c9d2 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1324,11 +1324,10 @@ EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn); * 1 on success * 0 on failure */ -int iscsi_is_flashnode_conn_dev(struct device *dev, void *data) +static int iscsi_is_flashnode_conn_dev(struct device *dev, void *data) { return dev->bus == &iscsi_flashnode_bus; } -EXPORT_SYMBOL_GPL(iscsi_is_flashnode_conn_dev); static int iscsi_destroy_flashnode_conn(struct iscsi_bus_flash_conn *fnode_conn) { From 4c1340af8854836796bc50555de446286dce4625 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:28:11 -0700 Subject: [PATCH 040/138] scsi_transport_iscsi: Declare local symbols static Avoid that building with W=1 causes gcc to report warnings about symbols that have not been declared. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index ea5a9f37c9d2..42bca619f854 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1009,7 +1009,7 @@ static void iscsi_flashnode_sess_release(struct device *dev) kfree(fnode_sess); } -struct device_type iscsi_flashnode_sess_dev_type = { +static struct device_type iscsi_flashnode_sess_dev_type = { .name = "iscsi_flashnode_sess_dev_type", .groups = iscsi_flashnode_sess_attr_groups, .release = iscsi_flashnode_sess_release, @@ -1195,13 +1195,13 @@ static void iscsi_flashnode_conn_release(struct device *dev) kfree(fnode_conn); } -struct device_type iscsi_flashnode_conn_dev_type = { +static struct device_type iscsi_flashnode_conn_dev_type = { .name = "iscsi_flashnode_conn_dev_type", .groups = iscsi_flashnode_conn_attr_groups, .release = iscsi_flashnode_conn_release, }; -struct bus_type iscsi_flashnode_bus; +static struct bus_type iscsi_flashnode_bus; int iscsi_flashnode_bus_match(struct device *dev, struct device_driver *drv) @@ -1212,7 +1212,7 @@ int iscsi_flashnode_bus_match(struct device *dev, } EXPORT_SYMBOL_GPL(iscsi_flashnode_bus_match); -struct bus_type iscsi_flashnode_bus = { +static struct bus_type iscsi_flashnode_bus = { .name = "iscsi_flashnode", .match = &iscsi_flashnode_bus_match, }; From de96e9c5b82801ea17558c271730fdc2aa5e7e77 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:27 -0700 Subject: [PATCH 041/138] lpfc: Correct LOGO handling during login After a link bounce, when a remote port issues a LOGO while a REGLOGIN is pending on that port, the driver does not clean up the ndlp structure. May result in stack traces in the console log. Fix: Clear the NLP_REG_LOGIN_SEND flag on the ndlp in the routine Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 ++ drivers/scsi/lpfc/lpfc_sli.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 193733e8c823..9b539e2e864b 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1512,6 +1512,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, if ((mb = phba->sli.mbox_active)) { if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && (ndlp == (struct lpfc_nodelist *) mb->context2)) { + ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; lpfc_nlp_put(ndlp); mb->context2 = NULL; mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; @@ -1527,6 +1528,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, __lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); } + ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; lpfc_nlp_put(ndlp); list_del(&mb->list); phba->sli.mboxq_cnt--; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 2207726b88ee..035105a24298 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2211,6 +2211,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) rpi = pmb->u.mb.un.varWords[0]; vpi = pmb->u.mb.un.varRegLogin.vpi; lpfc_unreg_login(phba, vpi, rpi, pmb); + pmb->vport = vport; pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); if (rc != MBX_NOT_FINISHED) From ae09c765109293b600ba9169aa3d632e1ac1a843 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:28 -0700 Subject: [PATCH 042/138] lpfc: Fix DMA faults observed upon plugging loopback connector Driver didn't program the REG_VFI mailbox correctly, giving the adapter bad addresses. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_mbox.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index f87f90e9b7df..1e34b5408a29 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -2145,10 +2145,12 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys) reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]); reg_vfi->e_d_tov = phba->fc_edtov; reg_vfi->r_a_tov = phba->fc_ratov; - reg_vfi->bde.addrHigh = putPaddrHigh(phys); - reg_vfi->bde.addrLow = putPaddrLow(phys); - reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam); - reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; + if (phys) { + reg_vfi->bde.addrHigh = putPaddrHigh(phys); + reg_vfi->bde.addrLow = putPaddrLow(phys); + reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam); + reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; + } bf_set(lpfc_reg_vfi_nport_id, reg_vfi, vport->fc_myDID); /* Only FC supports upd bit */ From a6517db9006eb618dfde54f4bf6a9a8bc21e16e7 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:29 -0700 Subject: [PATCH 043/138] lpfc: Fix crash when unregistering default rpi. The default rpi completion handler does back to back puts to force the removal of the ndlp. This ends up calling lpfc_unreg_rpi after the reference count is at 0. Fix: Check the reference count of the ndlp before getting the ref to make sure we are not getting a reference on a removed object. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 25b5dcd1a5c8..b3bf230f714a 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -4545,7 +4545,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) (!(vport->load_flag & FC_UNLOADING)) && (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == - LPFC_SLI_INTF_IF_TYPE_2)) { + LPFC_SLI_INTF_IF_TYPE_2) && + (atomic_read(&ndlp->kref.refcount) > 0)) { mbox->context1 = lpfc_nlp_get(ndlp); mbox->mbox_cmpl = lpfc_sli4_unreg_rpi_cmpl_clr; From b5c539583988b70bddea73f333c640fc93a62e88 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:30 -0700 Subject: [PATCH 044/138] lpfc: Utilize embedded CDB logic to minimize IO latency Pass cmd iu payloads inline to adapter job structure rather than as separate dma buffers. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_attr.c | 1 - drivers/scsi/lpfc/lpfc_hw4.h | 6 ++ drivers/scsi/lpfc/lpfc_init.c | 20 +++++- drivers/scsi/lpfc/lpfc_sli.c | 128 +++++++++++++++++++++++++++++----- 5 files changed, 136 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 90a3ca5a4dbd..da237d9c4b55 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -694,6 +694,7 @@ struct lpfc_hba { uint8_t wwnn[8]; uint8_t wwpn[8]; uint32_t RandomData[7]; + uint32_t fcp_embed_io; /* HBA Config Parameters */ uint32_t cfg_ack0; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 343ae9482891..d4559a6175e2 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5150,7 +5150,6 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport) sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); } - /* * Dynamic FC Host Attributes Support */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 608f9415fb08..aea00f8be9ac 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -2865,6 +2865,9 @@ struct lpfc_sli4_parameters { uint32_t word17; uint32_t word18; uint32_t word19; +#define cfg_ext_embed_cb_SHIFT 0 +#define cfg_ext_embed_cb_MASK 0x00000001 +#define cfg_ext_embed_cb_WORD word19 }; struct lpfc_mbx_get_sli4_parameters { @@ -3919,6 +3922,9 @@ union lpfc_wqe { union lpfc_wqe128 { uint32_t words[32]; struct lpfc_wqe_generic generic; + struct fcp_icmnd64_wqe fcp_icmd; + struct fcp_iread64_wqe fcp_iread; + struct fcp_iwrite64_wqe fcp_iwrite; struct xmit_seq64_wqe xmit_sequence; struct gen_req64_wqe gen_req; }; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f57d02c3b6cf..f0d0852bee0d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -7264,8 +7264,15 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.fcp_cq[idx] = qdesc; /* Create Fast Path FCP WQs */ - qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.wq_esize, - phba->sli4_hba.wq_ecount); + if (phba->fcp_embed_io) { + qdesc = lpfc_sli4_queue_alloc(phba, + LPFC_WQE128_SIZE, + LPFC_WQE128_DEF_COUNT); + } else { + qdesc = lpfc_sli4_queue_alloc(phba, + phba->sli4_hba.wq_esize, + phba->sli4_hba.wq_ecount); + } if (!qdesc) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0503 Failed allocate fast-path FCP " @@ -9510,6 +9517,15 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if (sli4_params->sge_supp_len > LPFC_MAX_SGE_SIZE) sli4_params->sge_supp_len = LPFC_MAX_SGE_SIZE; + /* + * Issue IOs with CDB embedded in WQE to minimized the number + * of DMAs the firmware has to do. Setting this to 1 also forces + * the driver to use 128 bytes WQEs for FCP IOs. + */ + if (bf_get(cfg_ext_embed_cb, mbx_sli4_parameters)) + phba->fcp_embed_io = 1; + else + phba->fcp_embed_io = 0; return 0; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 035105a24298..9c8368a7149a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4689,6 +4689,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) break; } + phba->fcp_embed_io = 0; /* SLI4 FC support only */ rc = lpfc_sli_config_port(phba, mode); @@ -6321,10 +6322,12 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) mqe = &mboxq->u.mqe; phba->sli_rev = bf_get(lpfc_mbx_rd_rev_sli_lvl, &mqe->un.read_rev); - if (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev)) + if (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev)) { phba->hba_flag |= HBA_FCOE_MODE; - else + phba->fcp_embed_io = 0; /* SLI4 FC support only */ + } else { phba->hba_flag &= ~HBA_FCOE_MODE; + } if (bf_get(lpfc_mbx_rd_rev_cee_ver, &mqe->un.read_rev) == LPFC_DCBX_CEE_MODE) @@ -8219,12 +8222,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, else command_type = ELS_COMMAND_NON_FIP; + if (phba->fcp_embed_io) + memset(wqe, 0, sizeof(union lpfc_wqe128)); /* Some of the fields are in the right position already */ memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); - abort_tag = (uint32_t) iocbq->iotag; - xritag = iocbq->sli4_xritag; wqe->generic.wqe_com.word7 = 0; /* The ct field has moved so reset */ wqe->generic.wqe_com.word10 = 0; + + abort_tag = (uint32_t) iocbq->iotag; + xritag = iocbq->sli4_xritag; /* words0-2 bpl convert bde */ if (iocbq->iocb.un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) { numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize / @@ -8373,11 +8379,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->iocb.ulpFCP2Rcvy); bf_set(wqe_lnk, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpXS); /* Always open the exchange */ - bf_set(wqe_xc, &wqe->fcp_iwrite.wqe_com, 0); bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE); bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_LENLOC_WORD4); - bf_set(wqe_ebde_cnt, &wqe->fcp_iwrite.wqe_com, 0); bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU); bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1); if (iocbq->iocb_flag & LPFC_IO_OAS) { @@ -8388,6 +8392,35 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, (phba->cfg_XLanePriority << 1)); } } + /* Note, word 10 is already initialized to 0 */ + + if (phba->fcp_embed_io) { + struct lpfc_scsi_buf *lpfc_cmd; + struct sli4_sge *sgl; + union lpfc_wqe128 *wqe128; + struct fcp_cmnd *fcp_cmnd; + uint32_t *ptr; + + /* 128 byte wqe support here */ + wqe128 = (union lpfc_wqe128 *)wqe; + + lpfc_cmd = iocbq->context1; + sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; + fcp_cmnd = lpfc_cmd->fcp_cmnd; + + /* Word 0-2 - FCP_CMND */ + wqe128->generic.bde.tus.f.bdeFlags = + BUFF_TYPE_BDE_IMMED; + wqe128->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe128->generic.bde.addrHigh = 0; + wqe128->generic.bde.addrLow = 88; /* Word 22 */ + + bf_set(wqe_wqes, &wqe128->fcp_iwrite.wqe_com, 1); + + /* Word 22-29 FCP CMND Payload */ + ptr = &wqe128->words[22]; + memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); + } break; case CMD_FCP_IREAD64_CR: /* word3 iocb=iotag wqe=payload_offset_len */ @@ -8402,11 +8435,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->iocb.ulpFCP2Rcvy); bf_set(wqe_lnk, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpXS); /* Always open the exchange */ - bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0); bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, LPFC_WQE_LENLOC_WORD4); - bf_set(wqe_ebde_cnt, &wqe->fcp_iread.wqe_com, 0); bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU); bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1); if (iocbq->iocb_flag & LPFC_IO_OAS) { @@ -8417,6 +8448,35 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, (phba->cfg_XLanePriority << 1)); } } + /* Note, word 10 is already initialized to 0 */ + + if (phba->fcp_embed_io) { + struct lpfc_scsi_buf *lpfc_cmd; + struct sli4_sge *sgl; + union lpfc_wqe128 *wqe128; + struct fcp_cmnd *fcp_cmnd; + uint32_t *ptr; + + /* 128 byte wqe support here */ + wqe128 = (union lpfc_wqe128 *)wqe; + + lpfc_cmd = iocbq->context1; + sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; + fcp_cmnd = lpfc_cmd->fcp_cmnd; + + /* Word 0-2 - FCP_CMND */ + wqe128->generic.bde.tus.f.bdeFlags = + BUFF_TYPE_BDE_IMMED; + wqe128->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe128->generic.bde.addrHigh = 0; + wqe128->generic.bde.addrLow = 88; /* Word 22 */ + + bf_set(wqe_wqes, &wqe128->fcp_iread.wqe_com, 1); + + /* Word 22-29 FCP CMND Payload */ + ptr = &wqe128->words[22]; + memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); + } break; case CMD_FCP_ICMND64_CR: /* word3 iocb=iotag wqe=payload_offset_len */ @@ -8428,13 +8488,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, /* word3 iocb=IO_TAG wqe=reserved */ bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); /* Always open the exchange */ - bf_set(wqe_xc, &wqe->fcp_icmd.wqe_com, 0); bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 1); bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_WRITE); bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, LPFC_WQE_LENLOC_NONE); - bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0); bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com, iocbq->iocb.ulpFCP2Rcvy); if (iocbq->iocb_flag & LPFC_IO_OAS) { @@ -8445,6 +8503,35 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, (phba->cfg_XLanePriority << 1)); } } + /* Note, word 10 is already initialized to 0 */ + + if (phba->fcp_embed_io) { + struct lpfc_scsi_buf *lpfc_cmd; + struct sli4_sge *sgl; + union lpfc_wqe128 *wqe128; + struct fcp_cmnd *fcp_cmnd; + uint32_t *ptr; + + /* 128 byte wqe support here */ + wqe128 = (union lpfc_wqe128 *)wqe; + + lpfc_cmd = iocbq->context1; + sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; + fcp_cmnd = lpfc_cmd->fcp_cmnd; + + /* Word 0-2 - FCP_CMND */ + wqe128->generic.bde.tus.f.bdeFlags = + BUFF_TYPE_BDE_IMMED; + wqe128->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe128->generic.bde.addrHigh = 0; + wqe128->generic.bde.addrLow = 88; /* Word 22 */ + + bf_set(wqe_wqes, &wqe128->fcp_icmd.wqe_com, 1); + + /* Word 22-29 FCP CMND Payload */ + ptr = &wqe128->words[22]; + memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); + } break; case CMD_GEN_REQUEST64_CR: /* For this command calculate the xmit length of the @@ -8676,12 +8763,19 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { struct lpfc_sglq *sglq; - union lpfc_wqe wqe; + union lpfc_wqe *wqe; + union lpfc_wqe128 wqe128; struct lpfc_queue *wq; struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number]; lockdep_assert_held(&phba->hbalock); + /* + * The WQE can be either 64 or 128 bytes, + * so allocate space on the stack assuming the largest. + */ + wqe = (union lpfc_wqe *)&wqe128; + if (piocb->sli4_xritag == NO_XRI) { if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) @@ -8728,7 +8822,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, return IOCB_ERROR; } - if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe)) + if (lpfc_sli4_iocb2wqe(phba, piocb, wqe)) return IOCB_ERROR; if ((piocb->iocb_flag & LPFC_IO_FCP) || @@ -8738,12 +8832,12 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, } else { wq = phba->sli4_hba.oas_wq; } - if (lpfc_sli4_wq_put(wq, &wqe)) + if (lpfc_sli4_wq_put(wq, wqe)) return IOCB_ERROR; } else { if (unlikely(!phba->sli4_hba.els_wq)) return IOCB_ERROR; - if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) + if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, wqe)) return IOCB_ERROR; } lpfc_sli_ringtxcmpl_put(phba, pring, piocb); @@ -8758,9 +8852,9 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, * pointer from the lpfc_hba struct. * * Return codes: - * IOCB_ERROR - Error - * IOCB_SUCCESS - Success - * IOCB_BUSY - Busy + * IOCB_ERROR - Error + * IOCB_SUCCESS - Success + * IOCB_BUSY - Busy **/ int __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, From 342b59caa66240b670285d519fdfe2c44289b516 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:31 -0700 Subject: [PATCH 045/138] lpfc: Fix Device discovery failures during switch reboot test. When the switch is rebooted, the lpfc driver fails to log into the fabric, and Unexpected timeout message is seen. Fix: Do not issue RegVFI if the FLOGI was internally aborted. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 7f5abb8f52bc..27dcde95ac0f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1069,7 +1069,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_sli4_unreg_all_rpis(vport); } } - lpfc_issue_reg_vfi(vport); + + /* Do not register VFI if the driver aborted FLOGI */ + if (!lpfc_error_lost_link(irsp)) + lpfc_issue_reg_vfi(vport); lpfc_nlp_put(ndlp); goto out; } From 56204984761d80b973a0a534c42566ad78303766 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:32 -0700 Subject: [PATCH 046/138] lpfc: Add support for SmartSAN 2.0 Revise versions to reflect SmartSAN 2.0 support RDP updated to support additional descriptors: Credit descriptor Optical Element Data descriptors for Temperature, Voltage, Bias current, TX power and TX power. Optical Product Data descriptor. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 4 +- drivers/scsi/lpfc/lpfc_els.c | 153 +++++++++++++++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_hw.h | 73 +++++++++++++++-- drivers/scsi/lpfc/lpfc_hw4.h | 21 ++++- 4 files changed, 243 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 79e261d2a0c8..982039e73d33 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -2322,7 +2322,7 @@ lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport, ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; memset(ae, 0, 256); - strncpy(ae->un.AttrString, "Smart SAN Version 1.0", + strncpy(ae->un.AttrString, "Smart SAN Version 2.0", sizeof(ae->un.AttrString)); len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString)); @@ -2397,7 +2397,7 @@ lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport, uint32_t size; ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - ae->un.AttrInt = cpu_to_be32(0); + ae->un.AttrInt = cpu_to_be32(1); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); ad->AttrType = cpu_to_be16(RPRT_SMART_SECURITY); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 27dcde95ac0f..9459ac451600 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -4708,6 +4708,144 @@ lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc, desc->length = cpu_to_be32(sizeof(desc->info)); } +void +lpfc_rdp_res_bbc_desc(struct fc_rdp_bbc_desc *desc, READ_LNK_VAR *stat, + struct lpfc_vport *vport) +{ + desc->tag = cpu_to_be32(RDP_BBC_DESC_TAG); + + desc->bbc_info.port_bbc = cpu_to_be32( + vport->fc_sparam.cmn.bbCreditMsb | + vport->fc_sparam.cmn.bbCreditlsb << 8); + if (vport->phba->fc_topology != LPFC_TOPOLOGY_LOOP) + desc->bbc_info.attached_port_bbc = cpu_to_be32( + vport->phba->fc_fabparam.cmn.bbCreditMsb | + vport->phba->fc_fabparam.cmn.bbCreditlsb << 8); + else + desc->bbc_info.attached_port_bbc = 0; + + desc->bbc_info.rtt = 0; + desc->length = cpu_to_be32(sizeof(desc->bbc_info)); +} + +void +lpfc_rdp_res_oed_temp_desc(struct fc_rdp_oed_sfp_desc *desc, uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_TEMP_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_TEMP_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_TEMP_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_TEMP_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_TEMPERATURE) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + +void +lpfc_rdp_res_oed_voltage_desc(struct fc_rdp_oed_sfp_desc *desc, + uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_VOLTAGE_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_VOLTAGE_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_VOLTAGE_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_VOLTAGE_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_VOLTAGE) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + +void +lpfc_rdp_res_oed_txbias_desc(struct fc_rdp_oed_sfp_desc *desc, + uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_BIAS_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_BIAS_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_BIAS_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_BIAS_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_TXBIAS) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + +void +lpfc_rdp_res_oed_txpower_desc(struct fc_rdp_oed_sfp_desc *desc, + uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_TXPOWER_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_TXPOWER_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_TXPOWER_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_TXPOWER_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_TXPOWER) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + + +void +lpfc_rdp_res_oed_rxpower_desc(struct fc_rdp_oed_sfp_desc *desc, + uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_RXPOWER_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_RXPOWER_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_RXPOWER_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_RXPOWER_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_RXPOWER) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + +void +lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc, + uint8_t *page_a0, struct lpfc_vport *vport) +{ + desc->tag = cpu_to_be32(RDP_OPD_DESC_TAG); + memcpy(desc->opd_info.vendor_name, &page_a0[SSF_VENDOR_NAME], 16); + memcpy(desc->opd_info.model_number, &page_a0[SSF_VENDOR_PN], 16); + memcpy(desc->opd_info.serial_number, &page_a0[SSF_VENDOR_SN], 16); + memcpy(desc->opd_info.revision, &page_a0[SSF_VENDOR_REV], 2); + memcpy(desc->opd_info.date, &page_a0[SSF_DATE_CODE], 8); + desc->length = cpu_to_be32(sizeof(desc->opd_info)); +} + int lpfc_rdp_res_fec_desc(struct fc_fec_rdp_desc *desc, READ_LNK_VAR *stat) { @@ -4779,6 +4917,8 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba) if (rdp_cap == 0) rdp_cap = RDP_CAP_UNKNOWN; + if (phba->cfg_link_speed != LPFC_USER_LINK_SPEED_AUTO) + rdp_cap |= RDP_CAP_USER_CONFIGURED; desc->info.port_speed.capabilities = cpu_to_be16(rdp_cap); desc->length = cpu_to_be32(sizeof(desc->info)); @@ -4878,6 +5018,19 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, lpfc_rdp_res_diag_port_names(&rdp_res->diag_port_names_desc, phba); lpfc_rdp_res_attach_port_names(&rdp_res->attached_port_names_desc, vport, ndlp); + lpfc_rdp_res_bbc_desc(&rdp_res->bbc_desc, &rdp_context->link_stat, + vport); + lpfc_rdp_res_oed_temp_desc(&rdp_res->oed_temp_desc, + rdp_context->page_a2); + lpfc_rdp_res_oed_voltage_desc(&rdp_res->oed_voltage_desc, + rdp_context->page_a2); + lpfc_rdp_res_oed_txbias_desc(&rdp_res->oed_txbias_desc, + rdp_context->page_a2); + lpfc_rdp_res_oed_txpower_desc(&rdp_res->oed_txpower_desc, + rdp_context->page_a2); + lpfc_rdp_res_oed_rxpower_desc(&rdp_res->oed_rxpower_desc, + rdp_context->page_a2); + lpfc_rdp_res_opd_desc(&rdp_res->opd_desc, rdp_context->page_a0, vport); fec_size = lpfc_rdp_res_fec_desc(&rdp_res->fec_desc, &rdp_context->link_stat); rdp_res->length = cpu_to_be32(fec_size + RDP_DESC_PAYLOAD_SIZE); diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index dd20412c7e4c..41a961e00f29 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1134,9 +1134,10 @@ struct fc_rdp_link_error_status_desc { #define RDP_PS_16GB 0x0400 #define RDP_PS_32GB 0x0200 -#define RDP_CAP_UNKNOWN 0x0001 -#define RDP_PS_UNKNOWN 0x0002 -#define RDP_PS_NOT_ESTABLISHED 0x0001 +#define RDP_CAP_USER_CONFIGURED 0x0002 +#define RDP_CAP_UNKNOWN 0x0001 +#define RDP_PS_UNKNOWN 0x0002 +#define RDP_PS_NOT_ESTABLISHED 0x0001 struct fc_rdp_port_speed { uint16_t capabilities; @@ -1192,6 +1193,58 @@ struct fc_rdp_sfp_desc { struct fc_rdp_sfp_info sfp_info; }; +/* Buffer Credit Descriptor */ +struct fc_rdp_bbc_info { + uint32_t port_bbc; /* FC_Port buffer-to-buffer credit */ + uint32_t attached_port_bbc; + uint32_t rtt; /* Round trip time */ +}; +#define RDP_BBC_DESC_TAG 0x00010006 +struct fc_rdp_bbc_desc { + uint32_t tag; + uint32_t length; + struct fc_rdp_bbc_info bbc_info; +}; + +#define RDP_OED_TEMPERATURE 0x1 +#define RDP_OED_VOLTAGE 0x2 +#define RDP_OED_TXBIAS 0x3 +#define RDP_OED_TXPOWER 0x4 +#define RDP_OED_RXPOWER 0x5 + +#define RDP_OED_TYPE_SHIFT 28 +/* Optical Element Data descriptor */ +struct fc_rdp_oed_info { + uint16_t hi_alarm; + uint16_t lo_alarm; + uint16_t hi_warning; + uint16_t lo_warning; + uint32_t function_flags; +}; +#define RDP_OED_DESC_TAG 0x00010007 +struct fc_rdp_oed_sfp_desc { + uint32_t tag; + uint32_t length; + struct fc_rdp_oed_info oed_info; +}; + +/* Optical Product Data descriptor */ +struct fc_rdp_opd_sfp_info { + uint8_t vendor_name[16]; + uint8_t model_number[16]; + uint8_t serial_number[16]; + uint8_t reserved[2]; + uint8_t revision[2]; + uint8_t date[8]; +}; + +#define RDP_OPD_DESC_TAG 0x00010008 +struct fc_rdp_opd_sfp_desc { + uint32_t tag; + uint32_t length; + struct fc_rdp_opd_sfp_info opd_info; +}; + struct fc_rdp_req_frame { uint32_t rdp_command; /* ELS command opcode (0x18)*/ uint32_t rdp_des_length; /* RDP Payload Word 1 */ @@ -1208,7 +1261,14 @@ struct fc_rdp_res_frame { struct fc_rdp_link_error_status_desc link_error_desc; /* Word 13-21 */ struct fc_rdp_port_name_desc diag_port_names_desc; /* Word 22-27 */ struct fc_rdp_port_name_desc attached_port_names_desc;/* Word 28-33 */ - struct fc_fec_rdp_desc fec_desc; /* FC Word 34 - 37 */ + struct fc_rdp_bbc_desc bbc_desc; /* FC Word 34-38*/ + struct fc_rdp_oed_sfp_desc oed_temp_desc; /* FC Word 39-43*/ + struct fc_rdp_oed_sfp_desc oed_voltage_desc; /* FC word 44-48*/ + struct fc_rdp_oed_sfp_desc oed_txbias_desc; /* FC word 49-53*/ + struct fc_rdp_oed_sfp_desc oed_txpower_desc; /* FC word 54-58*/ + struct fc_rdp_oed_sfp_desc oed_rxpower_desc; /* FC word 59-63*/ + struct fc_rdp_opd_sfp_desc opd_desc; /* FC word 64-80*/ + struct fc_fec_rdp_desc fec_desc; /* FC word 81-84*/ }; @@ -1216,7 +1276,10 @@ struct fc_rdp_res_frame { + sizeof(struct fc_rdp_sfp_desc) \ + sizeof(struct fc_rdp_port_speed_desc) \ + sizeof(struct fc_rdp_link_error_status_desc) \ - + (sizeof(struct fc_rdp_port_name_desc) * 2)) + + (sizeof(struct fc_rdp_port_name_desc) * 2) \ + + sizeof(struct fc_rdp_bbc_desc) \ + + (sizeof(struct fc_rdp_oed_sfp_desc) * 5) \ + + sizeof(struct fc_rdp_opd_sfp_desc)) /******** FDMI ********/ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index aea00f8be9ac..634c9b1c6710 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -2557,7 +2557,26 @@ struct lpfc_mbx_memory_dump_type3 { /* SFF-8472 Table 3.1a Diagnostics: Data Fields Address/Page A2 */ -#define SSF_AW_THRESHOLDS 0 +#define SSF_TEMP_HIGH_ALARM 0 +#define SSF_TEMP_LOW_ALARM 2 +#define SSF_TEMP_HIGH_WARNING 4 +#define SSF_TEMP_LOW_WARNING 6 +#define SSF_VOLTAGE_HIGH_ALARM 8 +#define SSF_VOLTAGE_LOW_ALARM 10 +#define SSF_VOLTAGE_HIGH_WARNING 12 +#define SSF_VOLTAGE_LOW_WARNING 14 +#define SSF_BIAS_HIGH_ALARM 16 +#define SSF_BIAS_LOW_ALARM 18 +#define SSF_BIAS_HIGH_WARNING 20 +#define SSF_BIAS_LOW_WARNING 22 +#define SSF_TXPOWER_HIGH_ALARM 24 +#define SSF_TXPOWER_LOW_ALARM 26 +#define SSF_TXPOWER_HIGH_WARNING 28 +#define SSF_TXPOWER_LOW_WARNING 30 +#define SSF_RXPOWER_HIGH_ALARM 32 +#define SSF_RXPOWER_LOW_ALARM 34 +#define SSF_RXPOWER_HIGH_WARNING 36 +#define SSF_RXPOWER_LOW_WARNING 38 #define SSF_EXT_CAL_CONSTANTS 56 #define SSF_CC_DMI 95 #define SFF_TEMPERATURE_B1 96 From 8663cbbe3ba0d8142faec48bbab0dc3482e3007d Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:33 -0700 Subject: [PATCH 047/138] lpfc: Fix interaction between fdmi_on and enable_SmartSAN Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 - drivers/scsi/lpfc/lpfc_attr.c | 23 +++++++---------------- drivers/scsi/lpfc/lpfc_els.c | 16 +++++++++------- drivers/scsi/lpfc/lpfc_init.c | 5 +++-- drivers/scsi/lpfc/lpfc_vport.c | 3 ++- 5 files changed, 21 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index da237d9c4b55..283942a4ae82 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -758,7 +758,6 @@ struct lpfc_hba { uint32_t cfg_fdmi_on; #define LPFC_FDMI_NO_SUPPORT 0 /* FDMI not supported */ #define LPFC_FDMI_SUPPORT 1 /* FDMI supported? */ -#define LPFC_FDMI_SMART_SAN 2 /* SmartSAN supported */ uint32_t cfg_enable_SmartSAN; lpfc_vpd_t vpd; /* vital product data */ diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index d4559a6175e2..9528f863f219 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4584,15 +4584,14 @@ LPFC_ATTR_R(enable_SmartSAN, 0, 0, 1, "Enable SmartSAN functionality"); # lpfc_fdmi_on: Controls FDMI support. # 0 No FDMI support (default) # 1 Traditional FDMI support -# 2 Smart SAN support -# If lpfc_enable_SmartSAN is set 1, the driver sets lpfc_fdmi_on to value 2 -# overwriting the current value. If lpfc_enable_SmartSAN is set 0, the -# driver uses the current value of lpfc_fdmi_on provided it has value 0 or 1. -# A value of 2 with lpfc_enable_SmartSAN set to 0 causes the driver to -# set lpfc_fdmi_on back to 1. -# Value range [0,2]. Default value is 0. +# Traditional FDMI support means the driver will assume FDMI-2 support; +# however, if that fails, it will fallback to FDMI-1. +# If lpfc_enable_SmartSAN is set to 1, the driver ignores lpfc_fdmi_on. +# If lpfc_enable_SmartSAN is set 0, the driver uses the current value of +# lpfc_fdmi_on. +# Value range [0,1]. Default value is 0. */ -LPFC_ATTR_R(fdmi_on, 0, 0, 2, "Enable FDMI support"); +LPFC_ATTR_R(fdmi_on, 0, 0, 1, "Enable FDMI support"); /* # Specifies the maximum number of ELS cmds we can have outstanding (for @@ -5856,14 +5855,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) else phba->cfg_poll = lpfc_poll; - /* Ensure fdmi_on and enable_SmartSAN don't conflict */ - if (phba->cfg_enable_SmartSAN) { - phba->cfg_fdmi_on = LPFC_FDMI_SMART_SAN; - } else { - if (phba->cfg_fdmi_on == LPFC_FDMI_SMART_SAN) - phba->cfg_fdmi_on = LPFC_FDMI_SUPPORT; - } - phba->cfg_soft_wwnn = 0L; phba->cfg_soft_wwpn = 0L; lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 9459ac451600..6cc1af42af36 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -690,16 +690,17 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp); if (fabric_param_changed) { /* Reset FDMI attribute masks based on config parameter */ - if (phba->cfg_fdmi_on == LPFC_FDMI_NO_SUPPORT) { - vport->fdmi_hba_mask = 0; - vport->fdmi_port_mask = 0; - } else { + if (phba->cfg_enable_SmartSAN || + (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) { /* Setup appropriate attribute masks */ vport->fdmi_hba_mask = LPFC_FDMI2_HBA_ATTR; - if (phba->cfg_fdmi_on == LPFC_FDMI_SMART_SAN) + if (phba->cfg_enable_SmartSAN) vport->fdmi_port_mask = LPFC_FDMI2_SMART_ATTR; else vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR; + } else { + vport->fdmi_hba_mask = 0; + vport->fdmi_port_mask = 0; } } @@ -8005,8 +8006,9 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) return; } - if ((phba->cfg_fdmi_on > LPFC_FDMI_NO_SUPPORT) && - (vport->load_flag & FC_ALLOW_FDMI)) + if ((phba->cfg_enable_SmartSAN || + (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) && + (vport->load_flag & FC_ALLOW_FDMI)) lpfc_start_fdmi(vport); } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f0d0852bee0d..c922a2b1f864 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -6158,11 +6158,12 @@ lpfc_create_shost(struct lpfc_hba *phba) * any initial discovery should be completed. */ vport->load_flag |= FC_ALLOW_FDMI; - if (phba->cfg_fdmi_on > LPFC_FDMI_NO_SUPPORT) { + if (phba->cfg_enable_SmartSAN || + (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) { /* Setup appropriate attribute masks */ vport->fdmi_hba_mask = LPFC_FDMI2_HBA_ATTR; - if (phba->cfg_fdmi_on == LPFC_FDMI_SMART_SAN) + if (phba->cfg_enable_SmartSAN) vport->fdmi_port_mask = LPFC_FDMI2_SMART_ATTR; else vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR; diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index b3f85def18cc..9b7adcac5a87 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -395,7 +395,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) /* At this point we are fully registered with SCSI Layer. */ vport->load_flag |= FC_ALLOW_FDMI; - if (phba->cfg_fdmi_on > LPFC_FDMI_NO_SUPPORT) { + if (phba->cfg_enable_SmartSAN || + (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) { /* Setup appropriate attribute masks */ vport->fdmi_hba_mask = phba->pport->fdmi_hba_mask; vport->fdmi_port_mask = phba->pport->fdmi_port_mask; From 506115777af017bfc0968ee1c6aed024cdb6e43b Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:34 -0700 Subject: [PATCH 048/138] lpfc: Update modified file copyrights Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 +- drivers/scsi/lpfc/lpfc_attr.c | 2 +- drivers/scsi/lpfc/lpfc_ct.c | 2 +- drivers/scsi/lpfc/lpfc_els.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/scsi/lpfc/lpfc_hw.h | 2 +- drivers/scsi/lpfc/lpfc_hw4.h | 2 +- drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/lpfc/lpfc_mbox.c | 2 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 2 +- drivers/scsi/lpfc/lpfc_version.h | 4 ++-- drivers/scsi/lpfc/lpfc_vport.c | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 283942a4ae82..d5bd420595c1 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 9528f863f219..cfec2eca4dd3 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 982039e73d33..a38816e96654 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6cc1af42af36..0498f5760d2b 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index b3bf230f714a..ed223937798a 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 41a961e00f29..39f0fd000d2c 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 634c9b1c6710..0c7070bf2813 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2009-2015 Emulex. All rights reserved. * + * Copyright (C) 2009-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index c922a2b1f864..b43f7ac9812c 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 1e34b5408a29..12dbe99ccc50 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 9b539e2e864b..56a3df4fddb0 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 9c8368a7149a..6b267b67f845 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 4dc22562aaf1..6b57e0cdb7cf 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -30,4 +30,4 @@ #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ LPFC_DRIVER_VERSION -#define LPFC_COPYRIGHT "Copyright(c) 2004-2015 Emulex. All rights reserved." +#define LPFC_COPYRIGHT "Copyright(c) 2004-2016 Emulex. All rights reserved." diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 9b7adcac5a87..c27f4b724547 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2013 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * From 45cc807291d5fde7a6691a06c0ca9f472fa3fb15 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:35 -0700 Subject: [PATCH 049/138] lpfc: Update driver version to 11.1.0.0 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 6b57e0cdb7cf..fa0d531bf351 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "11.0.0.10." +#define LPFC_DRIVER_VERSION "11.1.0.0." #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ From 3f5c11a463fd87b912f16976ff0ee3d6bbd1825e Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:10 -0700 Subject: [PATCH 050/138] snic: Added additional stats Adding additional stats, and fixed logging messages. - Added qdepth change stats - Added separate isr stats for each type of interrupt - Fixed race in updating active IOs - Suppressed Link event message for DAS backend. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_ctl.c | 8 +++----- drivers/scsi/snic/snic_debugfs.c | 20 ++++++++++++++++---- drivers/scsi/snic/snic_isr.c | 6 +++--- drivers/scsi/snic/snic_main.c | 9 ++++++++- drivers/scsi/snic/snic_scsi.c | 29 +++++++++++++++++++++-------- drivers/scsi/snic/snic_stats.h | 12 +++++++++--- 6 files changed, 60 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/snic/snic_ctl.c b/drivers/scsi/snic/snic_ctl.c index ab0e06b0b4ff..449b03f3bbd3 100644 --- a/drivers/scsi/snic/snic_ctl.c +++ b/drivers/scsi/snic/snic_ctl.c @@ -39,17 +39,15 @@ snic_handle_link(struct work_struct *work) { struct snic *snic = container_of(work, struct snic, link_work); - if (snic->config.xpt_type != SNIC_DAS) { - SNIC_HOST_INFO(snic->shost, "Link Event Received.\n"); - SNIC_ASSERT_NOT_IMPL(1); - + if (snic->config.xpt_type == SNIC_DAS) return; - } snic->link_status = svnic_dev_link_status(snic->vdev); snic->link_down_cnt = svnic_dev_link_down_cnt(snic->vdev); SNIC_HOST_INFO(snic->shost, "Link Event: Link %s.\n", ((snic->link_status) ? "Up" : "Down")); + + SNIC_ASSERT_NOT_IMPL(1); } diff --git a/drivers/scsi/snic/snic_debugfs.c b/drivers/scsi/snic/snic_debugfs.c index 1686f0196251..d30280326bde 100644 --- a/drivers/scsi/snic/snic_debugfs.c +++ b/drivers/scsi/snic/snic_debugfs.c @@ -264,12 +264,14 @@ snic_stats_show(struct seq_file *sfp, void *data) "Aborts Fail : %lld\n" "Aborts Driver Timeout : %lld\n" "Abort FW Timeout : %lld\n" - "Abort IO NOT Found : %lld\n", + "Abort IO NOT Found : %lld\n" + "Abort Queuing Failed : %lld\n", (u64) atomic64_read(&stats->abts.num), (u64) atomic64_read(&stats->abts.fail), (u64) atomic64_read(&stats->abts.drv_tmo), (u64) atomic64_read(&stats->abts.fw_tmo), - (u64) atomic64_read(&stats->abts.io_not_found)); + (u64) atomic64_read(&stats->abts.io_not_found), + (u64) atomic64_read(&stats->abts.q_fail)); /* Dump Reset Stats */ seq_printf(sfp, @@ -316,7 +318,9 @@ snic_stats_show(struct seq_file *sfp, void *data) seq_printf(sfp, "Last ISR Time : %llu (%8lu.%8lu)\n" "Last Ack Time : %llu (%8lu.%8lu)\n" - "ISRs : %llu\n" + "Ack ISRs : %llu\n" + "IO Cmpl ISRs : %llu\n" + "Err Notify ISRs : %llu\n" "Max CQ Entries : %lld\n" "Data Count Mismatch : %lld\n" "IOs w/ Timeout Status : %lld\n" @@ -324,12 +328,17 @@ snic_stats_show(struct seq_file *sfp, void *data) "IOs w/ SGL Invalid Stat : %lld\n" "WQ Desc Alloc Fail : %lld\n" "Queue Full : %lld\n" + "Queue Ramp Up : %lld\n" + "Queue Ramp Down : %lld\n" + "Queue Last Queue Depth : %lld\n" "Target Not Ready : %lld\n", (u64) stats->misc.last_isr_time, last_isr_tms.tv_sec, last_isr_tms.tv_nsec, (u64)stats->misc.last_ack_time, last_ack_tms.tv_sec, last_ack_tms.tv_nsec, - (u64) atomic64_read(&stats->misc.isr_cnt), + (u64) atomic64_read(&stats->misc.ack_isr_cnt), + (u64) atomic64_read(&stats->misc.cmpl_isr_cnt), + (u64) atomic64_read(&stats->misc.errnotify_isr_cnt), (u64) atomic64_read(&stats->misc.max_cq_ents), (u64) atomic64_read(&stats->misc.data_cnt_mismat), (u64) atomic64_read(&stats->misc.io_tmo), @@ -337,6 +346,9 @@ snic_stats_show(struct seq_file *sfp, void *data) (u64) atomic64_read(&stats->misc.sgl_inval), (u64) atomic64_read(&stats->misc.wq_alloc_fail), (u64) atomic64_read(&stats->misc.qfull), + (u64) atomic64_read(&stats->misc.qsz_rampup), + (u64) atomic64_read(&stats->misc.qsz_rampdown), + (u64) atomic64_read(&stats->misc.last_qsz), (u64) atomic64_read(&stats->misc.tgt_not_rdy)); return 0; diff --git a/drivers/scsi/snic/snic_isr.c b/drivers/scsi/snic/snic_isr.c index a85fae25ec8c..f552003128c6 100644 --- a/drivers/scsi/snic/snic_isr.c +++ b/drivers/scsi/snic/snic_isr.c @@ -38,7 +38,7 @@ snic_isr_msix_wq(int irq, void *data) unsigned long wq_work_done = 0; snic->s_stats.misc.last_isr_time = jiffies; - atomic64_inc(&snic->s_stats.misc.isr_cnt); + atomic64_inc(&snic->s_stats.misc.ack_isr_cnt); wq_work_done = snic_wq_cmpl_handler(snic, -1); svnic_intr_return_credits(&snic->intr[SNIC_MSIX_WQ], @@ -56,7 +56,7 @@ snic_isr_msix_io_cmpl(int irq, void *data) unsigned long iocmpl_work_done = 0; snic->s_stats.misc.last_isr_time = jiffies; - atomic64_inc(&snic->s_stats.misc.isr_cnt); + atomic64_inc(&snic->s_stats.misc.cmpl_isr_cnt); iocmpl_work_done = snic_fwcq_cmpl_handler(snic, -1); svnic_intr_return_credits(&snic->intr[SNIC_MSIX_IO_CMPL], @@ -73,7 +73,7 @@ snic_isr_msix_err_notify(int irq, void *data) struct snic *snic = data; snic->s_stats.misc.last_isr_time = jiffies; - atomic64_inc(&snic->s_stats.misc.isr_cnt); + atomic64_inc(&snic->s_stats.misc.errnotify_isr_cnt); svnic_intr_return_all_credits(&snic->intr[SNIC_MSIX_ERR_NOTIFY]); snic_log_q_error(snic); diff --git a/drivers/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c index 2b3c25371d76..37ec507b7e67 100644 --- a/drivers/scsi/snic/snic_main.c +++ b/drivers/scsi/snic/snic_main.c @@ -98,11 +98,18 @@ snic_slave_configure(struct scsi_device *sdev) static int snic_change_queue_depth(struct scsi_device *sdev, int qdepth) { + struct snic *snic = shost_priv(sdev->host); int qsz = 0; qsz = min_t(u32, qdepth, SNIC_MAX_QUEUE_DEPTH); + if (qsz < sdev->queue_depth) + atomic64_inc(&snic->s_stats.misc.qsz_rampdown); + else if (qsz > sdev->queue_depth) + atomic64_inc(&snic->s_stats.misc.qsz_rampup); + + atomic64_set(&snic->s_stats.misc.last_qsz, sdev->queue_depth); + scsi_change_queue_depth(sdev, qsz); - SNIC_INFO("QDepth Changed to %d\n", sdev->queue_depth); return sdev->queue_depth; } diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c index 2c7b4c321cbe..e423eaacb926 100644 --- a/drivers/scsi/snic/snic_scsi.c +++ b/drivers/scsi/snic/snic_scsi.c @@ -221,11 +221,15 @@ snic_queue_icmnd_req(struct snic *snic, pa, /* sense buffer pa */ SCSI_SENSE_BUFFERSIZE); + atomic64_inc(&snic->s_stats.io.active); ret = snic_queue_wq_desc(snic, rqi->req, rqi->req_len); - if (ret) + if (ret) { + atomic64_dec(&snic->s_stats.io.active); SNIC_HOST_ERR(snic->shost, "QIcmnd: Queuing Icmnd Failed. ret = %d\n", ret); + } else + snic_stats_update_active_ios(&snic->s_stats); return ret; } /* end of snic_queue_icmnd_req */ @@ -361,8 +365,7 @@ snic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc) if (ret) { SNIC_HOST_ERR(shost, "Failed to Q, Scsi Req w/ err %d.\n", ret); ret = SCSI_MLQUEUE_HOST_BUSY; - } else - snic_stats_update_active_ios(&snic->s_stats); + } atomic_dec(&snic->ios_inflight); @@ -1001,10 +1004,11 @@ snic_hba_reset_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq) unsigned long flags, gflags; int ret = 0; - SNIC_HOST_INFO(snic->shost, - "reset_cmpl:HBA Reset Completion received.\n"); - snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx); + SNIC_HOST_INFO(snic->shost, + "reset_cmpl:Tag %d ctx %lx cmpl status %s HBA Reset Completion received.\n", + cmnd_id, ctx, snic_io_status_to_str(hdr_stat)); + SNIC_SCSI_DBG(snic->shost, "reset_cmpl: type = %x, hdr_stat = %x, cmnd_id = %x, hid = %x, ctx = %lx\n", typ, hdr_stat, cmnd_id, hid, ctx); @@ -1012,6 +1016,9 @@ snic_hba_reset_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq) /* spl case, host reset issued through ioctl */ if (cmnd_id == SCSI_NO_TAG) { rqi = (struct snic_req_info *) ctx; + SNIC_HOST_INFO(snic->shost, + "reset_cmpl:Tag %d ctx %lx cmpl stat %s\n", + cmnd_id, ctx, snic_io_status_to_str(hdr_stat)); sc = rqi->sc; goto ioctl_hba_rst; @@ -1038,6 +1045,10 @@ snic_hba_reset_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq) return ret; } + SNIC_HOST_INFO(snic->shost, + "reset_cmpl: sc %p rqi %p Tag %d flags 0x%llx\n", + sc, rqi, cmnd_id, CMD_FLAGS(sc)); + io_lock = snic_io_lock_hash(snic, sc); spin_lock_irqsave(io_lock, flags); @@ -1554,6 +1565,7 @@ snic_send_abort_and_wait(struct snic *snic, struct scsi_cmnd *sc) /* Now Queue the abort command to firmware */ ret = snic_queue_abort_req(snic, rqi, sc, tmf); if (ret) { + atomic64_inc(&snic->s_stats.abts.q_fail); SNIC_HOST_ERR(snic->shost, "send_abt_cmd: IO w/ Tag 0x%x fail w/ err %d flags 0x%llx\n", tag, ret, CMD_FLAGS(sc)); @@ -2459,8 +2471,9 @@ snic_scsi_cleanup(struct snic *snic, int ex_tag) cleanup: sc->result = DID_TRANSPORT_DISRUPTED << 16; SNIC_HOST_INFO(snic->shost, - "sc_clean: DID_TRANSPORT_DISRUPTED for sc %p. rqi %p duration %llu msecs\n", - sc, rqi, (jiffies - st_time)); + "sc_clean: DID_TRANSPORT_DISRUPTED for sc %p, Tag %d flags 0x%llx rqi %p duration %u msecs\n", + sc, sc->request->tag, CMD_FLAGS(sc), rqi, + jiffies_to_msecs(jiffies - st_time)); /* Update IO stats */ snic_stats_update_io_cmpl(&snic->s_stats); diff --git a/drivers/scsi/snic/snic_stats.h b/drivers/scsi/snic/snic_stats.h index 11e614849a82..fd1066b1cad5 100644 --- a/drivers/scsi/snic/snic_stats.h +++ b/drivers/scsi/snic/snic_stats.h @@ -42,6 +42,7 @@ struct snic_abort_stats { atomic64_t drv_tmo; /* Abort Driver Timeouts */ atomic64_t fw_tmo; /* Abort Firmware Timeouts */ atomic64_t io_not_found;/* Abort IO Not Found */ + atomic64_t q_fail; /* Abort Queuing Failed */ }; struct snic_reset_stats { @@ -69,7 +70,9 @@ struct snic_fw_stats { struct snic_misc_stats { u64 last_isr_time; u64 last_ack_time; - atomic64_t isr_cnt; + atomic64_t ack_isr_cnt; + atomic64_t cmpl_isr_cnt; + atomic64_t errnotify_isr_cnt; atomic64_t max_cq_ents; /* Max CQ Entries */ atomic64_t data_cnt_mismat; /* Data Count Mismatch */ atomic64_t io_tmo; @@ -81,6 +84,9 @@ struct snic_misc_stats { atomic64_t no_icmnd_itmf_cmpls; atomic64_t io_under_run; atomic64_t qfull; + atomic64_t qsz_rampup; + atomic64_t qsz_rampdown; + atomic64_t last_qsz; atomic64_t tgt_not_rdy; }; @@ -101,9 +107,9 @@ static inline void snic_stats_update_active_ios(struct snic_stats *s_stats) { struct snic_io_stats *io = &s_stats->io; - u32 nr_active_ios; + int nr_active_ios; - nr_active_ios = atomic64_inc_return(&io->active); + nr_active_ios = atomic64_read(&io->active); if (atomic64_read(&io->max_active) < nr_active_ios) atomic64_set(&io->max_active, nr_active_ios); From f352a0d5bafa62d1f0b044613ea42483a529f9df Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:11 -0700 Subject: [PATCH 051/138] snic: LUN goes offline due to scsi cmd timeouts - LUN goes offline if there are at least two scsi command timeouts Completing the IO with scsi_done() fixes the issue. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_scsi.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c index e423eaacb926..5a709ebdb282 100644 --- a/drivers/scsi/snic/snic_scsi.c +++ b/drivers/scsi/snic/snic_scsi.c @@ -1465,11 +1465,19 @@ snic_abort_finish(struct snic *snic, struct scsi_cmnd *sc) case SNIC_STAT_IO_SUCCESS: case SNIC_STAT_IO_NOT_FOUND: ret = SUCCESS; + /* + * If abort path doesn't call scsi_done(), + * the # IO timeouts == 2, will cause the LUN offline. + * Call scsi_done to complete the IO. + */ + sc->result = (DID_ERROR << 16); + sc->scsi_done(sc); break; default: /* Firmware completed abort with error */ ret = FAILED; + rqi = NULL; break; } @@ -1842,6 +1850,9 @@ snic_dr_clean_single_req(struct snic *snic, snic_release_req_buf(snic, rqi, sc); + sc->result = (DID_ERROR << 16); + sc->scsi_done(sc); + ret = 0; return ret; @@ -2396,6 +2407,13 @@ snic_cmpl_pending_tmreq(struct snic *snic, struct scsi_cmnd *sc) "Completing Pending TM Req sc %p, state %s flags 0x%llx\n", sc, snic_io_status_to_str(CMD_STATE(sc)), CMD_FLAGS(sc)); + /* + * CASE : FW didn't post itmf completion due to PCIe Errors. + * Marking the abort status as Success to call scsi completion + * in snic_abort_finish() + */ + CMD_ABTS_STATUS(sc) = SNIC_STAT_IO_SUCCESS; + rqi = (struct snic_req_info *) CMD_SP(sc); if (!rqi) return; From 6e0ae74b5ca2826fa6c86a157ed5227c766156b9 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:12 -0700 Subject: [PATCH 052/138] snic: Handling control path queue issues Fix handles control path queue issues such as queue full and sudden removal of hardware. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/vnic_dev.c | 44 ++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/snic/vnic_dev.c b/drivers/scsi/snic/vnic_dev.c index e0b5549bc9fb..dad5fc66effb 100644 --- a/drivers/scsi/snic/vnic_dev.c +++ b/drivers/scsi/snic/vnic_dev.c @@ -263,12 +263,20 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, int wait) { struct devcmd2_controller *dc2c = vdev->devcmd2; - struct devcmd2_result *result = dc2c->result + dc2c->next_result; + struct devcmd2_result *result = NULL; unsigned int i; int delay; int err; u32 posted; + u32 fetch_idx; u32 new_posted; + u8 color; + + fetch_idx = ioread32(&dc2c->wq_ctrl->fetch_index); + if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone */ + /* Hardware surprise removal: return error */ + return -ENODEV; + } posted = ioread32(&dc2c->wq_ctrl->posted_index); @@ -278,6 +286,13 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, } new_posted = (posted + 1) % DEVCMD2_RING_SIZE; + if (new_posted == fetch_idx) { + pr_err("%s: wq is full while issuing devcmd2 command %d, fetch index: %u, posted index: %u\n", + pci_name(vdev->pdev), _CMD_N(cmd), fetch_idx, posted); + + return -EBUSY; + } + dc2c->cmd_ring[posted].cmd = cmd; dc2c->cmd_ring[posted].flags = 0; @@ -299,14 +314,22 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT) return 0; + result = dc2c->result + dc2c->next_result; + color = dc2c->color; + + /* + * Increment next_result, after posting the devcmd, irrespective of + * devcmd result, and it should be done only once. + */ + dc2c->next_result++; + if (dc2c->next_result == dc2c->result_size) { + dc2c->next_result = 0; + dc2c->color = dc2c->color ? 0 : 1; + } + for (delay = 0; delay < wait; delay++) { udelay(100); - if (result->color == dc2c->color) { - dc2c->next_result++; - if (dc2c->next_result == dc2c->result_size) { - dc2c->next_result = 0; - dc2c->color = dc2c->color ? 0 : 1; - } + if (result->color == color) { if (result->error) { err = (int) result->error; if (err != ERR_ECMDUNKNOWN || @@ -317,13 +340,6 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, return err; } if (_CMD_DIR(cmd) & _CMD_DIR_READ) { - /* - * Adding the rmb() prevents the compiler - * and/or CPU from reordering the reads which - * would potentially result in reading stale - * values. - */ - rmb(); for (i = 0; i < VNIC_DEVCMD_NARGS; i++) vdev->args[i] = result->results[i]; } From 58fcf92050cdf7b499ba6169459ec43aa0838662 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:13 -0700 Subject: [PATCH 053/138] snic: target cleanup in driver unload path Fix deletes the snic targets synchronously prior to deletion of host. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_disc.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c index 5f48795767bd..b0fefd67cac3 100644 --- a/drivers/scsi/snic/snic_disc.c +++ b/drivers/scsi/snic/snic_disc.c @@ -480,10 +480,21 @@ int snic_disc_start(struct snic *snic) { struct snic_disc *disc = &snic->disc; + unsigned long flags; int ret = 0; SNIC_SCSI_DBG(snic->shost, "Discovery Start.\n"); + spin_lock_irqsave(&snic->snic_lock, flags); + if (snic->in_remove) { + spin_unlock_irqrestore(&snic->snic_lock, flags); + SNIC_ERR("snic driver removal in progress ...\n"); + ret = 0; + + return ret; + } + spin_unlock_irqrestore(&snic->snic_lock, flags); + mutex_lock(&disc->mutex); if (disc->state == SNIC_DISC_PENDING) { disc->req_cnt++; @@ -533,6 +544,8 @@ snic_tgt_del_all(struct snic *snic) struct list_head *cur, *nxt; unsigned long flags; + scsi_flush_work(snic->shost); + mutex_lock(&snic->disc.mutex); spin_lock_irqsave(snic->shost->host_lock, flags); @@ -545,7 +558,7 @@ snic_tgt_del_all(struct snic *snic) tgt = NULL; } spin_unlock_irqrestore(snic->shost->host_lock, flags); - - scsi_flush_work(snic->shost); mutex_unlock(&snic->disc.mutex); + + flush_workqueue(snic_glob->event_q); } /* end of snic_tgt_del_all */ From c9747821f9bbff6c07fa36087b003d89d05245c8 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:14 -0700 Subject: [PATCH 054/138] snic: Fix for missing interrupts - On posting an IO to the firmware, adapter generates an interrupt. Due to hardware issues, sometimes the adapter fails to generate the interrupt. This behavior skips updating transmit queue- counters, which in turn causes the queue full condition. The fix addresses the queue full condition. - The fix also reserves a slot in transmit queue for hba reset. when queue full is observed during IO, there will always be room to post hba reset command. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_fwint.h | 4 ++- drivers/scsi/snic/snic_io.c | 64 ++++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/snic/snic_fwint.h b/drivers/scsi/snic/snic_fwint.h index 2cfaf2dc915f..c5f9e1917a8e 100644 --- a/drivers/scsi/snic/snic_fwint.h +++ b/drivers/scsi/snic/snic_fwint.h @@ -414,7 +414,7 @@ enum snic_ev_type { /* Payload 88 bytes = 128 - 24 - 16 */ #define SNIC_HOST_REQ_PAYLOAD ((int)(SNIC_HOST_REQ_LEN - \ sizeof(struct snic_io_hdr) - \ - (2 * sizeof(u64)))) + (2 * sizeof(u64)) - sizeof(ulong))) /* * snic_host_req: host -> firmware request @@ -448,6 +448,8 @@ struct snic_host_req { /* hba reset */ struct snic_hba_reset reset; } u; + + ulong req_pa; }; /* end of snic_host_req structure */ diff --git a/drivers/scsi/snic/snic_io.c b/drivers/scsi/snic/snic_io.c index 993db7de4e4b..8e69548395b9 100644 --- a/drivers/scsi/snic/snic_io.c +++ b/drivers/scsi/snic/snic_io.c @@ -48,7 +48,7 @@ snic_wq_cmpl_frame_send(struct vnic_wq *wq, SNIC_TRC(snic->shost->host_no, 0, 0, ((ulong)(buf->os_buf) - sizeof(struct snic_req_info)), 0, 0, 0); - pci_unmap_single(snic->pdev, buf->dma_addr, buf->len, PCI_DMA_TODEVICE); + buf->os_buf = NULL; } @@ -137,13 +137,36 @@ snic_select_wq(struct snic *snic) return 0; } +static int +snic_wqdesc_avail(struct snic *snic, int q_num, int req_type) +{ + int nr_wqdesc = snic->config.wq_enet_desc_count; + + if (q_num > 0) { + /* + * Multi Queue case, additional care is required. + * Per WQ active requests need to be maintained. + */ + SNIC_HOST_INFO(snic->shost, "desc_avail: Multi Queue case.\n"); + SNIC_BUG_ON(q_num > 0); + + return -1; + } + + nr_wqdesc -= atomic64_read(&snic->s_stats.fw.actv_reqs); + + return ((req_type == SNIC_REQ_HBA_RESET) ? nr_wqdesc : nr_wqdesc - 1); +} + int snic_queue_wq_desc(struct snic *snic, void *os_buf, u16 len) { dma_addr_t pa = 0; unsigned long flags; struct snic_fw_stats *fwstats = &snic->s_stats.fw; + struct snic_host_req *req = (struct snic_host_req *) os_buf; long act_reqs; + long desc_avail = 0; int q_num = 0; snic_print_desc(__func__, os_buf, len); @@ -156,11 +179,15 @@ snic_queue_wq_desc(struct snic *snic, void *os_buf, u16 len) return -ENOMEM; } + req->req_pa = (ulong)pa; + q_num = snic_select_wq(snic); spin_lock_irqsave(&snic->wq_lock[q_num], flags); - if (!svnic_wq_desc_avail(snic->wq)) { + desc_avail = snic_wqdesc_avail(snic, q_num, req->hdr.type); + if (desc_avail <= 0) { pci_unmap_single(snic->pdev, pa, len, PCI_DMA_TODEVICE); + req->req_pa = 0; spin_unlock_irqrestore(&snic->wq_lock[q_num], flags); atomic64_inc(&snic->s_stats.misc.wq_alloc_fail); SNIC_DBG("host = %d, WQ is Full\n", snic->shost->host_no); @@ -169,10 +196,13 @@ snic_queue_wq_desc(struct snic *snic, void *os_buf, u16 len) } snic_queue_wq_eth_desc(&snic->wq[q_num], os_buf, pa, len, 0, 0, 1); + /* + * Update stats + * note: when multi queue enabled, fw actv_reqs should be per queue. + */ + act_reqs = atomic64_inc_return(&fwstats->actv_reqs); spin_unlock_irqrestore(&snic->wq_lock[q_num], flags); - /* Update stats */ - act_reqs = atomic64_inc_return(&fwstats->actv_reqs); if (act_reqs > atomic64_read(&fwstats->max_actv_reqs)) atomic64_set(&fwstats->max_actv_reqs, act_reqs); @@ -318,11 +348,31 @@ snic_req_free(struct snic *snic, struct snic_req_info *rqi) "Req_free:rqi %p:ioreq %p:abt %p:dr %p\n", rqi, rqi->req, rqi->abort_req, rqi->dr_req); - if (rqi->abort_req) - mempool_free(rqi->abort_req, snic->req_pool[SNIC_REQ_TM_CACHE]); + if (rqi->abort_req) { + if (rqi->abort_req->req_pa) + pci_unmap_single(snic->pdev, + rqi->abort_req->req_pa, + sizeof(struct snic_host_req), + PCI_DMA_TODEVICE); + + mempool_free(rqi->abort_req, snic->req_pool[SNIC_REQ_TM_CACHE]); + } + + if (rqi->dr_req) { + if (rqi->dr_req->req_pa) + pci_unmap_single(snic->pdev, + rqi->dr_req->req_pa, + sizeof(struct snic_host_req), + PCI_DMA_TODEVICE); - if (rqi->dr_req) mempool_free(rqi->dr_req, snic->req_pool[SNIC_REQ_TM_CACHE]); + } + + if (rqi->req->req_pa) + pci_unmap_single(snic->pdev, + rqi->req->req_pa, + rqi->req_len, + PCI_DMA_TODEVICE); mempool_free(rqi, snic->req_pool[rqi->rq_pool_type]); } From 0da8519b2b1f08113cda65af88a4c9e35157dd53 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:15 -0700 Subject: [PATCH 055/138] snic: Fixing race in the hba reset and IO/TM completion While HBA reset is in progress, if IO/TM completion is received for the same IO then IO/TM completion path releases the driver private resources associated with IO. This fix prevents releasing the resources in IO and TM completion path if HBA reset is in progress. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic.h | 5 ++++- drivers/scsi/snic/snic_scsi.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/snic/snic.h b/drivers/scsi/snic/snic.h index d7f5ba6ba84c..8ed778d4dbb9 100644 --- a/drivers/scsi/snic/snic.h +++ b/drivers/scsi/snic/snic.h @@ -95,6 +95,8 @@ #define SNIC_DEV_RST_NOTSUP BIT(25) #define SNIC_SCSI_CLEANUP BIT(26) #define SNIC_HOST_RESET_ISSUED BIT(27) +#define SNIC_HOST_RESET_CMD_TERM \ + (SNIC_DEV_RST_NOTSUP | SNIC_SCSI_CLEANUP | SNIC_HOST_RESET_ISSUED) #define SNIC_ABTS_TIMEOUT 30000 /* msec */ #define SNIC_LUN_RESET_TIMEOUT 30000 /* msec */ @@ -216,9 +218,10 @@ enum snic_msix_intr_index { SNIC_MSIX_INTR_MAX, }; +#define SNIC_INTRHDLR_NAMSZ (2 * IFNAMSIZ) struct snic_msix_entry { int requested; - char devname[IFNAMSIZ]; + char devname[SNIC_INTRHDLR_NAMSZ]; irqreturn_t (*isr)(int, void *); void *devid; }; diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c index 5a709ebdb282..abada16b375b 100644 --- a/drivers/scsi/snic/snic_scsi.c +++ b/drivers/scsi/snic/snic_scsi.c @@ -601,6 +601,12 @@ snic_icmnd_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq) sc->device->lun, sc, sc->cmnd[0], snic_cmd_tag(sc), CMD_FLAGS(sc), rqi); + if (CMD_FLAGS(sc) & SNIC_HOST_RESET_CMD_TERM) { + spin_unlock_irqrestore(io_lock, flags); + + return; + } + SNIC_BUG_ON(rqi != (struct snic_req_info *)ctx); WARN_ON_ONCE(req); if (!rqi) { @@ -782,6 +788,11 @@ snic_process_itmf_cmpl(struct snic *snic, io_lock = snic_io_lock_hash(snic, sc); spin_lock_irqsave(io_lock, flags); + if (CMD_FLAGS(sc) & SNIC_HOST_RESET_CMD_TERM) { + spin_unlock_irqrestore(io_lock, flags); + + return ret; + } rqi = (struct snic_req_info *) CMD_SP(sc); WARN_ON_ONCE(!rqi); From be2a266d2a163a332666f396ea128a6bcc6882f7 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:16 -0700 Subject: [PATCH 056/138] snic: add scsi host after determining max IOs. scsi host is added after negotiating the max number of IOs with Firmware. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_main.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c index 37ec507b7e67..396b32dca074 100644 --- a/drivers/scsi/snic/snic_main.c +++ b/drivers/scsi/snic/snic_main.c @@ -631,19 +631,6 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_free_tmreq_pool; } - /* - * Initialization done with PCI system, hardware, firmware. - * Add shost to SCSI - */ - ret = snic_add_host(shost, pdev); - if (ret) { - SNIC_HOST_ERR(shost, - "Adding scsi host Failed ... exiting. %d\n", - ret); - - goto err_notify_unset; - } - spin_lock_irqsave(&snic_glob->snic_list_lock, flags); list_add_tail(&snic->list, &snic_glob->snic_list); spin_unlock_irqrestore(&snic_glob->snic_list_lock, flags); @@ -676,8 +663,6 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) for (i = 0; i < snic->intr_count; i++) svnic_intr_unmask(&snic->intr[i]); - snic_set_state(snic, SNIC_ONLINE); - /* Get snic params */ ret = snic_get_conf(snic); if (ret) { @@ -688,6 +673,21 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_get_conf; } + /* + * Initialization done with PCI system, hardware, firmware. + * Add shost to SCSI + */ + ret = snic_add_host(shost, pdev); + if (ret) { + SNIC_HOST_ERR(shost, + "Adding scsi host Failed ... exiting. %d\n", + ret); + + goto err_get_conf; + } + + snic_set_state(snic, SNIC_ONLINE); + ret = snic_disc_start(snic); if (ret) { SNIC_HOST_ERR(shost, "snic_probe:Discovery Failed w err = %d\n", @@ -712,6 +712,8 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) svnic_dev_disable(snic->vdev); err_vdev_enable: + svnic_dev_notify_unset(snic->vdev); + for (i = 0; i < snic->wq_count; i++) { int rc = 0; @@ -725,9 +727,6 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } snic_del_host(snic->shost); -err_notify_unset: - svnic_dev_notify_unset(snic->vdev); - err_free_tmreq_pool: mempool_destroy(snic->req_pool[SNIC_REQ_TM_CACHE]); From f05795d3d771f30a7bdc3a138bf714b06d42aa95 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Tue, 5 Apr 2016 11:50:44 +0200 Subject: [PATCH 057/138] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state Add intermediate STARGET_REMOVE state to scsi_target_state to avoid running into the BUG_ON() in scsi_target_reap(). The STARGET_REMOVE state is only valid in the path from scsi_remove_target() to scsi_target_destroy() indicating this target is going to be removed. This re-fixes the problem introduced in commits bc3f02a795d3 ("[SCSI] scsi_remove_target: fix softlockup regression on hot remove") and 40998193560d ("scsi: restart list search after unlock in scsi_remove_target") in a more comprehensive way. [mkp: Included James' fix for scsi_target_destroy()] Signed-off-by: Johannes Thumshirn Fixes: 40998193560dab6c3ce8d25f4fa58a23e252ef38 Cc: stable@vger.kernel.org Reported-by: Sergey Senozhatsky Tested-by: Sergey Senozhatsky Reviewed-by: Ewan D. Milne Reviewed-by: Hannes Reinecke Reviewed-by: James Bottomley Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_scan.c | 1 + drivers/scsi/scsi_sysfs.c | 2 ++ include/scsi/scsi_device.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 6c8ad36560d1..e0a78f53d809 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -319,6 +319,7 @@ static void scsi_target_destroy(struct scsi_target *starget) struct Scsi_Host *shost = dev_to_shost(dev->parent); unsigned long flags; + BUG_ON(starget->state == STARGET_DEL); starget->state = STARGET_DEL; transport_destroy_device(dev); spin_lock_irqsave(shost->host_lock, flags); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b36544162f2f..f7da8a9d40b6 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1374,11 +1374,13 @@ void scsi_remove_target(struct device *dev) spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state == STARGET_DEL || + starget->state == STARGET_REMOVE || starget == last_target) continue; if (starget->dev.parent == dev || &starget->dev == dev) { kref_get(&starget->reap_ref); last_target = starget; + starget->state = STARGET_REMOVE; spin_unlock_irqrestore(shost->host_lock, flags); __scsi_remove_target(starget); scsi_target_reap(starget); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 1d4a3297559e..7d85de855160 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -248,6 +248,7 @@ scmd_printk(const char *, const struct scsi_cmnd *, const char *, ...); enum scsi_target_state { STARGET_CREATED = 1, STARGET_RUNNING, + STARGET_REMOVE, STARGET_DEL, }; From 305c2e71b3d733ec065cb716c76af7d554bd5571 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Tue, 5 Apr 2016 11:50:45 +0200 Subject: [PATCH 058/138] Revert "scsi: fix soft lockup in scsi_remove_target() on module removal" Now that we've done a more comprehensive fix with the intermediate target state we can remove the previous hack introduced with commit 90a88d6ef88e ("scsi: fix soft lockup in scsi_remove_target() on module removal"). Signed-off-by: Johannes Thumshirn Cc: stable@vger.kernel.org Reviewed-by: Ewan D. Milne Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_sysfs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index f7da8a9d40b6..07349270535d 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1367,19 +1367,17 @@ static void __scsi_remove_target(struct scsi_target *starget) void scsi_remove_target(struct device *dev) { struct Scsi_Host *shost = dev_to_shost(dev->parent); - struct scsi_target *starget, *last_target = NULL; + struct scsi_target *starget; unsigned long flags; restart: spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state == STARGET_DEL || - starget->state == STARGET_REMOVE || - starget == last_target) + starget->state == STARGET_REMOVE) continue; if (starget->dev.parent == dev || &starget->dev == dev) { kref_get(&starget->reap_ref); - last_target = starget; starget->state = STARGET_REMOVE; spin_unlock_irqrestore(shost->host_lock, flags); __scsi_remove_target(starget); From e4c36ad756ec2de36b05c66bb50ed4ff47b0fdb0 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 1 Apr 2016 08:57:37 +0200 Subject: [PATCH 059/138] scsi: vpd pages are mandatory for SPC-2 VPD pages 0x0 and 0x83 are mandatory even for SPC-2, so we should be lowering the restriction to avoid having to whitelist every SPC-2 compliant device. Signed-off-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- include/scsi/scsi_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 7d85de855160..a6c346df290d 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -542,9 +542,9 @@ static inline int scsi_device_supports_vpd(struct scsi_device *sdev) /* * Although VPD inquiries can go to SCSI-2 type devices, * some USB ones crash on receiving them, and the pages - * we currently ask for are for SPC-3 and beyond + * we currently ask for are mandatory for SPC-2 and beyond */ - if (sdev->scsi_level > SCSI_SPC_2 && !sdev->skip_vpd_pages) + if (sdev->scsi_level >= SCSI_SPC_2 && !sdev->skip_vpd_pages) return 1; return 0; } From 10755d3f47a9b28639f2e3d29a09ff2a0969657d Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Thu, 7 Apr 2016 09:07:56 -0400 Subject: [PATCH 060/138] bnx2fc: Add driver tunables. Per customer request, add the following driver tunables: o devloss_tmo o max_luns o queue_depth o tm_timeout tm_timeout is set per scsi_host in /sys/class/scsi_host/hostX/tm_timeout. Signed-off-by: Joe Carnuccio Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc.h | 1 + drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 79 ++++++++++++++++++++++++++++++- drivers/scsi/bnx2fc/bnx2fc_io.c | 2 +- 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 499e369eabf0..106788f304d6 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -261,6 +261,7 @@ struct bnx2fc_interface { u8 vlan_enabled; int vlan_id; bool enabled; + u8 tm_timeout; }; #define bnx2fc_from_ctlr(x) \ diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index d7029ea5d319..b0305b0fd21c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -107,6 +107,21 @@ MODULE_PARM_DESC(debug_logging, "\t\t0x10 - fcoe L2 fame related logs.\n" "\t\t0xff - LOG all messages."); +uint bnx2fc_devloss_tmo; +module_param_named(devloss_tmo, bnx2fc_devloss_tmo, uint, S_IRUGO); +MODULE_PARM_DESC(devloss_tmo, " Change devloss_tmo for the remote ports " + "attached via bnx2fc."); + +uint bnx2fc_max_luns = BNX2FC_MAX_LUN; +module_param_named(max_luns, bnx2fc_max_luns, uint, S_IRUGO); +MODULE_PARM_DESC(max_luns, " Change the default max_lun per SCSI host. Default " + "0xffff."); + +uint bnx2fc_queue_depth; +module_param_named(queue_depth, bnx2fc_queue_depth, uint, S_IRUGO); +MODULE_PARM_DESC(queue_depth, " Change the default queue depth of SCSI devices " + "attached via bnx2fc."); + static int bnx2fc_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu); /* notification function for CPU hotplug events */ @@ -692,7 +707,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev) int rc = 0; shost->max_cmd_len = BNX2FC_MAX_CMD_LEN; - shost->max_lun = BNX2FC_MAX_LUN; + shost->max_lun = bnx2fc_max_luns; shost->max_id = BNX2FC_MAX_FCP_TGT; shost->max_channel = 0; if (lport->vport) @@ -1102,6 +1117,9 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled) return -EIO; } + if (bnx2fc_devloss_tmo) + fc_host_dev_loss_tmo(vn_port->host) = bnx2fc_devloss_tmo; + if (disabled) { fc_vport_set_state(vport, FC_VPORT_DISABLED); } else { @@ -1495,6 +1513,9 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, } fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN; + if (bnx2fc_devloss_tmo) + fc_host_dev_loss_tmo(shost) = bnx2fc_devloss_tmo; + /* Allocate exchange manager */ if (!npiv) rc = bnx2fc_em_config(lport, hba); @@ -2293,6 +2314,7 @@ static int _bnx2fc_create(struct net_device *netdev, ctlr = bnx2fc_to_ctlr(interface); cdev = fcoe_ctlr_to_ctlr_dev(ctlr); interface->vlan_id = vlan_id; + interface->tm_timeout = BNX2FC_TM_TIMEOUT; interface->timer_work_queue = create_singlethread_workqueue("bnx2fc_timer_wq"); @@ -2612,6 +2634,15 @@ static int bnx2fc_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } +static int bnx2fc_slave_configure(struct scsi_device *sdev) +{ + if (!bnx2fc_queue_depth) + return 0; + + scsi_change_queue_depth(sdev, bnx2fc_queue_depth); + return 0; +} + /** * bnx2fc_mod_init - module init entry point * @@ -2858,6 +2889,50 @@ static struct fc_function_template bnx2fc_vport_xport_function = { .bsg_request = fc_lport_bsg_request, }; +/* + * Additional scsi_host attributes. + */ +static ssize_t +bnx2fc_tm_timeout_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct fc_lport *lport = shost_priv(shost); + struct fcoe_port *port = lport_priv(lport); + struct bnx2fc_interface *interface = port->priv; + + sprintf(buf, "%u\n", interface->tm_timeout); + return strlen(buf); +} + +static ssize_t +bnx2fc_tm_timeout_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct fc_lport *lport = shost_priv(shost); + struct fcoe_port *port = lport_priv(lport); + struct bnx2fc_interface *interface = port->priv; + int rval, val; + + rval = kstrtouint(buf, 10, &val); + if (rval) + return rval; + if (val > 255) + return -ERANGE; + + interface->tm_timeout = (u8)val; + return strlen(buf); +} + +static DEVICE_ATTR(tm_timeout, S_IRUGO|S_IWUSR, bnx2fc_tm_timeout_show, + bnx2fc_tm_timeout_store); + +static struct device_attribute *bnx2fc_host_attrs[] = { + &dev_attr_tm_timeout, + NULL, +}; + /** * scsi_host_template structure used while registering with SCSI-ml */ @@ -2877,6 +2952,8 @@ static struct scsi_host_template bnx2fc_shost_template = { .sg_tablesize = BNX2FC_MAX_BDS_PER_CMD, .max_sectors = 1024, .track_queue_depth = 1, + .slave_configure = bnx2fc_slave_configure, + .shost_attrs = bnx2fc_host_attrs, }; static struct libfc_function_template bnx2fc_libfc_fcn_templ = { diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 2230dab67ca5..562175869d0f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -770,7 +770,7 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags) spin_unlock_bh(&tgt->tgt_lock); rc = wait_for_completion_timeout(&io_req->tm_done, - BNX2FC_TM_TIMEOUT * HZ); + interface->tm_timeout * HZ); spin_lock_bh(&tgt->tgt_lock); io_req->wait_for_comp = 0; From 3f12f76ee83b3388d2e6f97a9e8c4c642656e277 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Thu, 7 Apr 2016 09:07:57 -0400 Subject: [PATCH 061/138] bnx2fc: Print when we send a fip keep alive. Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index b0305b0fd21c..365101a1598f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -122,6 +122,11 @@ module_param_named(queue_depth, bnx2fc_queue_depth, uint, S_IRUGO); MODULE_PARM_DESC(queue_depth, " Change the default queue depth of SCSI devices " "attached via bnx2fc."); +uint bnx2fc_log_fka; +module_param_named(log_fka, bnx2fc_log_fka, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(log_fka, " Print message to kernel log when fcoe is " + "initiating a FIP keep alive when debug logging is enabled."); + static int bnx2fc_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu); /* notification function for CPU hotplug events */ @@ -1076,6 +1081,20 @@ static u8 *bnx2fc_get_src_mac(struct fc_lport *lport) */ static void bnx2fc_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) { + struct fip_header *fiph; + struct ethhdr *eth_hdr; + u16 op; + u8 sub; + + fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2); + eth_hdr = (struct ethhdr *)skb_mac_header(skb); + op = ntohs(fiph->fip_op); + sub = fiph->fip_subcode; + + if (op == FIP_OP_CTRL && sub == FIP_SC_SOL && bnx2fc_log_fka) + BNX2FC_MISC_DBG("Sending FKA from %pM to %pM.\n", + eth_hdr->h_source, eth_hdr->h_dest); + skb->dev = bnx2fc_from_ctlr(fip)->netdev; dev_queue_xmit(skb); } From f72464d128efd22301ce58b204f3f1808013a536 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Thu, 7 Apr 2016 09:07:58 -0400 Subject: [PATCH 062/138] bnx2fc: Print netdev device name when FCoE is successfully initialized. Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 365101a1598f..a1881993982c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -2039,6 +2039,8 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev) return; } + pr_info(PFX "FCoE initialized for %s.\n", dev->netdev->name); + /* Add HBA to the adapter list */ mutex_lock(&bnx2fc_dev_lock); list_add_tail(&hba->list, &adapter_list); From d02327a863168647b9e6fde610c4730ff4837f9e Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Thu, 7 Apr 2016 09:07:59 -0400 Subject: [PATCH 063/138] bnx2fc: Check sc_cmd device and host pointer before returning the command to the mid-layer. When we are in connection recovery and the internal command timer on a request pops, either the scsi_cmnd->device or scsi_cmnd->device->host back pointers may be NULL as the device that the command that the request was submitted on may have been subsequently reaped due to the connection recovery. This can cause one or both of the pointers above to be NULL and cause a system crash if we try to return the command to the midlayer. Instead, double check the pointers before the return to the midlayer so as to prevent the crash and let the upper layers finish the session recovery and rediscover the device. Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_io.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 562175869d0f..026f394a3851 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -179,12 +179,24 @@ static void bnx2fc_scsi_done(struct bnx2fc_cmd *io_req, int err_code) bnx2fc_unmap_sg_list(io_req); io_req->sc_cmd = NULL; + + /* Sanity checks before returning command to mid-layer */ if (!sc_cmd) { printk(KERN_ERR PFX "scsi_done - sc_cmd NULL. " "IO(0x%x) already cleaned up\n", io_req->xid); return; } + if (!sc_cmd->device) { + pr_err(PFX "0x%x: sc_cmd->device is NULL.\n", io_req->xid); + return; + } + if (!sc_cmd->device->host) { + pr_err(PFX "0x%x: sc_cmd->device->host is NULL.\n", + io_req->xid); + return; + } + sc_cmd->result = err_code << 16; BNX2FC_IO_DBG(io_req, "sc=%p, result=0x%x, retries=%d, allowed=%d\n", From 63f21677965ab5b888ca15be872fce294c6802d7 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Thu, 7 Apr 2016 09:08:00 -0400 Subject: [PATCH 064/138] bnx2fc: Update version number to 2.10.3. Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 106788f304d6..fdd4eb4e41b2 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -65,7 +65,7 @@ #include "bnx2fc_constants.h" #define BNX2FC_NAME "bnx2fc" -#define BNX2FC_VERSION "2.9.6" +#define BNX2FC_VERSION "2.10.3" #define PFX "bnx2fc: " From 7517b26c65eb4866ec9a02e9cc2b416c94326313 Mon Sep 17 00:00:00 2001 From: Leonid Moiseichuk Date: Thu, 7 Apr 2016 21:52:25 +0300 Subject: [PATCH 065/138] mvsas: Generalize Marvell 9485 in pci_device_id Claim Marvell 9485 controllers regardless of subdevice ID. Tested on ASUS P9A-I/C2550/SAS/4L which uses vendor-specific 1043:8635. [mkp: Tweaked commit message] Signed-off-by: Leonid Moiseichuk Reviewed-by: Andy Shevchenko Signed-off-by: Martin K. Petersen --- drivers/scsi/mvsas/mv_init.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index c7c250519c4b..8280046fd1f0 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -704,24 +704,7 @@ static struct pci_device_id mvs_pci_table[] = { .class_mask = 0, .driver_data = chip_9445, }, - { - .vendor = PCI_VENDOR_ID_MARVELL_EXT, - .device = 0x9485, - .subvendor = PCI_ANY_ID, - .subdevice = 0x9480, - .class = 0, - .class_mask = 0, - .driver_data = chip_9485, - }, - { - .vendor = PCI_VENDOR_ID_MARVELL_EXT, - .device = 0x9485, - .subvendor = PCI_ANY_ID, - .subdevice = 0x9485, - .class = 0, - .class_mask = 0, - .driver_data = chip_9485, - }, + { PCI_VDEVICE(MARVELL_EXT, 0x9485), chip_9485 }, /* Marvell 9480/9485 (any vendor/model) */ { PCI_VDEVICE(OCZ, 0x1021), chip_9485}, /* OCZ RevoDrive3 */ { PCI_VDEVICE(OCZ, 0x1022), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ { PCI_VDEVICE(OCZ, 0x1040), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ From 98be565f1c19747bfc463f668310ff89beb28696 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 8 Apr 2016 08:14:54 +0200 Subject: [PATCH 066/138] zfcp: Revert to original scanning behaviour zfcp has its own mechanism for selective scanning, so revert to the original scanning behaviour to not confuse users. Fixes: 4e91e876e9b8b6eb4255aa0d690778a89d3f1d28 Suggested-by: Benjamin Block Signed-off-by: Hannes Reinecke Reviewed-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_unit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 08bba7ce7cef..9310a547b89f 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -27,7 +27,7 @@ void zfcp_unit_scsi_scan(struct zfcp_unit *unit) if (rport && rport->port_state == FC_PORTSTATE_ONLINE) scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, - SCSI_SCAN_RESCAN); + SCSI_SCAN_MANUAL); } static void zfcp_unit_scsi_scan_work(struct work_struct *work) From 91dbc08d64fba7c1426a32be4c57ebb63c4be124 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:07 -0700 Subject: [PATCH 067/138] scsi: replace "scsi_data_buffer" with "sg_table" in SG functions Replace parameter "struct scsi_data_buffer" with "struct sg_table" in SG alloc/free functions to make them generic. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8106515d1df8..4229c183648b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -583,14 +583,14 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq) +static void scsi_free_sgtable(struct sg_table *table, bool mq) { - if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (mq && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); } -static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) +static int scsi_alloc_sgtable(struct sg_table *table, int nents, bool mq) { struct scatterlist *first_chunk = NULL; int ret; @@ -599,17 +599,17 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) if (mq) { if (nents <= SCSI_MAX_SG_SEGMENTS) { - sdb->table.nents = sdb->table.orig_nents = nents; - sg_init_table(sdb->table.sgl, nents); + table->nents = table->orig_nents = nents; + sg_init_table(table->sgl, nents); return 0; } - first_chunk = sdb->table.sgl; + first_chunk = table->sgl; } - ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, + ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, first_chunk, GFP_ATOMIC, scsi_sg_alloc); if (unlikely(ret)) - scsi_free_sgtable(sdb, mq); + scsi_free_sgtable(table, mq); return ret; } @@ -625,12 +625,17 @@ static void scsi_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) { + struct scsi_data_buffer *sdb; + if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb, true); - if (cmd->request->next_rq && cmd->request->next_rq->special) - scsi_free_sgtable(cmd->request->next_rq->special, true); + scsi_free_sgtable(&cmd->sdb.table, true); + if (cmd->request->next_rq) { + sdb = cmd->request->next_rq->special; + if (sdb) + scsi_free_sgtable(&sdb->table, true); + } if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb, true); + scsi_free_sgtable(&cmd->prot_sdb->table, true); } static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) @@ -669,19 +674,19 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb, false); + scsi_free_sgtable(&cmd->sdb.table, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb, false); + scsi_free_sgtable(&cmd->prot_sdb->table, false); } static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(bidi_sdb, false); + scsi_free_sgtable(&bidi_sdb->table, false); kmem_cache_free(scsi_sdb_cache, bidi_sdb); cmd->request->next_rq->special = NULL; } @@ -1085,7 +1090,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) /* * If sg table allocation fails, requeue request later. */ - if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments, + if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, req->mq_ctx != NULL))) return BLKPREP_DEFER; @@ -1158,7 +1163,7 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(prot_sdb, ivecs, is_mq)) { + if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, is_mq)) { error = BLKPREP_DEFER; goto err_exit; } From 22cc3d4c6f4c529f4bf17445c60893b13e7611fb Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:08 -0700 Subject: [PATCH 068/138] scsi: replace "mq" with "first_chunk" in SG functions Parameter "bool mq" is block driver specific. Change it to "first_chunk" to make it more generic. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4229c183648b..9675353770e9 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -583,33 +583,32 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct sg_table *table, bool mq) +static void scsi_free_sgtable(struct sg_table *table, bool first_chunk) { - if (mq && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, scsi_sg_free); } -static int scsi_alloc_sgtable(struct sg_table *table, int nents, bool mq) +static int scsi_alloc_sgtable(struct sg_table *table, int nents, + struct scatterlist *first_chunk) { - struct scatterlist *first_chunk = NULL; int ret; BUG_ON(!nents); - if (mq) { + if (first_chunk) { if (nents <= SCSI_MAX_SG_SEGMENTS) { table->nents = table->orig_nents = nents; sg_init_table(table->sgl, nents); return 0; } - first_chunk = table->sgl; } ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, first_chunk, GFP_ATOMIC, scsi_sg_alloc); if (unlikely(ret)) - scsi_free_sgtable(table, mq); + scsi_free_sgtable(table, (bool)first_chunk); return ret; } @@ -1091,7 +1090,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) * If sg table allocation fails, requeue request later. */ if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, - req->mq_ctx != NULL))) + sdb->table.sgl))) return BLKPREP_DEFER; /* @@ -1163,7 +1162,8 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, is_mq)) { + if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, + prot_sdb->table.sgl)) { error = BLKPREP_DEFER; goto err_exit; } From 001d63be61c3b5a0413a46bacafbfc60c353951a Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:09 -0700 Subject: [PATCH 069/138] scsi: rename SG related struct and functions Rename SCSI specific struct and functions to more genenic names. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9675353770e9..08134f621450 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -40,10 +40,10 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools) +#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) #define SG_MEMPOOL_SIZE 2 -struct scsi_host_sg_pool { +struct sg_pool { size_t size; char *name; struct kmem_cache *slab; @@ -54,7 +54,7 @@ struct scsi_host_sg_pool { #if (SCSI_MAX_SG_SEGMENTS < 32) #error SCSI_MAX_SG_SEGMENTS is too small (must be 32 or greater) #endif -static struct scsi_host_sg_pool scsi_sg_pools[] = { +static struct sg_pool sg_pools[] = { SP(8), SP(16), #if (SCSI_MAX_SG_SEGMENTS > 32) @@ -553,7 +553,7 @@ void scsi_run_host_queues(struct Scsi_Host *shost) scsi_run_queue(sdev->request_queue); } -static inline unsigned int scsi_sgtable_index(unsigned short nents) +static inline unsigned int sg_pool_index(unsigned short nents) { unsigned int index; @@ -567,30 +567,30 @@ static inline unsigned int scsi_sgtable_index(unsigned short nents) return index; } -static void scsi_sg_free(struct scatterlist *sgl, unsigned int nents) +static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) { - struct scsi_host_sg_pool *sgp; + struct sg_pool *sgp; - sgp = scsi_sg_pools + scsi_sgtable_index(nents); + sgp = sg_pools + sg_pool_index(nents); mempool_free(sgl, sgp->pool); } -static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) +static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) { - struct scsi_host_sg_pool *sgp; + struct sg_pool *sgp; - sgp = scsi_sg_pools + scsi_sgtable_index(nents); + sgp = sg_pools + sg_pool_index(nents); return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct sg_table *table, bool first_chunk) +static void sg_free_table_chained(struct sg_table *table, bool first_chunk) { if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, sg_pool_free); } -static int scsi_alloc_sgtable(struct sg_table *table, int nents, +static int sg_alloc_table_chained(struct sg_table *table, int nents, struct scatterlist *first_chunk) { int ret; @@ -606,9 +606,9 @@ static int scsi_alloc_sgtable(struct sg_table *table, int nents, } ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, - first_chunk, GFP_ATOMIC, scsi_sg_alloc); + first_chunk, GFP_ATOMIC, sg_pool_alloc); if (unlikely(ret)) - scsi_free_sgtable(table, (bool)first_chunk); + sg_free_table_chained(table, (bool)first_chunk); return ret; } @@ -627,14 +627,14 @@ static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) struct scsi_data_buffer *sdb; if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb.table, true); + sg_free_table_chained(&cmd->sdb.table, true); if (cmd->request->next_rq) { sdb = cmd->request->next_rq->special; if (sdb) - scsi_free_sgtable(&sdb->table, true); + sg_free_table_chained(&sdb->table, true); } if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(&cmd->prot_sdb->table, true); + sg_free_table_chained(&cmd->prot_sdb->table, true); } static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) @@ -673,19 +673,19 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb.table, false); + sg_free_table_chained(&cmd->sdb.table, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(&cmd->prot_sdb->table, false); + sg_free_table_chained(&cmd->prot_sdb->table, false); } static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(&bidi_sdb->table, false); + sg_free_table_chained(&bidi_sdb->table, false); kmem_cache_free(scsi_sdb_cache, bidi_sdb); cmd->request->next_rq->special = NULL; } @@ -1089,7 +1089,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) /* * If sg table allocation fails, requeue request later. */ - if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, + if (unlikely(sg_alloc_table_chained(&sdb->table, req->nr_phys_segments, sdb->table.sgl))) return BLKPREP_DEFER; @@ -1162,7 +1162,7 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, + if (sg_alloc_table_chained(&prot_sdb->table, ivecs, prot_sdb->table.sgl)) { error = BLKPREP_DEFER; goto err_exit; @@ -2280,7 +2280,7 @@ int __init scsi_init_queue(void) } for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; + struct sg_pool *sgp = sg_pools + i; int size = sgp->size * sizeof(struct scatterlist); sgp->slab = kmem_cache_create(sgp->name, size, 0, @@ -2304,7 +2304,7 @@ int __init scsi_init_queue(void) cleanup_sdb: for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; + struct sg_pool *sgp = sg_pools + i; if (sgp->pool) mempool_destroy(sgp->pool); if (sgp->slab) @@ -2322,7 +2322,7 @@ void scsi_exit_queue(void) kmem_cache_destroy(scsi_sdb_cache); for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; + struct sg_pool *sgp = sg_pools + i; mempool_destroy(sgp->pool); kmem_cache_destroy(sgp->slab); } From 65e8617fba17732b4c68d3369a621725838b6f28 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:10 -0700 Subject: [PATCH 070/138] scsi: rename SCSI_MAX_{SG, SG_CHAIN}_SEGMENTS Rename SCSI_MAX_SG_SEGMENTS to SG_CHUNK_SIZE, which means the amount we fit into a single scatterlist chunk. Rename SCSI_MAX_SG_CHAIN_SEGMENTS to SG_MAX_SEGMENTS. Will move these 2 generic definitions to scatterlist.h later. Reviewed-by: Christoph Hellwig Acked-by: Bart Van Assche (for ib_srp changes) Signed-off-by: Ming Lin Acked-by: Tejun Heo Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/ata/pata_icside.c | 2 +- drivers/infiniband/ulp/srp/ib_srp.c | 4 ++-- drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/eesox.c | 2 +- drivers/scsi/arm/powertec.c | 2 +- drivers/scsi/esas2r/esas2r_main.c | 4 ++-- drivers/scsi/hisi_sas/hisi_sas.h | 2 +- drivers/scsi/mpt3sas/mpt3sas_base.c | 4 ++-- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- drivers/scsi/scsi_debug.c | 2 +- drivers/scsi/scsi_lib.c | 34 ++++++++++++++--------------- drivers/usb/storage/scsiglue.c | 2 +- include/scsi/scsi.h | 8 +++---- include/scsi/scsi_host.h | 2 +- 14 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index d7c732042a4f..188f2f2eb21f 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -294,7 +294,7 @@ static int icside_dma_init(struct pata_icside_info *info) static struct scsi_host_template pata_icside_sht = { ATA_BASE_SHT(DRV_NAME), - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, }; diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index ff21597aa54d..369a75e1f44e 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -81,7 +81,7 @@ MODULE_PARM_DESC(cmd_sg_entries, module_param(indirect_sg_entries, uint, 0444); MODULE_PARM_DESC(indirect_sg_entries, - "Default max number of gather/scatter entries (default is 12, max is " __stringify(SCSI_MAX_SG_CHAIN_SEGMENTS) ")"); + "Default max number of gather/scatter entries (default is 12, max is " __stringify(SG_MAX_SEGMENTS) ")"); module_param(allow_ext_sg, bool, 0444); MODULE_PARM_DESC(allow_ext_sg, @@ -3097,7 +3097,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) case SRP_OPT_SG_TABLESIZE: if (match_int(args, &token) || token < 1 || - token > SCSI_MAX_SG_CHAIN_SEGMENTS) { + token > SG_MAX_SEGMENTS) { pr_warn("bad max sg_tablesize parameter '%s'\n", p); goto out; diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index faa1bee07c8a..edce5f3cfdba 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -365,7 +365,7 @@ static struct scsi_host_template cumanascsi2_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id = 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .use_clustering = DISABLE_CLUSTERING, .proc_name = "cumanascsi2", diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index a8ad6880dd91..e93e047f4316 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -484,7 +484,7 @@ static struct scsi_host_template eesox_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id = 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .use_clustering = DISABLE_CLUSTERING, .proc_name = "eesox", diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index 5e1b73e1b743..79aa88911b7f 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -291,7 +291,7 @@ static struct scsi_host_template powertecscsi_template = { .can_queue = 8, .this_id = 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 33581ba4386e..2aca4d16f39e 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -246,7 +246,7 @@ static struct scsi_host_template driver_template = { .eh_target_reset_handler = esas2r_target_reset, .can_queue = 128, .this_id = -1, - .sg_tablesize = SCSI_MAX_SG_SEGMENTS, + .sg_tablesize = SG_CHUNK_SIZE, .cmd_per_lun = ESAS2R_DEFAULT_CMD_PER_LUN, .present = 0, @@ -271,7 +271,7 @@ module_param(num_sg_lists, int, 0); MODULE_PARM_DESC(num_sg_lists, "Number of scatter/gather lists. Default 1024."); -int sg_tablesize = SCSI_MAX_SG_SEGMENTS; +int sg_tablesize = SG_CHUNK_SIZE; module_param(sg_tablesize, int, 0); MODULE_PARM_DESC(sg_tablesize, "Maximum number of entries in a scatter/gather table."); diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 29e89f340b64..fa12eeac140c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -298,7 +298,7 @@ struct hisi_sas_command_table_stp { u8 atapi_cdb[ATAPI_CDB_LEN]; }; -#define HISI_SAS_SGE_PAGE_CNT SCSI_MAX_SG_SEGMENTS +#define HISI_SAS_SGE_PAGE_CNT SG_CHUNK_SIZE struct hisi_sas_sge_page { struct hisi_sas_sge sge[HISI_SAS_SGE_PAGE_CNT]; }; diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 8c44b9c424af..28d85314b3c6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -3207,10 +3207,10 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) sg_tablesize = MPT_MIN_PHYS_SEGMENTS; else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) { sg_tablesize = min_t(unsigned short, sg_tablesize, - SCSI_MAX_SG_CHAIN_SEGMENTS); + SG_MAX_SEGMENTS); pr_warn(MPT3SAS_FMT "sg_tablesize(%u) is bigger than kernel" - " defined SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name, + " defined SG_CHUNK_SIZE(%u)\n", ioc->name, sg_tablesize, MPT_MAX_PHYS_SEGMENTS); } ioc->shost->sg_tablesize = sg_tablesize; diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 32580b514b18..6940c577053f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -90,7 +90,7 @@ /* * Set MPT3SAS_SG_DEPTH value based on user input. */ -#define MPT_MAX_PHYS_SEGMENTS SCSI_MAX_SG_SEGMENTS +#define MPT_MAX_PHYS_SEGMENTS SG_CHUNK_SIZE #define MPT_MIN_PHYS_SEGMENTS 16 #ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index f3d69a98c725..06b151711cdd 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -5305,7 +5305,7 @@ static struct scsi_host_template sdebug_driver_template = { .eh_host_reset_handler = scsi_debug_host_reset, .can_queue = SCSI_DEBUG_CANQUEUE, .this_id = 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .cmd_per_lun = DEF_CMD_PER_LUN, .max_sectors = -1U, .use_clustering = DISABLE_CLUSTERING, diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 08134f621450..8f776f1e95ce 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -51,25 +51,25 @@ struct sg_pool { }; #define SP(x) { .size = x, "sgpool-" __stringify(x) } -#if (SCSI_MAX_SG_SEGMENTS < 32) -#error SCSI_MAX_SG_SEGMENTS is too small (must be 32 or greater) +#if (SG_CHUNK_SIZE < 32) +#error SG_CHUNK_SIZE is too small (must be 32 or greater) #endif static struct sg_pool sg_pools[] = { SP(8), SP(16), -#if (SCSI_MAX_SG_SEGMENTS > 32) +#if (SG_CHUNK_SIZE > 32) SP(32), -#if (SCSI_MAX_SG_SEGMENTS > 64) +#if (SG_CHUNK_SIZE > 64) SP(64), -#if (SCSI_MAX_SG_SEGMENTS > 128) +#if (SG_CHUNK_SIZE > 128) SP(128), -#if (SCSI_MAX_SG_SEGMENTS > 256) -#error SCSI_MAX_SG_SEGMENTS is too large (256 MAX) +#if (SG_CHUNK_SIZE > 256) +#error SG_CHUNK_SIZE is too large (256 MAX) #endif #endif #endif #endif - SP(SCSI_MAX_SG_SEGMENTS) + SP(SG_CHUNK_SIZE) }; #undef SP @@ -557,7 +557,7 @@ static inline unsigned int sg_pool_index(unsigned short nents) { unsigned int index; - BUG_ON(nents > SCSI_MAX_SG_SEGMENTS); + BUG_ON(nents > SG_CHUNK_SIZE); if (nents <= 8) index = 0; @@ -585,9 +585,9 @@ static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) static void sg_free_table_chained(struct sg_table *table, bool first_chunk) { - if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, sg_pool_free); + __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free); } static int sg_alloc_table_chained(struct sg_table *table, int nents, @@ -598,14 +598,14 @@ static int sg_alloc_table_chained(struct sg_table *table, int nents, BUG_ON(!nents); if (first_chunk) { - if (nents <= SCSI_MAX_SG_SEGMENTS) { + if (nents <= SG_CHUNK_SIZE) { table->nents = table->orig_nents = nents; sg_init_table(table->sgl, nents); return 0; } } - ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, + ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, first_chunk, GFP_ATOMIC, sg_pool_alloc); if (unlikely(ret)) sg_free_table_chained(table, (bool)first_chunk); @@ -1937,7 +1937,7 @@ static int scsi_mq_prep_fn(struct request *req) if (scsi_host_get_prot(shost)) { cmd->prot_sdb = (void *)sg + min_t(unsigned int, - shost->sg_tablesize, SCSI_MAX_SG_SEGMENTS) * + shost->sg_tablesize, SG_CHUNK_SIZE) * sizeof(struct scatterlist); memset(cmd->prot_sdb, 0, sizeof(struct scsi_data_buffer)); @@ -2110,7 +2110,7 @@ static void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q) * this limit is imposed by hardware restrictions */ blk_queue_max_segments(q, min_t(unsigned short, shost->sg_tablesize, - SCSI_MAX_SG_CHAIN_SEGMENTS)); + SG_MAX_SEGMENTS)); if (scsi_host_prot_dma(shost)) { shost->sg_prot_tablesize = @@ -2192,8 +2192,8 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost) unsigned int cmd_size, sgl_size, tbl_size; tbl_size = shost->sg_tablesize; - if (tbl_size > SCSI_MAX_SG_SEGMENTS) - tbl_size = SCSI_MAX_SG_SEGMENTS; + if (tbl_size > SG_CHUNK_SIZE) + tbl_size = SG_CHUNK_SIZE; sgl_size = tbl_size * sizeof(struct scatterlist); cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size + sgl_size; if (scsi_host_get_prot(shost)) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 90901861bfc0..ae85861051eb 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -563,7 +563,7 @@ static const struct scsi_host_template usb_stor_host_template = { .target_alloc = target_alloc, /* lots of sg segments can be handled */ - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, /* limit the total size of a transfer to 120 KB */ .max_sectors = 240, diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index e0a3398b1547..74dafa75bae7 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -24,16 +24,16 @@ enum scsi_timeouts { * to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The * minimum value is 32 */ -#define SCSI_MAX_SG_SEGMENTS 128 +#define SG_CHUNK_SIZE 128 /* - * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit + * Like SG_CHUNK_SIZE, but for archs that have sg chaining. This limit * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. */ #ifdef CONFIG_ARCH_HAS_SG_CHAIN -#define SCSI_MAX_SG_CHAIN_SEGMENTS 2048 +#define SG_MAX_SEGMENTS 2048 #else -#define SCSI_MAX_SG_CHAIN_SEGMENTS SCSI_MAX_SG_SEGMENTS +#define SG_MAX_SEGMENTS SG_CHUNK_SIZE #endif /* diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index fcfa3d7f5e7e..76e9d278c334 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -37,7 +37,7 @@ struct blk_queue_tags; * used in one scatter-gather request. */ #define SG_NONE 0 -#define SG_ALL SCSI_MAX_SG_SEGMENTS +#define SG_ALL SG_CHUNK_SIZE #define MODE_UNKNOWN 0x00 #define MODE_INITIATOR 0x01 From 9b1d6c8950021ab007608d455fc9c398ecd25476 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:11 -0700 Subject: [PATCH 071/138] lib: scatterlist: move SG pool code from SCSI driver to lib/sg_pool.c Now it's ready to move the mempool based SG chained allocator code from SCSI driver to lib/sg_pool.c, which will be compiled only based on a Kconfig symbol CONFIG_SG_POOL. SCSI selects CONFIG_SG_POOL. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 1 + drivers/scsi/scsi_lib.c | 137 ---------------------------- include/linux/scatterlist.h | 25 ++++++ include/scsi/scsi.h | 19 ---- lib/Kconfig | 7 ++ lib/Makefile | 1 + lib/sg_pool.c | 172 ++++++++++++++++++++++++++++++++++++ 7 files changed, 206 insertions(+), 156 deletions(-) create mode 100644 lib/sg_pool.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 0950567e6269..98e5d51a3346 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -17,6 +17,7 @@ config SCSI tristate "SCSI device support" depends on BLOCK select SCSI_DMA if HAS_DMA + select SG_POOL ---help--- If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or any other SCSI device under Linux, say Y and make sure that you know diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8f776f1e95ce..b920c5dabf60 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include #include @@ -40,39 +38,6 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) -#define SG_MEMPOOL_SIZE 2 - -struct sg_pool { - size_t size; - char *name; - struct kmem_cache *slab; - mempool_t *pool; -}; - -#define SP(x) { .size = x, "sgpool-" __stringify(x) } -#if (SG_CHUNK_SIZE < 32) -#error SG_CHUNK_SIZE is too small (must be 32 or greater) -#endif -static struct sg_pool sg_pools[] = { - SP(8), - SP(16), -#if (SG_CHUNK_SIZE > 32) - SP(32), -#if (SG_CHUNK_SIZE > 64) - SP(64), -#if (SG_CHUNK_SIZE > 128) - SP(128), -#if (SG_CHUNK_SIZE > 256) -#error SG_CHUNK_SIZE is too large (256 MAX) -#endif -#endif -#endif -#endif - SP(SG_CHUNK_SIZE) -}; -#undef SP - struct kmem_cache *scsi_sdb_cache; /* @@ -553,65 +518,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost) scsi_run_queue(sdev->request_queue); } -static inline unsigned int sg_pool_index(unsigned short nents) -{ - unsigned int index; - - BUG_ON(nents > SG_CHUNK_SIZE); - - if (nents <= 8) - index = 0; - else - index = get_count_order(nents) - 3; - - return index; -} - -static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) -{ - struct sg_pool *sgp; - - sgp = sg_pools + sg_pool_index(nents); - mempool_free(sgl, sgp->pool); -} - -static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) -{ - struct sg_pool *sgp; - - sgp = sg_pools + sg_pool_index(nents); - return mempool_alloc(sgp->pool, gfp_mask); -} - -static void sg_free_table_chained(struct sg_table *table, bool first_chunk) -{ - if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) - return; - __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free); -} - -static int sg_alloc_table_chained(struct sg_table *table, int nents, - struct scatterlist *first_chunk) -{ - int ret; - - BUG_ON(!nents); - - if (first_chunk) { - if (nents <= SG_CHUNK_SIZE) { - table->nents = table->orig_nents = nents; - sg_init_table(table->sgl, nents); - return 0; - } - } - - ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, - first_chunk, GFP_ATOMIC, sg_pool_alloc); - if (unlikely(ret)) - sg_free_table_chained(table, (bool)first_chunk); - return ret; -} - static void scsi_uninit_cmd(struct scsi_cmnd *cmd) { if (cmd->request->cmd_type == REQ_TYPE_FS) { @@ -2269,8 +2175,6 @@ EXPORT_SYMBOL(scsi_unblock_requests); int __init scsi_init_queue(void) { - int i; - scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", sizeof(struct scsi_data_buffer), 0, 0, NULL); @@ -2279,53 +2183,12 @@ int __init scsi_init_queue(void) return -ENOMEM; } - for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct sg_pool *sgp = sg_pools + i; - int size = sgp->size * sizeof(struct scatterlist); - - sgp->slab = kmem_cache_create(sgp->name, size, 0, - SLAB_HWCACHE_ALIGN, NULL); - if (!sgp->slab) { - printk(KERN_ERR "SCSI: can't init sg slab %s\n", - sgp->name); - goto cleanup_sdb; - } - - sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE, - sgp->slab); - if (!sgp->pool) { - printk(KERN_ERR "SCSI: can't init sg mempool %s\n", - sgp->name); - goto cleanup_sdb; - } - } - return 0; - -cleanup_sdb: - for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct sg_pool *sgp = sg_pools + i; - if (sgp->pool) - mempool_destroy(sgp->pool); - if (sgp->slab) - kmem_cache_destroy(sgp->slab); - } - kmem_cache_destroy(scsi_sdb_cache); - - return -ENOMEM; } void scsi_exit_queue(void) { - int i; - kmem_cache_destroy(scsi_sdb_cache); - - for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct sg_pool *sgp = sg_pools + i; - mempool_destroy(sgp->pool); - kmem_cache_destroy(sgp->slab); - } } /** diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 556ec1ea2574..cb3c8fe6acd7 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -285,6 +285,31 @@ size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, */ #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) +/* + * The maximum number of SG segments that we will put inside a + * scatterlist (unless chaining is used). Should ideally fit inside a + * single page, to avoid a higher order allocation. We could define this + * to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The + * minimum value is 32 + */ +#define SG_CHUNK_SIZE 128 + +/* + * Like SG_CHUNK_SIZE, but for archs that have sg chaining. This limit + * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. + */ +#ifdef CONFIG_ARCH_HAS_SG_CHAIN +#define SG_MAX_SEGMENTS 2048 +#else +#define SG_MAX_SEGMENTS SG_CHUNK_SIZE +#endif + +#ifdef CONFIG_SG_POOL +void sg_free_table_chained(struct sg_table *table, bool first_chunk); +int sg_alloc_table_chained(struct sg_table *table, int nents, + struct scatterlist *first_chunk); +#endif + /* * sg page iterator * diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 74dafa75bae7..8ec7c30e35af 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -17,25 +17,6 @@ enum scsi_timeouts { SCSI_DEFAULT_EH_TIMEOUT = 10 * HZ, }; -/* - * The maximum number of SG segments that we will put inside a - * scatterlist (unless chaining is used). Should ideally fit inside a - * single page, to avoid a higher order allocation. We could define this - * to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The - * minimum value is 32 - */ -#define SG_CHUNK_SIZE 128 - -/* - * Like SG_CHUNK_SIZE, but for archs that have sg chaining. This limit - * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. - */ -#ifdef CONFIG_ARCH_HAS_SG_CHAIN -#define SG_MAX_SEGMENTS 2048 -#else -#define SG_MAX_SEGMENTS SG_CHUNK_SIZE -#endif - /* * DIX-capable adapters effectively support infinite chaining for the * protection information scatterlist diff --git a/lib/Kconfig b/lib/Kconfig index 3cca1222578e..61d55bd0ed89 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -523,6 +523,13 @@ config SG_SPLIT a scatterlist. This should be selected by a driver or an API which whishes to split a scatterlist amongst multiple DMA channels. +config SG_POOL + def_bool n + help + Provides a helper to allocate chained scatterlists. This should be + selected by a driver or an API which whishes to allocate chained + scatterlist. + # # sg chaining option # diff --git a/lib/Makefile b/lib/Makefile index 7bd6fd436c97..bf01c2673423 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -178,6 +178,7 @@ obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o obj-$(CONFIG_SG_SPLIT) += sg_split.o +obj-$(CONFIG_SG_POOL) += sg_pool.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o obj-$(CONFIG_IRQ_POLL) += irq_poll.o diff --git a/lib/sg_pool.c b/lib/sg_pool.c new file mode 100644 index 000000000000..6dd30615a201 --- /dev/null +++ b/lib/sg_pool.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include + +#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) +#define SG_MEMPOOL_SIZE 2 + +struct sg_pool { + size_t size; + char *name; + struct kmem_cache *slab; + mempool_t *pool; +}; + +#define SP(x) { .size = x, "sgpool-" __stringify(x) } +#if (SG_CHUNK_SIZE < 32) +#error SG_CHUNK_SIZE is too small (must be 32 or greater) +#endif +static struct sg_pool sg_pools[] = { + SP(8), + SP(16), +#if (SG_CHUNK_SIZE > 32) + SP(32), +#if (SG_CHUNK_SIZE > 64) + SP(64), +#if (SG_CHUNK_SIZE > 128) + SP(128), +#if (SG_CHUNK_SIZE > 256) +#error SG_CHUNK_SIZE is too large (256 MAX) +#endif +#endif +#endif +#endif + SP(SG_CHUNK_SIZE) +}; +#undef SP + +static inline unsigned int sg_pool_index(unsigned short nents) +{ + unsigned int index; + + BUG_ON(nents > SG_CHUNK_SIZE); + + if (nents <= 8) + index = 0; + else + index = get_count_order(nents) - 3; + + return index; +} + +static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) +{ + struct sg_pool *sgp; + + sgp = sg_pools + sg_pool_index(nents); + mempool_free(sgl, sgp->pool); +} + +static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) +{ + struct sg_pool *sgp; + + sgp = sg_pools + sg_pool_index(nents); + return mempool_alloc(sgp->pool, gfp_mask); +} + +/** + * sg_free_table_chained - Free a previously mapped sg table + * @table: The sg table header to use + * @first_chunk: was first_chunk not NULL in sg_alloc_table_chained? + * + * Description: + * Free an sg table previously allocated and setup with + * sg_alloc_table_chained(). + * + **/ +void sg_free_table_chained(struct sg_table *table, bool first_chunk) +{ + if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) + return; + __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free); +} +EXPORT_SYMBOL_GPL(sg_free_table_chained); + +/** + * sg_alloc_table_chained - Allocate and chain SGLs in an sg table + * @table: The sg table header to use + * @nents: Number of entries in sg list + * @first_chunk: first SGL + * + * Description: + * Allocate and chain SGLs in an sg table. If @nents@ is larger than + * SG_CHUNK_SIZE a chained sg table will be setup. + * + **/ +int sg_alloc_table_chained(struct sg_table *table, int nents, + struct scatterlist *first_chunk) +{ + int ret; + + BUG_ON(!nents); + + if (first_chunk) { + if (nents <= SG_CHUNK_SIZE) { + table->nents = table->orig_nents = nents; + sg_init_table(table->sgl, nents); + return 0; + } + } + + ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, + first_chunk, GFP_ATOMIC, sg_pool_alloc); + if (unlikely(ret)) + sg_free_table_chained(table, (bool)first_chunk); + return ret; +} +EXPORT_SYMBOL_GPL(sg_alloc_table_chained); + +static __init int sg_pool_init(void) +{ + int i; + + for (i = 0; i < SG_MEMPOOL_NR; i++) { + struct sg_pool *sgp = sg_pools + i; + int size = sgp->size * sizeof(struct scatterlist); + + sgp->slab = kmem_cache_create(sgp->name, size, 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!sgp->slab) { + printk(KERN_ERR "SG_POOL: can't init sg slab %s\n", + sgp->name); + goto cleanup_sdb; + } + + sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE, + sgp->slab); + if (!sgp->pool) { + printk(KERN_ERR "SG_POOL: can't init sg mempool %s\n", + sgp->name); + goto cleanup_sdb; + } + } + + return 0; + +cleanup_sdb: + for (i = 0; i < SG_MEMPOOL_NR; i++) { + struct sg_pool *sgp = sg_pools + i; + if (sgp->pool) + mempool_destroy(sgp->pool); + if (sgp->slab) + kmem_cache_destroy(sgp->slab); + } + + return -ENOMEM; +} + +static __exit void sg_pool_exit(void) +{ + int i; + + for (i = 0; i < SG_MEMPOOL_NR; i++) { + struct sg_pool *sgp = sg_pools + i; + mempool_destroy(sgp->pool); + kmem_cache_destroy(sgp->slab); + } +} + +module_init(sg_pool_init); +module_exit(sg_pool_exit); From 7524926826104b9e0665eaecd50f76889b89a72e Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:11 +0800 Subject: [PATCH 072/138] hisi_sas: use device linkrate in MCR for v2 hw Contrary to the field name, the MCR (max connection rate) in the ITCT should hold the device linkrate (linkrate of the connected phy), and not the max linkrate. This fixes an issue seen where some SATA drives connected through an expander which would not attach. Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index b7337476454b..f462fc4adc3a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -544,7 +544,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, } qw0 |= ((1 << ITCT_HDR_VALID_OFF) | - (device->max_linkrate << ITCT_HDR_MCR_OFF) | + (device->linkrate << ITCT_HDR_MCR_OFF) | (1 << ITCT_HDR_VLN_OFF) | (port->id << ITCT_HDR_PORT_ID_OFF)); itct->qw0 = cpu_to_le64(qw0); From 3a429d5ab60966cf75d9b99648700823c514b7ad Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:12 +0800 Subject: [PATCH 073/138] hisi_sas: fix v2 hw multiple SATA disk issue Intermittently it is found that when multiple SATA disks are directly connected to the host that some disks are not detected. The problem is that all set bitfields in ENT_INT_SRC1 are cleared for all phys in sata_int_v2_hw() - it should clear the set bit for the phy being serviced. Also unnecessary double-write to ENT_INT_SRC1 and ENT_INT_SRC_MSK1 is removed (remaining writes are done at end label). Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index f462fc4adc3a..5a7f7092018a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2003,12 +2003,10 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk | 1 << phy_no); ent_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC1); - ent_tmp = ent_int; + ent_tmp = ent_int & (1 << (ENT_INT_SRC1_D2H_FIS_CH1_OFF * phy_no)); ent_int >>= ENT_INT_SRC1_D2H_FIS_CH1_OFF * (phy_no % 4); if ((ent_int & ENT_INT_SRC1_D2H_FIS_CH0_MSK) == 0) { dev_warn(dev, "sata int: phy%d did not receive FIS\n", phy_no); - hisi_sas_write32(hisi_hba, ENT_INT_SRC1, ent_tmp); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk); res = IRQ_NONE; goto end; } From 11826e5dc7b7297164dd9dd6d735c6ff6acb4b86 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:13 +0800 Subject: [PATCH 074/138] hisi_sas: add v2 hw support for >4 SATA phys This patch adds support for directly attaching SATA disks to phy 4-8. The problem was that only registers concerned with phy 0-3 were being considered in sata_int_v2_hw(). The issue was not detected previously as the development board only exposed phy 0-3; the new board provides access to 8 phys. Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 5a7f7092018a..cc083b9b1041 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1993,17 +1993,20 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) u32 ent_tmp, ent_msk, ent_int, port_id, link_rate, hard_phy_linkrate; irqreturn_t res = IRQ_HANDLED; u8 attached_sas_addr[SAS_ADDR_SIZE] = {0}; - int phy_no; + int phy_no, offset; phy_no = sas_phy->id; initial_fis = &hisi_hba->initial_fis[phy_no]; fis = &initial_fis->fis; - ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK1); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk | 1 << phy_no); + offset = 4 * (phy_no / 4); + ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK1 + offset); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset, + ent_msk | 1 << ((phy_no % 4) * 8)); - ent_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC1); - ent_tmp = ent_int & (1 << (ENT_INT_SRC1_D2H_FIS_CH1_OFF * phy_no)); + ent_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC1 + offset); + ent_tmp = ent_int & (1 << (ENT_INT_SRC1_D2H_FIS_CH1_OFF * + (phy_no % 4))); ent_int >>= ENT_INT_SRC1_D2H_FIS_CH1_OFF * (phy_no % 4); if ((ent_int & ENT_INT_SRC1_D2H_FIS_CH0_MSK) == 0) { dev_warn(dev, "sata int: phy%d did not receive FIS\n", phy_no); @@ -2054,8 +2057,8 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) queue_work(hisi_hba->wq, &phy->phyup_ws); end: - hisi_sas_write32(hisi_hba, ENT_INT_SRC1, ent_tmp); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk); + hisi_sas_write32(hisi_hba, ENT_INT_SRC1 + offset, ent_tmp); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset, ent_msk); return res; } From f76a0b49402b39b2d314ced52aac2f02d6a6c45d Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:14 +0800 Subject: [PATCH 075/138] hisi_sas: for v2 hw only set ITCT qw2 for SAS device This patch fixes the ITCT table setup as it should be configured differently for SAS and SATA devices. For SATA disks there is no need to set qw2 (already zeroed). Also, link parameters for Bus inactive limit, max connection time limit, and reject to open limit timers parameters are changed to match global config register, MAX_CON_TIME_LIMIT_TIME, as recommended by hw team. Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index cc083b9b1041..4276594a14c8 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -554,10 +554,11 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, itct->sas_addr = __swab64(itct->sas_addr); /* qw2 */ - itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_INLT_OFF) | - (0xff00ULL << ITCT_HDR_BITLT_OFF) | - (0xff00ULL << ITCT_HDR_MCTLT_OFF) | - (0xff00ULL << ITCT_HDR_RTOLT_OFF)); + if (!dev_is_sata(device)) + itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_INLT_OFF) | + (0x1ULL << ITCT_HDR_BITLT_OFF) | + (0x32ULL << ITCT_HDR_MCTLT_OFF) | + (0x1ULL << ITCT_HDR_RTOLT_OFF)); } static void free_device_v2_hw(struct hisi_hba *hisi_hba, @@ -715,7 +716,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL, 0x7FF); hisi_sas_write32(hisi_hba, OPENA_WT_CONTI_TIME, 0x1); hisi_sas_write32(hisi_hba, I_T_NEXUS_LOSS_TIME, 0x1F4); - hisi_sas_write32(hisi_hba, MAX_CON_TIME_LIMIT_TIME, 0x4E20); + hisi_sas_write32(hisi_hba, MAX_CON_TIME_LIMIT_TIME, 0x32); hisi_sas_write32(hisi_hba, BUS_INACTIVE_LIMIT_TIME, 0x1); hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1); hisi_sas_write32(hisi_hba, HGC_ERR_STAT_EN, 0x1); From 33e56e48ea3b3f58358d12b28f36474040325f0c Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:15 +0800 Subject: [PATCH 076/138] hisi_sas: update driver version to 1.4 Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index fa12eeac140c..0978016482c1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -23,7 +23,7 @@ #include #include -#define DRV_VERSION "v1.3" +#define DRV_VERSION "v1.4" #define HISI_SAS_MAX_PHYS 9 #define HISI_SAS_MAX_QUEUES 32 From 5ea33eb573c9858cdebfb69626cc8621c7468f9e Mon Sep 17 00:00:00 2001 From: Tina Ruchandani Date: Mon, 25 Jan 2016 23:00:20 +0100 Subject: [PATCH 077/138] qla2xxx: Remove use of 'struct timeval' struct register_host_info stores a 64-bit UTC system time timestamp. This patch removes the use of 'struct timeval' to obtain that timestamp as its tv_sec value will overflow on 32-bit systems in year 2038 beyond. The patch uses ktime_get_real_seconds() which returns a 64-bit seconds value. Signed-off-by: Tina Ruchandani Reviewed-by: Johannes Thumshirn Acked-by: Himanshu Madhani Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index b5029e543b91..15dff7099955 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -6,6 +6,7 @@ */ #include "qla_def.h" #include +#include #include #include #include @@ -1812,7 +1813,6 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) struct host_system_info *phost_info; struct register_host_info *preg_hsi; struct new_utsname *p_sysid = NULL; - struct timeval tv; sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) @@ -1886,8 +1886,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) p_sysid->domainname, DOMNAME_LENGTH); strncpy(phost_info->hostdriver, QLA2XXX_VERSION, VERSION_LENGTH); - do_gettimeofday(&tv); - preg_hsi->utc = (uint64_t)tv.tv_sec; + preg_hsi->utc = (uint64_t)ktime_get_real_seconds(); ql_dbg(ql_dbg_init, vha, 0x0149, "ISP%04X: Host registration with firmware\n", ha->pdev->device); From e83596b41cb9729837468a1c14de56a5529a2aa6 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 13 Apr 2016 14:26:56 -0700 Subject: [PATCH 078/138] pm80xx: Remove bogus address masking in pm8001_ioremap() It is unclear what the original intent of the masking was, but it is clearly incorrect to truncate a physical address before calling ioremap(). On systems where there are valid physical address bits above bit-31 (arm64 for example) the result is an eventual OOPs when initializing the driver. Remove the bogus code to fix it. Signed-off-by: David Daney Acked-by: Jack Wang Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 062ab34b86f8..6bd7bf4f4a81 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -418,8 +418,6 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha) if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { pm8001_ha->io_mem[logicalBar].membase = pci_resource_start(pdev, bar); - pm8001_ha->io_mem[logicalBar].membase &= - (u32)PCI_BASE_ADDRESS_MEM_MASK; pm8001_ha->io_mem[logicalBar].memsize = pci_resource_len(pdev, bar); pm8001_ha->io_mem[logicalBar].memvirtaddr = From 23409bd4a8b051e28d0106c7a83f362617452098 Mon Sep 17 00:00:00 2001 From: Tina Ruchandani Date: Wed, 13 Apr 2016 00:01:40 -0700 Subject: [PATCH 079/138] mpt3sas: Remove usage of 'struct timeval' 'struct timeval' will have its tv_sec value overflow on 32-bit systems in year 2038 and beyond. This patch replaces the use of struct timeval for computing mpi_request.TimeStamp, and instead uses ktime_t which provides 64-bit seconds value. The timestamp computed remains unaffected (milliseconds since Unix epoch). Signed-off-by: Tina Ruchandani Reviewed-by: Arnd Bergmann Reviewed-by: Johannes Thumshirn Acked-by: Sathya Prakash Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 28d85314b3c6..93d7c28f8162 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -4387,7 +4388,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) Mpi2IOCInitRequest_t mpi_request; Mpi2IOCInitReply_t mpi_reply; int i, r = 0; - struct timeval current_time; + ktime_t current_time; u16 ioc_status; u32 reply_post_free_array_sz = 0; Mpi2IOCInitRDPQArrayEntry *reply_post_free_array = NULL; @@ -4449,9 +4450,8 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) /* This time stamp specifies number of milliseconds * since epoch ~ midnight January 1, 1970. */ - do_gettimeofday(¤t_time); - mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 + - (current_time.tv_usec / 1000)); + current_time = ktime_get_real(); + mpi_request.TimeStamp = cpu_to_le64(ktime_to_ms(current_time)); if (ioc->logging_level & MPT_DEBUG_INIT) { __le32 *mfp; From 1f275f976fdc04bf1bfd06929d10852b1b05decc Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 14 Apr 2016 10:27:14 -0700 Subject: [PATCH 080/138] scsi_dh_alua: Declare local functions static This patch avoids that building with W=1 causes gcc to report the following type of warning: no previous prototype for ... [-Wmissing-prototypes] Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinicke Cc: Hannes Reinecke Cc: Christoph Hellwig Cc: Ewan Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 8eaed0522aa3..e034f12c1418 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -190,8 +190,8 @@ static int submit_stpg(struct scsi_device *sdev, int group_id, ALUA_FAILOVER_RETRIES, NULL, req_flags); } -struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size, - int group_id) +static struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size, + int group_id) { struct alua_port_group *pg; @@ -219,8 +219,8 @@ struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size, * Allocate a new port_group structure for a given * device. */ -struct alua_port_group *alua_alloc_pg(struct scsi_device *sdev, - int group_id, int tpgs) +static struct alua_port_group *alua_alloc_pg(struct scsi_device *sdev, + int group_id, int tpgs) { struct alua_port_group *pg, *tmp_pg; From c3e385a1b985a9202ba7fbd0bdbdcb909905d00c Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Fri, 15 Apr 2016 00:23:30 -0700 Subject: [PATCH 081/138] megaraid_sas: reduce memory footprints in kdump mode This patch will reduce memory footprints of megaraid_sas driver when booted in kdump mode. Driver will not allocate memory for optional and perfromance oriented features. Below are key changes done in megaraid_sas driver to do this: 1. Limit Controller's queue depth to 100 in kdump mode. 2. Do not allocate memory for system info buffer and PD info buffer. 3. Disable performance oriented features e.g. Disable RDPQ mode, disable dual queue depth, restrict to single MSI-x vector. Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 2 + drivers/scsi/megaraid/megaraid_sas_base.c | 48 +++++++++++++-------- drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 ++ 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index fce414a2cd76..1784b09523d3 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1344,6 +1344,8 @@ struct megasas_ctrl_info { #define SCAN_PD_CHANNEL 0x1 #define SCAN_VD_CHANNEL 0x2 +#define MEGASAS_KDUMP_QUEUE_DEPTH 100 + enum MR_SCSI_CMD_TYPE { READ_WRITE_LDIO = 0, NON_READ_WRITE_LDIO = 1, diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index e6ebc7ae2df1..858820255dcb 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -5761,13 +5761,6 @@ static int megasas_probe_one(struct pci_dev *pdev, break; } - instance->system_info_buf = pci_zalloc_consistent(pdev, - sizeof(struct MR_DRV_SYSTEM_INFO), - &instance->system_info_h); - - if (!instance->system_info_buf) - dev_info(&instance->pdev->dev, "Can't allocate system info buffer\n"); - /* Crash dump feature related initialisation*/ instance->drv_buf_index = 0; instance->drv_buf_alloc = 0; @@ -5777,14 +5770,6 @@ static int megasas_probe_one(struct pci_dev *pdev, spin_lock_init(&instance->crashdump_lock); instance->crash_dump_buf = NULL; - if (!reset_devices) - instance->crash_dump_buf = pci_alloc_consistent(pdev, - CRASH_DMA_BUF_SIZE, - &instance->crash_dump_h); - if (!instance->crash_dump_buf) - dev_err(&pdev->dev, "Can't allocate Firmware " - "crash dump DMA buffer\n"); - megasas_poll_wait_aen = 0; instance->flag_ieee = 0; instance->ev = NULL; @@ -5803,11 +5788,26 @@ static int megasas_probe_one(struct pci_dev *pdev, goto fail_alloc_dma_buf; } - instance->pd_info = pci_alloc_consistent(pdev, - sizeof(struct MR_PD_INFO), &instance->pd_info_h); + if (!reset_devices) { + instance->system_info_buf = pci_zalloc_consistent(pdev, + sizeof(struct MR_DRV_SYSTEM_INFO), + &instance->system_info_h); + if (!instance->system_info_buf) + dev_info(&instance->pdev->dev, "Can't allocate system info buffer\n"); - if (!instance->pd_info) - dev_err(&instance->pdev->dev, "Failed to alloc mem for pd_info\n"); + instance->pd_info = pci_alloc_consistent(pdev, + sizeof(struct MR_PD_INFO), &instance->pd_info_h); + + if (!instance->pd_info) + dev_err(&instance->pdev->dev, "Failed to alloc mem for pd_info\n"); + + instance->crash_dump_buf = pci_alloc_consistent(pdev, + CRASH_DMA_BUF_SIZE, + &instance->crash_dump_h); + if (!instance->crash_dump_buf) + dev_err(&pdev->dev, "Can't allocate Firmware " + "crash dump DMA buffer\n"); + } /* * Initialize locks and queues @@ -7173,6 +7173,16 @@ static int __init megasas_init(void) { int rval; + /* + * Booted in kdump kernel, minimize memory footprints by + * disabling few features + */ + if (reset_devices) { + msix_vectors = 1; + rdpq_enable = 0; + dual_qdepth_disable = 1; + } + /* * Announce driver version and other information */ diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 98a848bdfdc2..320c1a0952d0 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -257,6 +257,9 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c if (!instance->is_rdpq) instance->max_fw_cmds = min_t(u16, instance->max_fw_cmds, 1024); + if (reset_devices) + instance->max_fw_cmds = min(instance->max_fw_cmds, + (u16)MEGASAS_KDUMP_QUEUE_DEPTH); /* * Reduce the max supported cmds by 1. This is to ensure that the * reply_q_sz (1 more than the max cmd that driver may send) From 64d0b8e4a6f7e9a3c366c2df93ec1f003d180ca3 Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Fri, 15 Apr 2016 00:23:31 -0700 Subject: [PATCH 082/138] megaraid_sas: call ISR function to clean up pending replies in OCR path In OCR path, before calling chip reset calls function megasas_wait_for_outstanding_fusion to check reason for OCR. In case of firmware FAULT initiated OCR and DCMD timeout initiated timeout, driver will clear any outstanding reply (yet to be processed by driver) in reply queues before going for chip reset. This code is added to handle a scenario when IO timeout initiated adapter reset and management application initiated adapter reset (by sending command to FAULT firmware) happens simultaneously since adapter reset function is safe-guarded by reset_mutex so only thread will be doing controller reset. Consider IO timeout thread gets mutex and proceeds with adapter reset process after disabling interrupts and by the time management application has fired command to firmware to do adapter reset and the same command is completed by firmware but since interrupts are disabled, driver will not get completion and the same command will be in outstanding/pending commands list of driver and refires same command from IO timeout thread after chip reset which will again FAULT firmware and eventually causes kill adapter. Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 320c1a0952d0..e2dc20566ab7 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -2762,6 +2762,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, dev_warn(&instance->pdev->dev, "Found FW in FAULT state," " will reset adapter scsi%d.\n", instance->host->host_no); + megasas_complete_cmd_dpc_fusion((unsigned long)instance); retval = 1; goto out; } @@ -2769,6 +2770,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, if (reason == MFI_IO_TIMEOUT_OCR) { dev_info(&instance->pdev->dev, "MFI IO is timed out, initiating OCR\n"); + megasas_complete_cmd_dpc_fusion((unsigned long)instance); retval = 1; goto out; } From bd23d4abe5edf09dfba086d44b7972cf73c14b0b Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Fri, 15 Apr 2016 00:23:32 -0700 Subject: [PATCH 083/138] megaraid_sas: task management code optimizations This patch will do code optmization for task management functions. Below are key changes: 1. Remove reset_device hook as it was not being used and driver was setting this to NULL. 2. Create wrapper functions for task abort and target reset and inside these functions adapter specific calls be made. e.g. fusion adapters support task abort and target reset so task abort and target reset should be issued to fusion adapters only and for MFI adapters, print a message saying feature not supported. Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 67 ++++++++++++++++------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 858820255dcb..b84756c1d230 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -2669,17 +2669,6 @@ blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) return BLK_EH_RESET_TIMER; } -/** - * megasas_reset_device - Device reset handler entry point - */ -static int megasas_reset_device(struct scsi_cmnd *scmd) -{ - /* - * First wait for all commands to complete - */ - return megasas_generic_reset(scmd); -} - /** * megasas_reset_bus_host - Bus & host reset handler entry point */ @@ -2701,6 +2690,50 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) return ret; } +/** + * megasas_task_abort - Issues task abort request to firmware + * (supported only for fusion adapters) + * @scmd: SCSI command pointer + */ +static int megasas_task_abort(struct scsi_cmnd *scmd) +{ + int ret; + struct megasas_instance *instance; + + instance = (struct megasas_instance *)scmd->device->host->hostdata; + + if (instance->ctrl_context) + ret = megasas_task_abort_fusion(scmd); + else { + sdev_printk(KERN_NOTICE, scmd->device, "TASK ABORT not supported\n"); + ret = FAILED; + } + + return ret; +} + +/** + * megasas_reset_target: Issues target reset request to firmware + * (supported only for fusion adapters) + * @scmd: SCSI command pointer + */ +static int megasas_reset_target(struct scsi_cmnd *scmd) +{ + int ret; + struct megasas_instance *instance; + + instance = (struct megasas_instance *)scmd->device->host->hostdata; + + if (instance->ctrl_context) + ret = megasas_reset_target_fusion(scmd); + else { + sdev_printk(KERN_NOTICE, scmd->device, "TARGET RESET not supported\n"); + ret = FAILED; + } + + return ret; +} + /** * megasas_bios_param - Returns disk geometry for a disk * @sdev: device handle @@ -2969,8 +3002,8 @@ static struct scsi_host_template megasas_template = { .slave_alloc = megasas_slave_alloc, .slave_destroy = megasas_slave_destroy, .queuecommand = megasas_queue_command, - .eh_device_reset_handler = megasas_reset_device, - .eh_bus_reset_handler = megasas_reset_bus_host, + .eh_target_reset_handler = megasas_reset_target, + .eh_abort_handler = megasas_task_abort, .eh_host_reset_handler = megasas_reset_bus_host, .eh_timed_out = megasas_reset_timer, .shost_attrs = megaraid_host_attrs, @@ -5598,14 +5631,6 @@ static int megasas_io_attach(struct megasas_instance *instance) host->max_lun = MEGASAS_MAX_LUN; host->max_cmd_len = 16; - /* Fusion only supports host reset */ - if (instance->ctrl_context) { - host->hostt->eh_device_reset_handler = NULL; - host->hostt->eh_bus_reset_handler = NULL; - host->hostt->eh_target_reset_handler = megasas_reset_target_fusion; - host->hostt->eh_abort_handler = megasas_task_abort_fusion; - } - /* * Notify the mid-layer about the new controller */ From 54c4042852a85713a7bdd8436cc63762049fbb39 Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Fri, 15 Apr 2016 00:23:33 -0700 Subject: [PATCH 084/138] megaraid_sas: driver version upgrade Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 1784b09523d3..ca86c885dfaa 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -35,8 +35,8 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "06.810.09.00-rc1" -#define MEGASAS_RELDATE "Jan. 28, 2016" +#define MEGASAS_VERSION "06.811.02.00-rc1" +#define MEGASAS_RELDATE "April 12, 2016" /* * Device IDs From 685b6d6e678705bf7ff5b7fdd9a904ec7ae9fbe3 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 15 Apr 2016 21:36:36 +0800 Subject: [PATCH 085/138] hisi_sas: add device and slot alloc hw methods Add methods to use HW specific versions of functions to allocate slot and device. HW specific methods are permitted to workaround device id vs IPTT collision issue in v2 hw. Signed-off-by: John Garry Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 3 +++ drivers/scsi/hisi_sas/hisi_sas_main.c | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 0978016482c1..d7cab724f203 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -133,6 +133,9 @@ struct hisi_sas_hw { int (*hw_init)(struct hisi_hba *hisi_hba); void (*setup_itct)(struct hisi_hba *hisi_hba, struct hisi_sas_device *device); + int (*slot_index_alloc)(struct hisi_hba *hisi_hba, int *slot_idx, + struct domain_device *device); + struct hisi_sas_device *(*alloc_dev)(struct domain_device *device); void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no); int (*get_free_slot)(struct hisi_hba *hisi_hba, int *q, int *s); void (*start_delivery)(struct hisi_hba *hisi_hba); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 097ab4f27a6b..18dd5ea2c721 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -227,7 +227,11 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, } else n_elem = task->num_scatter; - rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); + if (hisi_hba->hw->slot_index_alloc) + rc = hisi_hba->hw->slot_index_alloc(hisi_hba, &slot_idx, + device); + else + rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); if (rc) goto err_out; rc = hisi_hba->hw->get_free_slot(hisi_hba, &dlvry_queue, @@ -417,7 +421,10 @@ static int hisi_sas_dev_found(struct domain_device *device) struct hisi_sas_device *sas_dev; struct device *dev = &hisi_hba->pdev->dev; - sas_dev = hisi_sas_alloc_dev(device); + if (hisi_hba->hw->alloc_dev) + sas_dev = hisi_hba->hw->alloc_dev(device); + else + sas_dev = hisi_sas_alloc_dev(device); if (!sas_dev) { dev_err(dev, "fail alloc dev: max support %d devices\n", HISI_SAS_MAX_DEVICES); From 330fa7f3140481463eb4956c38b9a44dfeee52b9 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 15 Apr 2016 21:36:37 +0800 Subject: [PATCH 086/138] hisi_sas: add slot_index_alloc_quirk_v2_hw() Add v2 hw custom function slot_index_alloc_quirk_v2_hw(). SAS devices should have IPTT bit0 equal to 1. Signed-off-by: John Garry Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 4276594a14c8..f2966d8cde07 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -465,6 +465,33 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba, return readl(regs); } +/* This function needs to be protected from pre-emption. */ +static int +slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, int *slot_idx, + struct domain_device *device) +{ + unsigned int index = 0; + void *bitmap = hisi_hba->slot_index_tags; + int sata_dev = dev_is_sata(device); + + while (1) { + index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count, + index); + if (index >= hisi_hba->slot_index_count) + return -SAS_QUEUE_FULL; + /* + * SAS IPTT bit0 should be 1 + */ + if (sata_dev || (index & 1)) + break; + index++; + } + + set_bit(index, bitmap); + *slot_idx = index; + return 0; +} + static void config_phy_opt_mode_v2_hw(struct hisi_hba *hisi_hba, int phy_no) { u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG); @@ -2167,6 +2194,7 @@ static int hisi_sas_v2_init(struct hisi_hba *hisi_hba) static const struct hisi_sas_hw hisi_sas_v2_hw = { .hw_init = hisi_sas_v2_init, .setup_itct = setup_itct_v2_hw, + .slot_index_alloc = slot_index_alloc_quirk_v2_hw, .sl_notify = sl_notify_v2_hw, .get_wideport_bitmap = get_wideport_bitmap_v2_hw, .free_device = free_device_v2_hw, From b2bdaf2bde16537cbdbd5376acecc555f428603f Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 15 Apr 2016 21:36:38 +0800 Subject: [PATCH 087/138] hisi_sas: add alloc_dev_quirk_v2_hw() Add custom version of function to allocate device, alloc_dev_quirk_v2_hw(). For sata devices the device id bit0 should be 0. Signed-off-by: John Garry Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index f2966d8cde07..bbe98ecea0bc 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -492,6 +492,35 @@ slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, int *slot_idx, return 0; } +static struct +hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device *device) +{ + struct hisi_hba *hisi_hba = device->port->ha->lldd_ha; + struct hisi_sas_device *sas_dev = NULL; + int i, sata_dev = dev_is_sata(device); + + spin_lock(&hisi_hba->lock); + for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) { + /* + * SATA device id bit0 should be 0 + */ + if (sata_dev && (i & 1)) + continue; + if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) { + hisi_hba->devices[i].device_id = i; + sas_dev = &hisi_hba->devices[i]; + sas_dev->dev_status = HISI_SAS_DEV_NORMAL; + sas_dev->dev_type = device->dev_type; + sas_dev->hisi_hba = hisi_hba; + sas_dev->sas_device = device; + break; + } + } + spin_unlock(&hisi_hba->lock); + + return sas_dev; +} + static void config_phy_opt_mode_v2_hw(struct hisi_hba *hisi_hba, int phy_no) { u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG); @@ -2195,6 +2224,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { .hw_init = hisi_sas_v2_init, .setup_itct = setup_itct_v2_hw, .slot_index_alloc = slot_index_alloc_quirk_v2_hw, + .alloc_dev = alloc_dev_quirk_v2_hw, .sl_notify = sl_notify_v2_hw, .get_wideport_bitmap = get_wideport_bitmap_v2_hw, .free_device = free_device_v2_hw, From b8ac0cc78b56e798851f1435bc673761d3fb877e Mon Sep 17 00:00:00 2001 From: Joe Lawrence Date: Mon, 18 Apr 2016 10:50:12 -0400 Subject: [PATCH 088/138] mpt3sas - remove unused fw_event_work elements Firmware events are queued up using the fw_event_work's struct work, not its delayed_work member. The initial driver for SAS2 controllers had handled firmware reset using the rescan barrier and was later redesigned through "mpt2sas: [Resend] Host Reset code cleanup". The delayed_work variables are now unused and may provoke CONFIG_DEBUG_OBJECTS_TIMERS "assert_init not available" false warnings in _scsih_fw_event_cleanup_queue. Cleanup fw_event_work's unused entries, update its kerneldoc, and update _scsih_fw_event_cleanup_queue accordingly. Fixes: 146b16c8071f (mpt3sas: Refcount fw_events and fix unsafe list usage) Signed-off-by: Joe Lawrence Acked-by: Chaitra P B Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index e0e4920d0fa6..f2139e5604a3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -174,13 +174,13 @@ struct sense_info { * struct fw_event_work - firmware event struct * @list: link list framework * @work: work object (ioc->fault_reset_work_q) - * @cancel_pending_work: flag set during reset handling * @ioc: per adapter object * @device_handle: device handle * @VF_ID: virtual function id * @VP_ID: virtual port id * @ignore: flag meaning this event has been marked to ignore - * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h + * @event: firmware event MPI2_EVENT_XXX defined in mpi2_ioc.h + * @refcount: kref for this event * @event_data: reply event data payload follows * * This object stored on ioc->fw_event_list. @@ -188,8 +188,6 @@ struct sense_info { struct fw_event_work { struct list_head list; struct work_struct work; - u8 cancel_pending_work; - struct delayed_work delayed_work; struct MPT3SAS_ADAPTER *ioc; u16 device_handle; @@ -2804,12 +2802,12 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) /* * Wait on the fw_event to complete. If this returns 1, then * the event was never executed, and we need a put for the - * reference the delayed_work had on the fw_event. + * reference the work had on the fw_event. * * If it did execute, we wait for it to finish, and the put will * happen from _firmware_event_work() */ - if (cancel_delayed_work_sync(&fw_event->delayed_work)) + if (cancel_work_sync(&fw_event->work)) fw_event_work_put(fw_event); fw_event_work_put(fw_event); From aa105695732daa6604cb017ceb59a05ef34956bd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Apr 2016 12:37:44 +0300 Subject: [PATCH 089/138] hpsa: set the enclosure identifier to zero This has only called from show_sas_rphy_enclosure_identifier(). The caller expects that we set an identifier, otherwise it uses an uninitialized variable. [mkp: fixed typo] Signed-off-by: Dan Carpenter Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5be944c8b71c..25aa219ea2d2 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -9602,6 +9602,7 @@ hpsa_sas_get_linkerrors(struct sas_phy *phy) static int hpsa_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) { + *identifier = 0; return 0; } From 9c8a76d5f00dbfd1da6ea242a9263a47133e4053 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Apr 2016 12:40:06 +0300 Subject: [PATCH 090/138] bnx2i: silence uninitialized variable warnings Presumably it isn't possible to have empty lists here, but my static checker doesn't know that and complains that "ep" can be used uninitialized. Signed-off-by: Dan Carpenter Acked-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2i/bnx2i_iscsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 72894378ffcf..133901fd3e35 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -675,7 +675,7 @@ bnx2i_find_ep_in_ofld_list(struct bnx2i_hba *hba, u32 iscsi_cid) { struct list_head *list; struct list_head *tmp; - struct bnx2i_endpoint *ep; + struct bnx2i_endpoint *ep = NULL; read_lock_bh(&hba->ep_rdwr_lock); list_for_each_safe(list, tmp, &hba->ep_ofld_list) { @@ -703,7 +703,7 @@ bnx2i_find_ep_in_destroy_list(struct bnx2i_hba *hba, u32 iscsi_cid) { struct list_head *list; struct list_head *tmp; - struct bnx2i_endpoint *ep; + struct bnx2i_endpoint *ep = NULL; read_lock_bh(&hba->ep_rdwr_lock); list_for_each_safe(list, tmp, &hba->ep_destroy_list) { From 718924180a6a79afa558bd978c8a3436c39691ff Mon Sep 17 00:00:00 2001 From: Sebastian Herbszt Date: Sun, 17 Apr 2016 13:27:27 +0200 Subject: [PATCH 091/138] lpfc: remove incorrect lockdep assertion Remove incorrect lockdep assertion from lpfc_sli_hbqbuf_find() which acquires the hbalock itself. Fix the comment which resulted in this mistake. Fixes: 1c2ba475eb0e ("lpfc: Add lockdep assertions") Signed-off-by: Sebastian Herbszt Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 6b267b67f845..70edf21ae1b9 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2000,10 +2000,9 @@ lpfc_sli_hbqbuf_get(struct list_head *rb_list) * @phba: Pointer to HBA context object. * @tag: Tag of the hbq buffer. * - * This function is called with hbalock held. This function searches - * for the hbq buffer associated with the given tag in the hbq buffer - * list. If it finds the hbq buffer, it returns the hbq_buffer other wise - * it returns NULL. + * This function searches for the hbq buffer associated with the given tag in + * the hbq buffer list. If it finds the hbq buffer, it returns the hbq_buffer + * otherwise it returns NULL. **/ static struct hbq_dmabuf * lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) @@ -2012,8 +2011,6 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) struct hbq_dmabuf *hbq_buf; uint32_t hbqno; - lockdep_assert_held(&phba->hbalock); - hbqno = tag >> 16; if (hbqno >= LPFC_MAX_HBQS) return NULL; From 5e4fabb6eb058f6d473e22b6db3ef299acf00f1c Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Mon, 18 Apr 2016 08:47:18 +0300 Subject: [PATCH 092/138] st: clear ILI if Medium Error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some drives set the ILI flag together with MEDIUM ERROR sense code. Clear the ILI flag in this case so that the medium error will be handled. The problem was reported by Maurizio Lombardi. Signed-off-by: Kai Mäkisara Reviewed-by: Laurence Oberman Signed-off-by: Martin K. Petersen --- drivers/scsi/st.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index dbf1882cfbac..7af5226aa55b 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1974,9 +1974,12 @@ static long read_tape(struct scsi_tape *STp, long count, transfer = (int)cmdstatp->uremainder64; else transfer = 0; - if (STp->block_size == 0 && - cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR) - transfer = bytes; + if (cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR) { + if (STp->block_size == 0) + transfer = bytes; + /* Some drives set ILI with MEDIUM ERROR */ + cmdstatp->flags &= ~SENSE_ILI; + } if (cmdstatp->flags & SENSE_ILI) { /* ILI */ if (STp->block_size == 0 && From 71d397581d52c24c9903d9729aae09828f956801 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 23 Apr 2016 12:20:07 +1000 Subject: [PATCH 093/138] MAINTAINERS: Update the file list for the NCR 5380 entry The file atari_NCR5380.c has been removed from the tree so remove it from the MAINTAINERS file as well. While we are here, add the file dtc3x80.txt as it is only relevant to the dtc driver. Signed-off-by: Finn Thain Signed-off-by: Martin K. Petersen --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 61a323a6b2cf..a87defae88c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7539,10 +7539,10 @@ M: Michael Schmitz L: linux-scsi@vger.kernel.org S: Maintained F: Documentation/scsi/g_NCR5380.txt +F: Documentation/scsi/dtc3x80.txt F: drivers/scsi/NCR5380.* F: drivers/scsi/arm/cumana_1.c F: drivers/scsi/arm/oak.c -F: drivers/scsi/atari_NCR5380.c F: drivers/scsi/atari_scsi.* F: drivers/scsi/dmx3191d.c F: drivers/scsi/dtc.* From 1354379b13f190ae5da21c26836a16ba56566ab3 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 16 Apr 2016 02:12:29 +0300 Subject: [PATCH 094/138] mptsas: fix checks for dma mapping errors mptsas_smp_handler() checks for dma mapping errors by comparison returned address with zero, while pci_dma_mapping_error() should be used. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Acked-by: Sathya Prakash Veerichetty Signed-off-by: Martin K. Petersen --- drivers/message/fusion/mptsas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 7ebccfa8072a..7ee1667acde4 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -2281,7 +2281,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio), blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); - if (!dma_addr_out) + if (pci_dma_mapping_error(ioc->pcidev, dma_addr_out)) goto put_mf; ioc->add_sge(psge, flagsLength, dma_addr_out); psge += ioc->SGE_size; @@ -2296,7 +2296,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, flagsLength |= blk_rq_bytes(rsp) + 4; dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio), blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); - if (!dma_addr_in) + if (pci_dma_mapping_error(ioc->pcidev, dma_addr_in)) goto unmap; ioc->add_sge(psge, flagsLength, dma_addr_in); From da31df8c7285910ee8c8629d901b34a480ab0005 Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:30:55 -0700 Subject: [PATCH 095/138] aacraid: Removed unnecessary checks for NULL Current driver checks for NULL return from aac_fib_alloc_tag, but it not possible for it to return NULL. Fixed by: Remove all the checks for NULL returns from aac_fib_alloc_tag Suggested-by: Tomas Henzl Signed-off-by: Raghava Aditya Renukunta Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aachba.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 7dfd0fa27255..6678d1fd897b 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -555,8 +555,6 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd) dev = (struct aac_dev *)scsicmd->device->host->hostdata; cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd); - if (!cmd_fibcontext) - return -ENOMEM; aac_fib_init(cmd_fibcontext); dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext); @@ -1037,8 +1035,6 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd) dev = (struct aac_dev *)scsicmd->device->host->hostdata; cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd); - if (!cmd_fibcontext) - return -ENOMEM; aac_fib_init(cmd_fibcontext); dinfo = (struct aac_get_serial *) fib_data(cmd_fibcontext); @@ -1950,10 +1946,6 @@ static int aac_read(struct scsi_cmnd * scsicmd) * Alocate and initialize a Fib */ cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd); - if (!cmd_fibcontext) { - printk(KERN_WARNING "aac_read: fib allocation failed\n"); - return -1; - } status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count); @@ -2048,16 +2040,6 @@ static int aac_write(struct scsi_cmnd * scsicmd) * Allocate and initialize a Fib then setup a BlockWrite command */ cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd); - if (!cmd_fibcontext) { - /* FIB temporarily unavailable,not catastrophic failure */ - - /* scsicmd->result = DID_ERROR << 16; - * scsicmd->scsi_done(scsicmd); - * return 0; - */ - printk(KERN_WARNING "aac_write: fib allocation failed\n"); - return -1; - } status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua); @@ -2283,8 +2265,6 @@ static int aac_start_stop(struct scsi_cmnd *scsicmd) * Allocate and initialize a Fib */ cmd_fibcontext = aac_fib_alloc_tag(aac, scsicmd); - if (!cmd_fibcontext) - return SCSI_MLQUEUE_HOST_BUSY; aac_fib_init(cmd_fibcontext); @@ -3184,8 +3164,6 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) * Allocate and initialize a Fib then setup a BlockWrite command */ cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd); - if (!cmd_fibcontext) - return -1; status = aac_adapter_scsi(cmd_fibcontext, scsicmd); From a6cd4549af54ee1ba70a77661499828ea5a2bb3c Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:31:03 -0700 Subject: [PATCH 096/138] aacraid: Fix incorrectly named MACRO Suggested-by: Seymour, Shane M Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aacraid.h | 2 +- drivers/scsi/aacraid/comminit.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index efa493cf1bc6..1936e0813f13 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -720,7 +720,7 @@ struct sa_registers { }; -#define Sa_MINIPORT_REVISION 1 +#define SA_INIT_NUM_MSIXVECTORS 1 #define sa_readw(AEP, CSR) readl(&((AEP)->regs.sa->CSR)) #define sa_readl(AEP, CSR) readl(&((AEP)->regs.sa->CSR)) diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 2b4e75380ae6..35697c18ad51 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -91,7 +91,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); if (dev->max_fib_size != sizeof(struct hw_fib)) init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); - init->Sa_MSIXVectors = cpu_to_le32(Sa_MINIPORT_REVISION); + init->Sa_MSIXVectors = cpu_to_le32(SA_INIT_NUM_MSIXVECTORS); init->fsrev = cpu_to_le32(dev->fsrev); /* From 116d77fea02e2a5aded7d29ba4c692774cb339f1 Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:31:12 -0700 Subject: [PATCH 097/138] aacraid: Start adapter after updating number of MSIX vectors The adapter has to be started after updating the number of MSIX Vectors Fixes: ecc479e00db8 (aacraid: Set correct MSIX count for EEH recovery) Cc: stable@vger.kernel.org Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/linit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index ff6caab8cc8b..79a1cec1a51f 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1431,8 +1431,8 @@ static int aac_acquire_resources(struct aac_dev *dev) /* After EEH recovery or suspend resume, max_msix count * may change, therfore updating in init as well. */ - aac_adapter_start(dev); dev->init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix); + aac_adapter_start(dev); } return 0; From 07beca2be24cc710461c0b131832524c9ee08910 Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:31:26 -0700 Subject: [PATCH 098/138] aacraid: Relinquish CPU during timeout wait aac_fib_send has a special function case for initial commands during driver initialization using wait < 0(pseudo sync mode). In this case, the command does not sleep but rather spins checking for timeout.This loop is calls cpu_relax() in an attempt to allow other processes/threads to use the CPU, but this function does not relinquish the CPU and so the command will hog the processor. This was observed in a KDUMP "crashkernel" and that prevented the "command thread" (which is responsible for completing the command from being timed out) from starting because it could not get the CPU. Fixed by replacing "cpu_relax()" call with "schedule()" Cc: stable@vger.kernel.org Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/commsup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 511bbc575062..725aa78cab61 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -637,10 +637,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, } return -EFAULT; } - /* We used to udelay() here but that absorbed - * a CPU when a timeout occured. Not very - * useful. */ - cpu_relax(); + /* + * Allow other processes / CPUS to use core + */ + schedule(); } } else if (down_interruptible(&fibptr->event_wait)) { /* Do nothing ... satisfy From e4d5c4e238999ba0b68618a91eec33e7079cdbd4 Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:31:43 -0700 Subject: [PATCH 099/138] aacraid: Disable MSI mode for series 6, 7, 8 cards As the firmware for series 6, 7, 8 cards does not support msi, remove it in the driver Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/comminit.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 35697c18ad51..50d521a452d2 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -378,21 +378,8 @@ void aac_define_int_mode(struct aac_dev *dev) msi_count = i; } else { dev->msi_enabled = 0; - printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n", - dev->name, dev->id, i); - } - } - - if (!dev->msi_enabled) { - msi_count = 1; - i = pci_enable_msi(dev->pdev); - - if (!i) { - dev->msi_enabled = 1; - dev->msi = 1; - } else { - printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n", - dev->name, dev->id, i); + dev_err(&dev->pdev->dev, + "MSIX not supported!! Will try INTX 0x%x.\n", i); } } From fc4bf75ea300a5e62a2419f89dd0e22189dd7ab7 Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:31:57 -0700 Subject: [PATCH 100/138] aacraid: Fix for aac_command_thread hang Typically under error conditions, it is possible for aac_command_thread() to miss the wakeup from kthread_stop() and go back to sleep, causing it to hang aac_shutdown. In the observed scenario, the adapter is not functioning correctly and so aac_fib_send() never completes (or time-outs depending on how it was called). Shortly after aac_command_thread() starts it performs aac_fib_send(SendHostTime) which hangs. When aac_probe_one /aac_get_adapter_info send time outs, kthread_stop is called which breaks the command thread out of it's hang. The code will still go back to sleep in schedule_timeout() without checking kthread_should_stop() so it causes aac_probe_one to hang until the schedule_timeout() which is 30 minutes. Fixed by: Adding another kthread_should_stop() before schedule_timeout() Cc: stable@vger.kernel.org Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/commsup.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 725aa78cab61..bb7988d53216 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1996,6 +1996,10 @@ int aac_command_thread(void *data) if (difference <= 0) difference = 1; set_current_state(TASK_INTERRUPTIBLE); + + if (kthread_should_stop()) + break; + schedule_timeout(difference); if (kthread_should_stop()) From 9cb62fa24e0d22dbe991c315d6c454a341ea3f76 Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:32:09 -0700 Subject: [PATCH 101/138] aacraid: Log firmware AIF messages Firmware AIF messages about cache loss and data recovery are being missed by the driver since currently they are not captured but rather let go. This patch to capture those messages and log them for the user. Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aacraid.h | 4 ++++ drivers/scsi/aacraid/commsup.c | 27 +++++++++++++++++++++++++++ drivers/scsi/aacraid/linit.c | 2 ++ drivers/scsi/aacraid/src.c | 3 ++- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 1936e0813f13..b70f3eb323f7 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -2065,6 +2065,10 @@ extern struct aac_common aac_config; #define AifEnAddJBOD 30 /* JBOD created */ #define AifEnDeleteJBOD 31 /* JBOD deleted */ +#define AifBuManagerEvent 42 /* Bu management*/ +#define AifBuCacheDataLoss 10 +#define AifBuCacheDataRecover 11 + #define AifCmdJobProgress 2 /* Progress report */ #define AifJobCtrZero 101 /* Array Zero progress */ #define AifJobStsSuccess 1 /* Job completes */ diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index bb7988d53216..0aeecec1f5ea 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -901,6 +901,31 @@ void aac_printf(struct aac_dev *dev, u32 val) memset(cp, 0, 256); } +static inline int aac_aif_data(struct aac_aifcmd *aifcmd, uint32_t index) +{ + return le32_to_cpu(((__le32 *)aifcmd->data)[index]); +} + + +static void aac_handle_aif_bu(struct aac_dev *dev, struct aac_aifcmd *aifcmd) +{ + switch (aac_aif_data(aifcmd, 1)) { + case AifBuCacheDataLoss: + if (aac_aif_data(aifcmd, 2)) + dev_info(&dev->pdev->dev, "Backup unit had cache data loss - [%d]\n", + aac_aif_data(aifcmd, 2)); + else + dev_info(&dev->pdev->dev, "Backup Unit had cache data loss\n"); + break; + case AifBuCacheDataRecover: + if (aac_aif_data(aifcmd, 2)) + dev_info(&dev->pdev->dev, "DDR cache data recovered successfully - [%d]\n", + aac_aif_data(aifcmd, 2)); + else + dev_info(&dev->pdev->dev, "DDR cache data recovered successfully\n"); + break; + } +} /** * aac_handle_aif - Handle a message from the firmware @@ -1154,6 +1179,8 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) ADD : DELETE; break; } + case AifBuManagerEvent: + aac_handle_aif_bu(dev, aifcmd); break; } diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 79a1cec1a51f..a943bd230bc2 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1299,6 +1299,8 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) else shost->this_id = shost->max_id; + aac_intr_normal(aac, 0, 2, 0, NULL); + /* * dmb - we may need to move the setting of these parms somewhere else once * we get a fib that can report the actual numbers diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index bc0203f3d243..28f8b8a1b8a4 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -135,7 +135,8 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) if (mode & AAC_INT_MODE_AIF) { /* handle AIF */ - aac_intr_normal(dev, 0, 2, 0, NULL); + if (dev->aif_thread && dev->fsa_dev) + aac_intr_normal(dev, 0, 2, 0, NULL); if (dev->msi_enabled) aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT); mode = 0; From eef76f16295d34d7fab6994b82dda60ce002f91d Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:32:26 -0700 Subject: [PATCH 102/138] aacraid: Remove code to needlessly complete fib Currently driver completes double completed or spurious interrupted fibs. This is not necessary and causes the SCSI mid layer to issue aborts and resets, since completing a fib prematurely might trigger a race condition resulting in the driver not calling the scsi_done callback. Fixed by removing the call to fib complete. Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/dpcsup.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index d677b52860ae..7e836205aef1 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -392,9 +392,10 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, if (likely(fib->callback && fib->callback_data)) { fib->flags &= FIB_CONTEXT_FLAG_FASTRESP; fib->callback(fib->callback_data, fib); - } else { - aac_fib_complete(fib); - } + } else + dev_info(&dev->pdev->dev, + "Invalid callback_fib[%d] (*%p)(%p)\n", + index, fib->callback, fib->callback_data); } else { unsigned long flagv; dprintk((KERN_INFO "event_wait up\n")); From 78cbccd3bd683c295a44af8050797dc4a41376ff Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:32:37 -0700 Subject: [PATCH 103/138] aacraid: Fix for KDUMP driver hang When KDUMP is triggered the driver first talks to the firmware in INTX mode, but the adapter firmware is still in MSIX mode. Therefore the first driver command hangs since the driver is waiting for an INTX response and firmware gives a MSIX response. If when the OS is installed on a RAID drive created by the adapter KDUMP will hang since the driver does not receive a response in sync mode. Fixed by: Change the firmware to INTX mode if it is in MSIX mode before sending the first sync command. Cc: stable@vger.kernel.org Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aacraid.h | 1 + drivers/scsi/aacraid/comminit.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index b70f3eb323f7..0ba8f6118e75 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -29,6 +29,7 @@ enum { #define AAC_INT_MODE_MSI (1<<1) #define AAC_INT_MODE_AIF (1<<2) #define AAC_INT_MODE_SYNC (1<<3) +#define AAC_INT_MODE_MSIX (1<<16) #define AAC_INT_ENABLE_TYPE1_INTX 0xfffffffb #define AAC_INT_ENABLE_TYPE1_MSIX 0xfffffffa diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 50d521a452d2..341ea327ae79 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,20 @@ struct aac_common aac_config = { .irq_mod = 1 }; +static inline int aac_is_msix_mode(struct aac_dev *dev) +{ + u32 status; + + status = src_readl(dev, MUnit.OMR); + return (status & AAC_INT_MODE_MSIX); +} + +static inline void aac_change_to_intx(struct aac_dev *dev) +{ + aac_src_access_devreg(dev, AAC_DISABLE_MSIX); + aac_src_access_devreg(dev, AAC_ENABLE_INTX); +} + static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign) { unsigned char *base; @@ -414,6 +429,15 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) dev->comm_interface = AAC_COMM_PRODUCER; dev->raw_io_interface = dev->raw_io_64 = 0; + + /* + * Enable INTX mode, if not done already Enabled + */ + if (aac_is_msix_mode(dev)) { + aac_change_to_intx(dev); + dev_info(&dev->pdev->dev, "Changed firmware to INTX mode"); + } + if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, status+3, NULL)) && From 139112fb34db6361082b992d7b5fbb9d223c2c33 Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Mon, 25 Apr 2016 23:32:44 -0700 Subject: [PATCH 104/138] aacraid: Update driver version Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aacraid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 0ba8f6118e75..8f90d9e77104 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -63,7 +63,7 @@ enum { #define PMC_GLOBAL_INT_BIT0 0x00000001 #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 41052 +# define AAC_DRIVER_BUILD 41066 # define AAC_DRIVER_BRANCH "-ms" #endif #define MAXIMUM_NUM_CONTAINERS 32 From cf47723763a72354f90cd0b3e527704f4e2f7eb7 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 27 Apr 2016 17:13:26 -0500 Subject: [PATCH 105/138] hpsa: correct initialization order issue The driver was calling scsi_scan_host before enabling interrupts. This has gone unnoticed except for customers running in intx mode. Calling scsi_scan_host before interrupts are enabled causes "irq XX: nobody cared" messages and the driver to hang. This patch enables interrupts before the call to scsi_scan_host. Reported-by: Piotr Karbowski Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 25aa219ea2d2..9baf04e13a70 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8541,11 +8541,6 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto clean6; /* sg, cmd, irq, shost, pci, lu, aer/h */ - /* hook into SCSI subsystem */ - rc = hpsa_scsi_add_host(h); - if (rc) - goto clean7; /* perf, sg, cmd, irq, shost, pci, lu, aer/h */ - /* create the resubmit workqueue */ h->rescan_ctlr_wq = hpsa_create_controller_wq(h, "rescan"); if (!h->rescan_ctlr_wq) { @@ -8642,6 +8637,11 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&h->pdev->dev, "Can't track change to report lun data\n"); + /* hook into SCSI subsystem */ + rc = hpsa_scsi_add_host(h); + if (rc) + goto clean7; /* perf, sg, cmd, irq, shost, pci, lu, aer/h */ + /* Monitor the controller for firmware lockups */ h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker); From ded1be4ae6b8e279ab43a5fe2069dd60bb836d30 Mon Sep 17 00:00:00 2001 From: Joseph T Handzik Date: Wed, 27 Apr 2016 17:13:33 -0500 Subject: [PATCH 106/138] hpsa: add sas_address to sysfs device attibute There have been companies requesting a sysfs entry to obtain the sas address of device. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9baf04e13a70..a677dfe09998 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -728,6 +728,29 @@ static ssize_t unique_id_show(struct device *dev, sn[12], sn[13], sn[14], sn[15]); } +static ssize_t sas_address_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ctlr_info *h; + struct scsi_device *sdev; + struct hpsa_scsi_dev_t *hdev; + unsigned long flags; + u64 sas_address; + + sdev = to_scsi_device(dev); + h = sdev_to_hba(sdev); + spin_lock_irqsave(&h->lock, flags); + hdev = sdev->hostdata; + if (!hdev || is_logical_device(hdev) || !hdev->expose_device) { + spin_unlock_irqrestore(&h->lock, flags); + return -ENODEV; + } + sas_address = hdev->sas_address; + spin_unlock_irqrestore(&h->lock, flags); + + return snprintf(buf, PAGE_SIZE, "0x%016llx\n", sas_address); +} + static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, struct device_attribute *attr, char *buf) { @@ -840,6 +863,7 @@ static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL); static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); +static DEVICE_ATTR(sas_address, S_IRUGO, sas_address_show, NULL); static DEVICE_ATTR(hp_ssd_smart_path_enabled, S_IRUGO, host_show_hp_ssd_smart_path_enabled, NULL); static DEVICE_ATTR(path_info, S_IRUGO, path_info_show, NULL); @@ -865,6 +889,7 @@ static struct device_attribute *hpsa_sdev_attrs[] = { &dev_attr_unique_id, &dev_attr_hp_ssd_smart_path_enabled, &dev_attr_path_info, + &dev_attr_sas_address, NULL, }; From c448ecfa0b2e648a668a1c62286e989ab1dbf6c8 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 27 Apr 2016 17:13:51 -0500 Subject: [PATCH 107/138] hpsa: add timeouts for driver initiated commands faulty drives can cause the driver to hang during a scan operation. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index a677dfe09998..5ef62eafe5d1 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2831,7 +2831,7 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, goto out; } rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, NO_TIMEOUT); + PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -2857,7 +2857,7 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr, /* fill_cmd can't fail here, no data buffer to map. */ (void) fill_cmd(c, reset_type, h, NULL, 0, 0, scsi3addr, TYPE_MSG); - rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); + rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, DEFAULT_TIMEOUT); if (rc) { dev_warn(&h->pdev->dev, "Failed to send reset command\n"); goto out; @@ -3105,7 +3105,7 @@ static int hpsa_get_raid_map(struct ctlr_info *h, return -1; } rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, NO_TIMEOUT); + PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3148,7 +3148,7 @@ static int hpsa_bmic_sense_subsystem_information(struct ctlr_info *h, c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, NO_TIMEOUT); + PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3176,7 +3176,7 @@ static int hpsa_bmic_id_controller(struct ctlr_info *h, goto out; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, NO_TIMEOUT); + PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3207,7 +3207,7 @@ static int hpsa_bmic_id_physical_device(struct ctlr_info *h, c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff; hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, - NO_TIMEOUT); + DEFAULT_TIMEOUT); ei = c->err_info; if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { hpsa_scsi_interpret_error(h, c); @@ -3275,7 +3275,7 @@ static void hpsa_get_enclosure_info(struct ctlr_info *h, c->Request.CDB[5] = 0; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, - NO_TIMEOUT); + DEFAULT_TIMEOUT); if (rc) goto out; @@ -3487,7 +3487,7 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, if (extended_response) c->Request.CDB[1] = extended_response; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, NO_TIMEOUT); + PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3594,7 +3594,8 @@ static int hpsa_volume_offline(struct ctlr_info *h, c = cmd_alloc(h); (void) fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, scsi3addr, TYPE_CMD); - rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, NO_TIMEOUT); + rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, + DEFAULT_TIMEOUT); if (rc) { cmd_free(h, c); return 0; @@ -3669,7 +3670,8 @@ static int hpsa_device_supports_aborts(struct ctlr_info *h, c = cmd_alloc(h); (void) fill_cmd(c, HPSA_ABORT_MSG, h, &tag, 0, 0, scsi3addr, TYPE_MSG); - (void) hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, NO_TIMEOUT); + (void) hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, + DEFAULT_TIMEOUT); /* no unmap needed here because no data xfer. */ ei = c->err_info; switch (ei->CommandStatus) { @@ -5439,7 +5441,7 @@ static int hpsa_send_test_unit_ready(struct ctlr_info *h, /* Send the Test Unit Ready, fill_cmd can't fail, no mapping */ (void) fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, lunaddr, TYPE_CMD); - rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); + rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, DEFAULT_TIMEOUT); if (rc) return rc; /* no unmap needed here because no data xfer. */ @@ -5663,7 +5665,7 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr, 0, 0, scsi3addr, TYPE_MSG); if (h->needs_abort_tags_swizzled) swizzle_abort_tag(&c->Request.CDB[4]); - (void) hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); + (void) hpsa_scsi_do_simple_cmd(h, c, reply_queue, DEFAULT_TIMEOUT); hpsa_get_tag(h, abort, &taglower, &tagupper); dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: do_simple_cmd(abort) completed.\n", __func__, tagupper, taglower); @@ -5828,7 +5830,7 @@ static int hpsa_send_abort_ioaccel2(struct ctlr_info *h, c = cmd_alloc(h); setup_ioaccel2_abort_cmd(c, h, abort, reply_queue); c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; - (void) hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); + (void) hpsa_scsi_do_simple_cmd(h, c, reply_queue, DEFAULT_TIMEOUT); hpsa_get_tag(h, abort, &taglower, &tagupper); dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: do_simple_cmd(ioaccel2 abort) completed.\n", @@ -6373,7 +6375,8 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp) c->SG[0].Len = cpu_to_le32(iocommand.buf_size); c->SG[0].Ext = cpu_to_le32(HPSA_SG_LAST); /* not chaining */ } - rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, NO_TIMEOUT); + rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, + DEFAULT_TIMEOUT); if (iocommand.buf_size > 0) hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL); check_ioctl_unit_attention(h, c); @@ -6505,7 +6508,8 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) } c->SG[--i].Ext = cpu_to_le32(HPSA_SG_LAST); } - status = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, NO_TIMEOUT); + status = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, + DEFAULT_TIMEOUT); if (sg_used) hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL); check_ioctl_unit_attention(h, c); @@ -8728,7 +8732,7 @@ static void hpsa_flush_cache(struct ctlr_info *h) goto out; } rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_TODEVICE, NO_TIMEOUT); + PCI_DMA_TODEVICE, DEFAULT_TIMEOUT); if (rc) goto out; if (c->err_info->CommandStatus != 0) @@ -8767,7 +8771,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) goto errout; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, NO_TIMEOUT); + PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); if ((rc != 0) || (c->err_info->CommandStatus != 0)) goto errout; @@ -8779,7 +8783,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) goto errout; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_TODEVICE, NO_TIMEOUT); + PCI_DMA_TODEVICE, DEFAULT_TIMEOUT); if ((rc != 0) || (c->err_info->CommandStatus != 0)) goto errout; @@ -8789,7 +8793,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) goto errout; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, NO_TIMEOUT); + PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); if ((rc != 0) || (c->err_info->CommandStatus != 0)) goto errout; From 5323ed74bdf1274caabea6bfc94eef32b89c72fe Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 27 Apr 2016 17:13:59 -0500 Subject: [PATCH 108/138] hpsa: correct ioaccel state change operation offload_to_be_enabled also needs to be set to 0 during a state change. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5ef62eafe5d1..57f7062f03cf 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8283,8 +8283,10 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h) event_type = "configuration change"; /* Stop sending new RAID offload reqs via the IO accelerator */ scsi_block_requests(h->scsi_host); - for (i = 0; i < h->ndevices; i++) + for (i = 0; i < h->ndevices; i++) { h->dev[i]->offload_enabled = 0; + h->dev[i]->offload_to_be_enabled = 0; + } hpsa_drain_accel_commands(h); /* Set 'accelerator path config change' bit */ dev_warn(&h->pdev->dev, From 064d1b1d2d8e0b90f1a0a49112eca0d5c2a09b16 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 27 Apr 2016 17:14:07 -0500 Subject: [PATCH 109/138] hpsa: correct ioaccel2 error procecssing. set offload_to_be_enabled to 0 when an ioaccel2 error is processed. Before, an ioaccel completion error would turn of ioaccel but a rescan would turn it back on again. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 57f7062f03cf..4f8e3285baa9 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2360,8 +2360,10 @@ static void process_ioaccel2_completion(struct ctlr_info *h, c2->error_data.serv_response == IOACCEL2_SERV_RESPONSE_FAILURE) { if (c2->error_data.status == - IOACCEL2_STATUS_SR_IOACCEL_DISABLED) + IOACCEL2_STATUS_SR_IOACCEL_DISABLED) { dev->offload_enabled = 0; + dev->offload_to_be_enabled = 0; + } return hpsa_retry_cmd(h, c); } From ba74fdc411b84064d7abe4b10d0708f6dad03eb2 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 27 Apr 2016 17:14:17 -0500 Subject: [PATCH 110/138] hpsa: correct handling of HBA device removal Need to report HBA device removal faster than the event handler polling interval. Stop I/O to the removed disk and wait for all I/O operations to flush before removing the device. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 89 ++++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/hpsa.h | 1 + 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4f8e3285baa9..034624f1ca64 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -294,6 +294,9 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h); static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h, struct ReportExtendedLUNdata *buf, int bufsize); static int hpsa_luns_changed(struct ctlr_info *h); +static bool hpsa_cmd_dev_match(struct ctlr_info *h, struct CommandList *c, + struct hpsa_scsi_dev_t *dev, + unsigned char *scsi3addr); static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) { @@ -1745,6 +1748,51 @@ static int hpsa_add_device(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) return rc; } +static int hpsa_find_outstanding_commands_for_dev(struct ctlr_info *h, + struct hpsa_scsi_dev_t *dev) +{ + int i; + int count = 0; + + for (i = 0; i < h->nr_cmds; i++) { + struct CommandList *c = h->cmd_pool + i; + int refcount = atomic_inc_return(&c->refcount); + + if (refcount > 1 && hpsa_cmd_dev_match(h, c, dev, + dev->scsi3addr)) { + unsigned long flags; + + spin_lock_irqsave(&h->lock, flags); /* Implied MB */ + if (!hpsa_is_cmd_idle(c)) + ++count; + spin_unlock_irqrestore(&h->lock, flags); + } + + cmd_free(h, c); + } + + return count; +} + +static void hpsa_wait_for_outstanding_commands_for_dev(struct ctlr_info *h, + struct hpsa_scsi_dev_t *device) +{ + int cmds = 0; + int waits = 0; + + while (1) { + cmds = hpsa_find_outstanding_commands_for_dev(h, device); + if (cmds == 0) + break; + if (++waits > 20) + break; + dev_warn(&h->pdev->dev, + "%s: removing device with %d outstanding commands!\n", + __func__, cmds); + msleep(1000); + } +} + static void hpsa_remove_device(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) { @@ -1768,8 +1816,13 @@ static void hpsa_remove_device(struct ctlr_info *h, hpsa_show_dev_msg(KERN_WARNING, h, device, "didn't find device for removal."); } - } else /* HBA */ + } else { /* HBA */ + + device->removed = 1; + hpsa_wait_for_outstanding_commands_for_dev(h, device); + hpsa_remove_sas_device(device); + } } static void adjust_hpsa_scsi_table(struct ctlr_info *h, @@ -2171,7 +2224,8 @@ static void hpsa_unmap_sg_chain_block(struct ctlr_info *h, static int handle_ioaccel_mode2_error(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd, - struct io_accel2_cmd *c2) + struct io_accel2_cmd *c2, + struct hpsa_scsi_dev_t *dev) { int data_len; int retry = 0; @@ -2235,8 +2289,27 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, case IOACCEL2_STATUS_SR_NO_PATH_TO_DEVICE: case IOACCEL2_STATUS_SR_INVALID_DEVICE: case IOACCEL2_STATUS_SR_IOACCEL_DISABLED: - /* We will get an event from ctlr to trigger rescan */ - retry = 1; + /* + * Did an HBA disk disappear? We will eventually + * get a state change event from the controller but + * in the meantime, we need to tell the OS that the + * HBA disk is no longer there and stop I/O + * from going down. This allows the potential re-insert + * of the disk to get the same device node. + */ + if (dev->physical_device && dev->expose_device) { + cmd->result = DID_NO_CONNECT << 16; + dev->removed = 1; + h->drv_req_rescan = 1; + dev_warn(&h->pdev->dev, + "%s: device is gone!\n", __func__); + } else + /* + * Retry by sending down the RAID path. + * We will get an event from ctlr to + * trigger rescan regardless. + */ + retry = 1; break; default: retry = 1; @@ -2368,7 +2441,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h, return hpsa_retry_cmd(h, c); } - if (handle_ioaccel_mode2_error(h, c, cmd, c2)) + if (handle_ioaccel_mode2_error(h, c, cmd, c2, dev)) return hpsa_retry_cmd(h, c); return hpsa_cmd_free_and_done(h, c, cmd); @@ -5263,6 +5336,12 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) dev = cmd->device->hostdata; if (!dev) { + cmd->result = NOT_READY << 16; /* host byte */ + cmd->scsi_done(cmd); + return 0; + } + + if (dev->removed) { cmd->result = DID_NO_CONNECT << 16; cmd->scsi_done(cmd); return 0; diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index d06bb7417e36..a1487e67f7a1 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -63,6 +63,7 @@ struct hpsa_scsi_dev_t { unsigned char scsi3addr[8]; /* as presented to the HW */ u8 physical_device : 1; u8 expose_device; + u8 removed : 1; /* device is marked for death */ #define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0" unsigned char device_id[16]; /* from inquiry pg. 0x83 */ u64 sas_address; From ff54aee466e3ad3f5aad76c629a8bcb88fc9b348 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 27 Apr 2016 17:14:26 -0500 Subject: [PATCH 111/138] hpsa: update driver version Reviewed-by: Gerry Morong Signed-off-by: Don Brace Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 034624f1ca64..ff25d2082139 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -60,7 +60,7 @@ * HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' * with an optional trailing '-' followed by a byte value (0-255). */ -#define HPSA_DRIVER_VERSION "3.4.14-0" +#define HPSA_DRIVER_VERSION "3.4.16-0" #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" #define HPSA "hpsa" From 773642d95b8220502555122578694deeee8af4af Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Mon, 25 Apr 2016 12:16:28 -0400 Subject: [PATCH 112/138] scsi_debug: cleanup naming and bit crunching Shorten file scope static and constant names. Use more get/put_unaligned calls to hide bit banging. Introduce sdebug_verbose boolean to replace frequent masking of option bit flags. Add GPL and bump version. [mkp: Use logical instead of bitwise OR for LBP VPD flags] Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 1162 +++++++++++++++++-------------------- 1 file changed, 525 insertions(+), 637 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 06b151711cdd..ac74cbde7adf 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -6,23 +6,15 @@ * anything out of the ordinary is seen. * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * - * This version is more generic, simulating a variable number of disk - * (or disk like devices) sharing a common amount of RAM. To be more - * realistic, the simulated devices have the transport attributes of - * SAS disks. + * Copyright (C) 2001 - 2016 Douglas Gilbert * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. * * For documentation see http://sg.danny.cz/sg/sdebug26.html * - * D. Gilbert (dpg) work for Magneto-Optical device test [20010421] - * dpg: work for devfs large number of disks [20010809] - * forked for lk 2.5 series [20011216, 20020101] - * use vmalloc() more inquiry+mode_sense [20020302] - * add timers for delayed responses [20020721] - * Patrick Mansfield max_luns+scsi_level [20021031] - * Mike Anderson sysfs work [20021118] - * dpg: change style of boot options to "scsi_debug.num_tgts=2" and - * module options to "modprobe scsi_debug num_tgts=2" [20021221] */ @@ -66,8 +58,9 @@ #include "sd.h" #include "scsi_logging.h" -#define SCSI_DEBUG_VERSION "1.85" -static const char *scsi_debug_version_date = "20141022"; +/* make sure inq_product_rev string corresponds to this version */ +#define SCSI_DEBUG_VERSION "1.86" +static const char *sdebug_version_date = "20160422"; #define MY_NAME "scsi_debug" @@ -145,38 +138,44 @@ static const char *scsi_debug_version_date = "20141022"; #define DEF_STRICT 0 #define DELAY_OVERRIDDEN -9999 -/* bit mask values for scsi_debug_opts */ -#define SCSI_DEBUG_OPT_NOISE 1 -#define SCSI_DEBUG_OPT_MEDIUM_ERR 2 -#define SCSI_DEBUG_OPT_TIMEOUT 4 -#define SCSI_DEBUG_OPT_RECOVERED_ERR 8 -#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 -#define SCSI_DEBUG_OPT_DIF_ERR 32 -#define SCSI_DEBUG_OPT_DIX_ERR 64 -#define SCSI_DEBUG_OPT_MAC_TIMEOUT 128 -#define SCSI_DEBUG_OPT_SHORT_TRANSFER 0x100 -#define SCSI_DEBUG_OPT_Q_NOISE 0x200 -#define SCSI_DEBUG_OPT_ALL_TSF 0x400 -#define SCSI_DEBUG_OPT_RARE_TSF 0x800 -#define SCSI_DEBUG_OPT_N_WCE 0x1000 -#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000 -#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000 -#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000) +/* bit mask values for sdebug_opts */ +#define SDEBUG_OPT_NOISE 1 +#define SDEBUG_OPT_MEDIUM_ERR 2 +#define SDEBUG_OPT_TIMEOUT 4 +#define SDEBUG_OPT_RECOVERED_ERR 8 +#define SDEBUG_OPT_TRANSPORT_ERR 16 +#define SDEBUG_OPT_DIF_ERR 32 +#define SDEBUG_OPT_DIX_ERR 64 +#define SDEBUG_OPT_MAC_TIMEOUT 128 +#define SDEBUG_OPT_SHORT_TRANSFER 0x100 +#define SDEBUG_OPT_Q_NOISE 0x200 +#define SDEBUG_OPT_ALL_TSF 0x400 +#define SDEBUG_OPT_RARE_TSF 0x800 +#define SDEBUG_OPT_N_WCE 0x1000 +#define SDEBUG_OPT_RESET_NOISE 0x2000 +#define SDEBUG_OPT_NO_CDB_NOISE 0x4000 +#define SDEBUG_OPT_ALL_NOISE (SDEBUG_OPT_NOISE | SDEBUG_OPT_Q_NOISE | \ + SDEBUG_OPT_RESET_NOISE) +#define SDEBUG_OPT_ALL_INJECTING (SDEBUG_OPT_RECOVERED_ERR | \ + SDEBUG_OPT_TRANSPORT_ERR | \ + SDEBUG_OPT_DIF_ERR | SDEBUG_OPT_DIX_ERR | \ + SDEBUG_OPT_SHORT_TRANSFER) /* When "every_nth" > 0 then modulo "every_nth" commands: - * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set + * - a no response is simulated if SDEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write - * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. + * commands if SDEBUG_OPT_RECOVERED_ERR is set. * - a TRANSPORT_ERROR is simulated on successful read and write - * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. + * commands if SDEBUG_OPT_TRANSPORT_ERR is set. * * When "every_nth" < 0 then after "- every_nth" commands: - * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set + * - a no response is simulated if SDEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write - * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. + * commands if SDEBUG_OPT_RECOVERED_ERR is set. * - a TRANSPORT_ERROR is simulated on successful read and write - * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. - * This will continue until some other action occurs (e.g. the user - * writing a new value (other than -1 or 1) to every_nth via sysfs). + * commands if _DEBUG_OPT_TRANSPORT_ERR is set. + * This will continue on every subsequent command until some other action + * occurs (e.g. the user * writing a new value (other than -1 or 1) to + * every_nth via sysfs). */ /* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in @@ -196,7 +195,7 @@ static const char *scsi_debug_version_date = "20141022"; #define UAS_ONLY 1 /* check for UAs only */ #define UAS_TUR 0 /* if no UAs then check if media access possible */ -/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this +/* when 1==SDEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this * sector on read commands: */ #define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ #define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */ @@ -517,47 +516,48 @@ struct sdebug_scmd_extra_t { bool inj_short; }; -static int scsi_debug_add_host = DEF_NUM_HOST; -static int scsi_debug_ato = DEF_ATO; -static int scsi_debug_delay = DEF_DELAY; -static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; -static int scsi_debug_dif = DEF_DIF; -static int scsi_debug_dix = DEF_DIX; -static int scsi_debug_dsense = DEF_D_SENSE; -static int scsi_debug_every_nth = DEF_EVERY_NTH; -static int scsi_debug_fake_rw = DEF_FAKE_RW; -static unsigned int scsi_debug_guard = DEF_GUARD; -static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; -static int scsi_debug_max_luns = DEF_MAX_LUNS; -static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE; +static int sdebug_add_host = DEF_NUM_HOST; +static int sdebug_ato = DEF_ATO; +static int sdebug_delay = DEF_DELAY; +static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB; +static int sdebug_dif = DEF_DIF; +static int sdebug_dix = DEF_DIX; +static int sdebug_dsense = DEF_D_SENSE; +static int sdebug_every_nth = DEF_EVERY_NTH; +static int sdebug_fake_rw = DEF_FAKE_RW; +static unsigned int sdebug_guard = DEF_GUARD; +static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED; +static int sdebug_max_luns = DEF_MAX_LUNS; +static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE; static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ -static int scsi_debug_ndelay = DEF_NDELAY; -static int scsi_debug_no_lun_0 = DEF_NO_LUN_0; -static int scsi_debug_no_uld = 0; -static int scsi_debug_num_parts = DEF_NUM_PARTS; -static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */ -static int scsi_debug_opt_blks = DEF_OPT_BLKS; -static int scsi_debug_opts = DEF_OPTS; -static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP; -static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */ -static int scsi_debug_scsi_level = DEF_SCSI_LEVEL; -static int scsi_debug_sector_size = DEF_SECTOR_SIZE; -static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; -static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; -static unsigned int scsi_debug_lbpu = DEF_LBPU; -static unsigned int scsi_debug_lbpws = DEF_LBPWS; -static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10; -static unsigned int scsi_debug_lbprz = DEF_LBPRZ; -static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT; -static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY; -static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS; -static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC; -static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH; -static bool scsi_debug_removable = DEF_REMOVABLE; -static bool scsi_debug_clustering; -static bool scsi_debug_host_lock = DEF_HOST_LOCK; -static bool scsi_debug_strict = DEF_STRICT; +static int sdebug_ndelay = DEF_NDELAY; +static int sdebug_no_lun_0 = DEF_NO_LUN_0; +static int sdebug_no_uld; +static int sdebug_num_parts = DEF_NUM_PARTS; +static int sdebug_num_tgts = DEF_NUM_TGTS; /* targets per host */ +static int sdebug_opt_blks = DEF_OPT_BLKS; +static int sdebug_opts = DEF_OPTS; +static int sdebug_physblk_exp = DEF_PHYSBLK_EXP; +static int sdebug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */ +static int sdebug_scsi_level = DEF_SCSI_LEVEL; +static int sdebug_sector_size = DEF_SECTOR_SIZE; +static int sdebug_virtual_gb = DEF_VIRTUAL_GB; +static int sdebug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; +static unsigned int sdebug_lbpu = DEF_LBPU; +static unsigned int sdebug_lbpws = DEF_LBPWS; +static unsigned int sdebug_lbpws10 = DEF_LBPWS10; +static unsigned int sdebug_lbprz = DEF_LBPRZ; +static unsigned int sdebug_unmap_alignment = DEF_UNMAP_ALIGNMENT; +static unsigned int sdebug_unmap_granularity = DEF_UNMAP_GRANULARITY; +static unsigned int sdebug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS; +static unsigned int sdebug_unmap_max_desc = DEF_UNMAP_MAX_DESC; +static unsigned int sdebug_write_same_length = DEF_WRITESAME_LENGTH; +static bool sdebug_removable = DEF_REMOVABLE; +static bool sdebug_clustering; +static bool sdebug_host_lock = DEF_HOST_LOCK; +static bool sdebug_strict = DEF_STRICT; static bool sdebug_any_injecting_opt; +static bool sdebug_verbose; static atomic_t sdebug_cmnd_count; static atomic_t sdebug_completions; @@ -580,8 +580,8 @@ static int sdebug_sectors_per; /* sectors per cylinder */ static unsigned int scsi_debug_lbp(void) { - return ((0 == scsi_debug_fake_rw) && - (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10)); + return 0 == sdebug_fake_rw && + (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10); } struct sdebug_dev_info { @@ -674,7 +674,7 @@ static void *fake_store(unsigned long long lba) { lba = do_div(lba, sdebug_store_sectors); - return fake_storep + lba * scsi_debug_sector_size; + return fake_storep + lba * sdebug_sector_size; } static struct sd_dif_tuple *dif_store(sector_t sector) @@ -696,11 +696,11 @@ static void sdebug_max_tgts_luns(void) list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { hpnt = sdbg_host->shost; if ((hpnt->this_id >= 0) && - (scsi_debug_num_tgts > hpnt->this_id)) - hpnt->max_id = scsi_debug_num_tgts + 1; + (sdebug_num_tgts > hpnt->this_id)) + hpnt->max_id = sdebug_num_tgts + 1; else - hpnt->max_id = scsi_debug_num_tgts; - /* scsi_debug_max_luns; */ + hpnt->max_id = sdebug_num_tgts; + /* sdebug_max_luns; */ hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1; } spin_unlock(&sdebug_host_list_lock); @@ -725,8 +725,7 @@ mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d, } asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST; memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE); - scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST, - asc, 0); + scsi_build_sense_buffer(sdebug_dsense, sbuff, ILLEGAL_REQUEST, asc, 0); memset(sks, 0, sizeof(sks)); sks[0] = 0x80; if (c_d) @@ -736,7 +735,7 @@ mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d, sks[0] |= 0x7 & in_bit; } put_unaligned_be16(in_byte, sks + 1); - if (scsi_debug_dsense) { + if (sdebug_dsense) { sl = sbuff[7] + 8; sbuff[7] = sl; sbuff[sl] = 0x2; @@ -744,7 +743,7 @@ mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d, memcpy(sbuff + sl + 4, sks, 3); } else memcpy(sbuff + 15, sks, 3); - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + if (sdebug_verbose) sdev_printk(KERN_INFO, scp->device, "%s: [sense_key,asc,ascq" "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n", my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit); @@ -762,9 +761,9 @@ static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq) } memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE); - scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq); + scsi_build_sense_buffer(sdebug_dsense, sbuff, key, asc, asq); - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + if (sdebug_verbose) sdev_printk(KERN_INFO, scp->device, "%s: [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n", my_name, key, asc, asq); @@ -778,7 +777,7 @@ mk_sense_invalid_opcode(struct scsi_cmnd *scp) static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) { - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { + if (sdebug_verbose) { if (0x1261 == cmd) sdev_printk(KERN_INFO, dev, "%s: BLKFLSBUF [0x1261]\n", __func__); @@ -814,7 +813,6 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, struct sdebug_dev_info * devip) { int k; - bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts); k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS); if (k != SDEBUG_NUM_UAS) { @@ -824,38 +822,38 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, case SDEBUG_UA_POR: mk_sense_buffer(SCpnt, UNIT_ATTENTION, UA_RESET_ASC, POWER_ON_RESET_ASCQ); - if (debug) + if (sdebug_verbose) cp = "power on reset"; break; case SDEBUG_UA_BUS_RESET: mk_sense_buffer(SCpnt, UNIT_ATTENTION, UA_RESET_ASC, BUS_RESET_ASCQ); - if (debug) + if (sdebug_verbose) cp = "bus reset"; break; case SDEBUG_UA_MODE_CHANGED: mk_sense_buffer(SCpnt, UNIT_ATTENTION, UA_CHANGED_ASC, MODE_CHANGED_ASCQ); - if (debug) + if (sdebug_verbose) cp = "mode parameters changed"; break; case SDEBUG_UA_CAPACITY_CHANGED: mk_sense_buffer(SCpnt, UNIT_ATTENTION, UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ); - if (debug) + if (sdebug_verbose) cp = "capacity data changed"; break; case SDEBUG_UA_MICROCODE_CHANGED: mk_sense_buffer(SCpnt, UNIT_ATTENTION, TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ); - if (debug) + if (sdebug_verbose) cp = "microcode has been changed"; break; case SDEBUG_UA_MICROCODE_CHANGED_WO_RESET: mk_sense_buffer(SCpnt, UNIT_ATTENTION, TARGET_CHANGED_ASC, MICROCODE_CHANGED_WO_RESET_ASCQ); - if (debug) + if (sdebug_verbose) cp = "microcode has been changed without reset"; break; case SDEBUG_UA_LUNS_CHANGED: @@ -864,26 +862,25 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, * ASC/ASCQ REPORTED LUNS DATA HAS CHANGED on every LUN * on the target, until a REPORT LUNS command is * received. SPC-4 behavior is to report it only once. - * NOTE: scsi_debug_scsi_level does not use the same + * NOTE: sdebug_scsi_level does not use the same * values as struct scsi_device->scsi_level. */ - if (scsi_debug_scsi_level >= 6) /* SPC-4 and above */ + if (sdebug_scsi_level >= 6) /* SPC-4 and above */ clear_luns_changed_on_target(devip); mk_sense_buffer(SCpnt, UNIT_ATTENTION, TARGET_CHANGED_ASC, LUNS_CHANGED_ASCQ); - if (debug) + if (sdebug_verbose) cp = "reported luns data has changed"; break; default: - pr_warn("%s: unexpected unit attention code=%d\n", - __func__, k); - if (debug) + pr_warn("unexpected unit attention code=%d\n", k); + if (sdebug_verbose) cp = "unknown"; break; } clear_bit(k, devip->uas_bm); - if (debug) + if (sdebug_verbose) sdev_printk(KERN_INFO, SCpnt->device, "%s reports: Unit attention: %s\n", my_name, cp); @@ -892,7 +889,7 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, if ((UAS_TUR == uas_only) && devip->stopped) { mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); - if (debug) + if (sdebug_verbose) sdev_printk(KERN_INFO, SCpnt->device, "%s reports: Not ready: %s\n", my_name, "initializing command required"); @@ -911,7 +908,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, if (!sdb->length) return 0; if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE)) - return (DID_ERROR << 16); + return DID_ERROR << 16; act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents, arr, arr_len); @@ -935,7 +932,10 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, static const char * inq_vendor_id = "Linux "; static const char * inq_product_id = "scsi_debug "; -static const char *inq_product_rev = "0184"; /* version less '.' */ +static const char *inq_product_rev = "0186"; /* version less '.' */ +static const u64 naa5_comp_a = 0x5222222000000000ULL; +static const u64 naa5_comp_b = 0x5333333000000000ULL; +static const u64 naa5_comp_c = 0x5111111000000000ULL; /* Device identification VPD page. Returns number of bytes placed in arr */ static int inquiry_evpd_83(unsigned char * arr, int port_group_id, @@ -963,14 +963,8 @@ static int inquiry_evpd_83(unsigned char * arr, int port_group_id, arr[num++] = 0x3; /* PIV=0, lu, naa */ arr[num++] = 0x0; arr[num++] = 0x8; - arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */ - arr[num++] = 0x33; - arr[num++] = 0x33; - arr[num++] = 0x30; - arr[num++] = (dev_id_num >> 24); - arr[num++] = (dev_id_num >> 16) & 0xff; - arr[num++] = (dev_id_num >> 8) & 0xff; - arr[num++] = dev_id_num & 0xff; + put_unaligned_be64(naa5_comp_b + dev_id_num, arr + num); + num += 8; /* Target relative port number */ arr[num++] = 0x61; /* proto=sas, binary */ arr[num++] = 0x94; /* PIV=1, target port, rel port */ @@ -986,14 +980,8 @@ static int inquiry_evpd_83(unsigned char * arr, int port_group_id, arr[num++] = 0x93; /* piv=1, target port, naa */ arr[num++] = 0x0; arr[num++] = 0x8; - arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */ - arr[num++] = 0x22; - arr[num++] = 0x22; - arr[num++] = 0x20; - arr[num++] = (port_a >> 24); - arr[num++] = (port_a >> 16) & 0xff; - arr[num++] = (port_a >> 8) & 0xff; - arr[num++] = port_a & 0xff; + put_unaligned_be64(naa5_comp_a + port_a, arr + num); + num += 8; /* NAA-5, Target port group identifier */ arr[num++] = 0x61; /* proto=sas, binary */ arr[num++] = 0x95; /* piv=1, target port group id */ @@ -1001,21 +989,15 @@ static int inquiry_evpd_83(unsigned char * arr, int port_group_id, arr[num++] = 0x4; arr[num++] = 0; arr[num++] = 0; - arr[num++] = (port_group_id >> 8) & 0xff; - arr[num++] = port_group_id & 0xff; + put_unaligned_be16(port_group_id, arr + num); + num += 2; /* NAA-5, Target device identifier */ arr[num++] = 0x61; /* proto=sas, binary */ arr[num++] = 0xa3; /* piv=1, target device, naa */ arr[num++] = 0x0; arr[num++] = 0x8; - arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */ - arr[num++] = 0x22; - arr[num++] = 0x22; - arr[num++] = 0x20; - arr[num++] = (target_dev_id >> 24); - arr[num++] = (target_dev_id >> 16) & 0xff; - arr[num++] = (target_dev_id >> 8) & 0xff; - arr[num++] = target_dev_id & 0xff; + put_unaligned_be64(naa5_comp_a + target_dev_id, arr + num); + num += 8; /* SCSI name string: Target device identifier */ arr[num++] = 0x63; /* proto=sas, UTF-8 */ arr[num++] = 0xa8; /* piv=1, target device, SCSI name string */ @@ -1031,7 +1013,6 @@ static int inquiry_evpd_83(unsigned char * arr, int port_group_id, return num; } - static unsigned char vpd84_data[] = { /* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0, 0x22,0x22,0x22,0x0,0xbb,0x1, @@ -1101,15 +1082,8 @@ static int inquiry_evpd_88(unsigned char * arr, int target_dev_id) arr[num++] = 0x93; /* PIV=1, target port, NAA */ arr[num++] = 0x0; /* reserved */ arr[num++] = 0x8; /* length */ - arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */ - arr[num++] = 0x22; - arr[num++] = 0x22; - arr[num++] = 0x20; - arr[num++] = (port_a >> 24); - arr[num++] = (port_a >> 16) & 0xff; - arr[num++] = (port_a >> 8) & 0xff; - arr[num++] = port_a & 0xff; - + put_unaligned_be64(naa5_comp_a + port_a, arr + num); + num += 8; arr[num++] = 0x0; /* reserved */ arr[num++] = 0x0; /* reserved */ arr[num++] = 0x0; @@ -1123,14 +1097,8 @@ static int inquiry_evpd_88(unsigned char * arr, int target_dev_id) arr[num++] = 0x93; /* PIV=1, target port, NAA */ arr[num++] = 0x0; /* reserved */ arr[num++] = 0x8; /* length */ - arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */ - arr[num++] = 0x22; - arr[num++] = 0x22; - arr[num++] = 0x20; - arr[num++] = (port_b >> 24); - arr[num++] = (port_b >> 16) & 0xff; - arr[num++] = (port_b >> 8) & 0xff; - arr[num++] = port_b & 0xff; + put_unaligned_be64(naa5_comp_a + port_b, arr + num); + num += 8; return num; } @@ -1203,40 +1171,35 @@ static int inquiry_evpd_b0(unsigned char * arr) memcpy(arr, vpdb0_data, sizeof(vpdb0_data)); /* Optimal transfer length granularity */ - gran = 1 << scsi_debug_physblk_exp; - arr[2] = (gran >> 8) & 0xff; - arr[3] = gran & 0xff; + gran = 1 << sdebug_physblk_exp; + put_unaligned_be16(gran, arr + 2); /* Maximum Transfer Length */ - if (sdebug_store_sectors > 0x400) { - arr[4] = (sdebug_store_sectors >> 24) & 0xff; - arr[5] = (sdebug_store_sectors >> 16) & 0xff; - arr[6] = (sdebug_store_sectors >> 8) & 0xff; - arr[7] = sdebug_store_sectors & 0xff; - } + if (sdebug_store_sectors > 0x400) + put_unaligned_be32(sdebug_store_sectors, arr + 4); /* Optimal Transfer Length */ - put_unaligned_be32(scsi_debug_opt_blks, &arr[8]); + put_unaligned_be32(sdebug_opt_blks, &arr[8]); - if (scsi_debug_lbpu) { + if (sdebug_lbpu) { /* Maximum Unmap LBA Count */ - put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]); + put_unaligned_be32(sdebug_unmap_max_blocks, &arr[16]); /* Maximum Unmap Block Descriptor Count */ - put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]); + put_unaligned_be32(sdebug_unmap_max_desc, &arr[20]); } /* Unmap Granularity Alignment */ - if (scsi_debug_unmap_alignment) { - put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]); + if (sdebug_unmap_alignment) { + put_unaligned_be32(sdebug_unmap_alignment, &arr[28]); arr[28] |= 0x80; /* UGAVALID */ } /* Optimal Unmap Granularity */ - put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]); + put_unaligned_be32(sdebug_unmap_granularity, &arr[24]); /* Maximum WRITE SAME Length */ - put_unaligned_be64(scsi_debug_write_same_length, &arr[32]); + put_unaligned_be64(sdebug_write_same_length, &arr[32]); return 0x3c; /* Mandatory page length for Logical Block Provisioning */ @@ -1261,16 +1224,16 @@ static int inquiry_evpd_b2(unsigned char *arr) memset(arr, 0, 0x4); arr[0] = 0; /* threshold exponent */ - if (scsi_debug_lbpu) + if (sdebug_lbpu) arr[1] = 1 << 7; - if (scsi_debug_lbpws) + if (sdebug_lbpws) arr[1] |= 1 << 6; - if (scsi_debug_lbpws10) + if (sdebug_lbpws10) arr[1] |= 1 << 5; - if (scsi_debug_lbprz) + if (sdebug_lbprz) arr[1] |= 1 << 2; return 0x4; @@ -1287,17 +1250,17 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) int alloc_len, n, ret; bool have_wlun; - alloc_len = (cmd[3] << 8) + cmd[4]; + alloc_len = get_unaligned_be16(cmd + 3); arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); if (! arr) return DID_REQUEUE << 16; have_wlun = (scp->device->lun == SCSI_W_LUN_REPORT_LUNS); if (have_wlun) pq_pdt = 0x1e; /* present, wlun */ - else if (scsi_debug_no_lun_0 && (0 == devip->lun)) + else if (sdebug_no_lun_0 && (0 == devip->lun)) pq_pdt = 0x7f; /* not present, no device type */ else - pq_pdt = (scsi_debug_ptype & 0x1f); + pq_pdt = (sdebug_ptype & 0x1f); arr[0] = pq_pdt; if (0x2 & cmd[1]) { /* CMDDT bit set */ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1); @@ -1310,7 +1273,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) port_group_id = (((host_no + 1) & 0x7f) << 8) + (devip->channel & 0x7f); - if (0 == scsi_debug_vpd_use_hostno) + if (0 == sdebug_vpd_use_hostno) host_no = 0; lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) + (devip->target * 1000) + devip->lun); @@ -1352,9 +1315,9 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) } else if (0x86 == cmd[2]) { /* extended inquiry */ arr[1] = cmd[2]; /*sanity */ arr[3] = 0x3c; /* number of following entries */ - if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) + if (sdebug_dif == SD_DIF_TYPE3_PROTECTION) arr[4] = 0x4; /* SPT: GRD_CHK:1 */ - else if (scsi_debug_dif) + else if (sdebug_dif) arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */ else arr[4] = 0x0; /* no protection stuff */ @@ -1372,8 +1335,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) } else if (0x89 == cmd[2]) { /* ATA information */ arr[1] = cmd[2]; /*sanity */ n = inquiry_evpd_89(&arr[4]); - arr[2] = (n >> 8); - arr[3] = (n & 0xff); + put_unaligned_be16(n, arr + 2); } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */ arr[1] = cmd[2]; /*sanity */ arr[3] = inquiry_evpd_b0(&arr[4]); @@ -1388,19 +1350,19 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) kfree(arr); return check_condition_result; } - len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len); + len = min(get_unaligned_be16(arr + 2) + 4, alloc_len); ret = fill_from_dev_buffer(scp, arr, min(len, SDEBUG_MAX_INQ_ARR_SZ)); kfree(arr); return ret; } /* drops through here for a standard inquiry */ - arr[1] = scsi_debug_removable ? 0x80 : 0; /* Removable disk */ - arr[2] = scsi_debug_scsi_level; + arr[1] = sdebug_removable ? 0x80 : 0; /* Removable disk */ + arr[2] = sdebug_scsi_level; arr[3] = 2; /* response_data_format==2 */ arr[4] = SDEBUG_LONG_INQ_SZ - 5; - arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */ - if (0 == scsi_debug_vpd_use_hostno) + arr[5] = sdebug_dif ? 1 : 0; /* PROTECT bit */ + if (0 == sdebug_vpd_use_hostno) arr[5] = 0x10; /* claim: implicit TGPS */ arr[6] = 0x10; /* claim: MultiP */ /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */ @@ -1412,9 +1374,9 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */ arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */ n = 62; - if (scsi_debug_ptype == 0) { + if (sdebug_ptype == 0) { arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */ - } else if (scsi_debug_ptype == 1) { + } else if (sdebug_ptype == 1) { arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */ } arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */ @@ -1452,7 +1414,7 @@ static int resp_requests(struct scsi_cmnd * scp, } } else { memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE); - if (arr[0] >= 0x70 && dsense == scsi_debug_dsense) + if (arr[0] >= 0x70 && dsense == sdebug_dsense) ; /* have sense and formats match */ else if (arr[0] <= 0x70) { if (dsense) { @@ -1504,9 +1466,11 @@ static int resp_start_stop(struct scsi_cmnd * scp, static sector_t get_sdebug_capacity(void) { - if (scsi_debug_virtual_gb > 0) - return (sector_t)scsi_debug_virtual_gb * - (1073741824 / scsi_debug_sector_size); + static const unsigned int gibibyte = 1073741824; + + if (sdebug_virtual_gb > 0) + return (sector_t)sdebug_virtual_gb * + (gibibyte / sdebug_sector_size); else return sdebug_store_sectors; } @@ -1523,18 +1487,10 @@ static int resp_readcap(struct scsi_cmnd * scp, memset(arr, 0, SDEBUG_READCAP_ARR_SZ); if (sdebug_capacity < 0xffffffff) { capac = (unsigned int)sdebug_capacity - 1; - arr[0] = (capac >> 24); - arr[1] = (capac >> 16) & 0xff; - arr[2] = (capac >> 8) & 0xff; - arr[3] = capac & 0xff; - } else { - arr[0] = 0xff; - arr[1] = 0xff; - arr[2] = 0xff; - arr[3] = 0xff; - } - arr[6] = (scsi_debug_sector_size >> 8) & 0xff; - arr[7] = scsi_debug_sector_size & 0xff; + put_unaligned_be32(capac, arr + 0); + } else + put_unaligned_be32(0xffffffff, arr + 0); + put_unaligned_be16(sdebug_sector_size, arr + 6); return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ); } @@ -1544,34 +1500,27 @@ static int resp_readcap16(struct scsi_cmnd * scp, { unsigned char *cmd = scp->cmnd; unsigned char arr[SDEBUG_READCAP16_ARR_SZ]; - unsigned long long capac; - int k, alloc_len; + int alloc_len; - alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8) - + cmd[13]); + alloc_len = get_unaligned_be32(cmd + 10); /* following just in case virtual_gb changed */ sdebug_capacity = get_sdebug_capacity(); memset(arr, 0, SDEBUG_READCAP16_ARR_SZ); - capac = sdebug_capacity - 1; - for (k = 0; k < 8; ++k, capac >>= 8) - arr[7 - k] = capac & 0xff; - arr[8] = (scsi_debug_sector_size >> 24) & 0xff; - arr[9] = (scsi_debug_sector_size >> 16) & 0xff; - arr[10] = (scsi_debug_sector_size >> 8) & 0xff; - arr[11] = scsi_debug_sector_size & 0xff; - arr[13] = scsi_debug_physblk_exp & 0xf; - arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f; + put_unaligned_be64((u64)(sdebug_capacity - 1), arr + 0); + put_unaligned_be32(sdebug_sector_size, arr + 8); + arr[13] = sdebug_physblk_exp & 0xf; + arr[14] = (sdebug_lowest_aligned >> 8) & 0x3f; if (scsi_debug_lbp()) { arr[14] |= 0x80; /* LBPME */ - if (scsi_debug_lbprz) + if (sdebug_lbprz) arr[14] |= 0x40; /* LBPRZ */ } - arr[15] = scsi_debug_lowest_aligned & 0xff; + arr[15] = sdebug_lowest_aligned & 0xff; - if (scsi_debug_dif) { - arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */ + if (sdebug_dif) { + arr[12] = (sdebug_dif - 1) << 1; /* P_TYPE */ arr[12] |= 1; /* PROT_EN */ } @@ -1590,9 +1539,7 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp, int n, ret, alen, rlen; int port_group_a, port_group_b, port_a, port_b; - alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8) - + cmd[9]); - + alen = get_unaligned_be32(cmd + 6); arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC); if (! arr) return DID_REQUEUE << 16; @@ -1605,49 +1552,46 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp, port_a = 0x1; /* relative port A */ port_b = 0x2; /* relative port B */ port_group_a = (((host_no + 1) & 0x7f) << 8) + - (devip->channel & 0x7f); + (devip->channel & 0x7f); port_group_b = (((host_no + 1) & 0x7f) << 8) + - (devip->channel & 0x7f) + 0x80; + (devip->channel & 0x7f) + 0x80; /* * The asymmetric access state is cycled according to the host_id. */ n = 4; - if (0 == scsi_debug_vpd_use_hostno) { - arr[n++] = host_no % 3; /* Asymm access state */ - arr[n++] = 0x0F; /* claim: all states are supported */ + if (0 == sdebug_vpd_use_hostno) { + arr[n++] = host_no % 3; /* Asymm access state */ + arr[n++] = 0x0F; /* claim: all states are supported */ } else { - arr[n++] = 0x0; /* Active/Optimized path */ - arr[n++] = 0x01; /* claim: only support active/optimized paths */ + arr[n++] = 0x0; /* Active/Optimized path */ + arr[n++] = 0x01; /* only support active/optimized paths */ } - arr[n++] = (port_group_a >> 8) & 0xff; - arr[n++] = port_group_a & 0xff; + put_unaligned_be16(port_group_a, arr + n); + n += 2; arr[n++] = 0; /* Reserved */ arr[n++] = 0; /* Status code */ arr[n++] = 0; /* Vendor unique */ arr[n++] = 0x1; /* One port per group */ arr[n++] = 0; /* Reserved */ arr[n++] = 0; /* Reserved */ - arr[n++] = (port_a >> 8) & 0xff; - arr[n++] = port_a & 0xff; + put_unaligned_be16(port_a, arr + n); + n += 2; arr[n++] = 3; /* Port unavailable */ arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */ - arr[n++] = (port_group_b >> 8) & 0xff; - arr[n++] = port_group_b & 0xff; + put_unaligned_be16(port_group_b, arr + n); + n += 2; arr[n++] = 0; /* Reserved */ arr[n++] = 0; /* Status code */ arr[n++] = 0; /* Vendor unique */ arr[n++] = 0x1; /* One port per group */ arr[n++] = 0; /* Reserved */ arr[n++] = 0; /* Reserved */ - arr[n++] = (port_b >> 8) & 0xff; - arr[n++] = port_b & 0xff; + put_unaligned_be16(port_b, arr + n); + n += 2; rlen = n - 4; - arr[0] = (rlen >> 24) & 0xff; - arr[1] = (rlen >> 16) & 0xff; - arr[2] = (rlen >> 8) & 0xff; - arr[3] = rlen & 0xff; + put_unaligned_be32(rlen, arr + 0); /* * Return the smallest value of either @@ -1871,11 +1815,9 @@ static int resp_format_pg(unsigned char * p, int pcontrol, int target) 0, 0, 0, 0, 0x40, 0, 0, 0}; memcpy(p, format_pg, sizeof(format_pg)); - p[10] = (sdebug_sectors_per >> 8) & 0xff; - p[11] = sdebug_sectors_per & 0xff; - p[12] = (scsi_debug_sector_size >> 8) & 0xff; - p[13] = scsi_debug_sector_size & 0xff; - if (scsi_debug_removable) + put_unaligned_be16(sdebug_sectors_per, p + 10); + put_unaligned_be16(sdebug_sector_size, p + 12); + if (sdebug_removable) p[20] |= 0x20; /* should agree with INQUIRY */ if (1 == pcontrol) memset(p + 2, 0, sizeof(format_pg) - 2); @@ -1889,7 +1831,7 @@ static int resp_caching_pg(unsigned char * p, int pcontrol, int target) unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0}; - if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts) + if (SDEBUG_OPT_N_WCE & sdebug_opts) caching_pg[2] &= ~0x4; /* set WCE=0 (default WCE=1) */ memcpy(p, caching_pg, sizeof(caching_pg)); if (1 == pcontrol) @@ -1906,12 +1848,12 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target) unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0x2, 0x4b}; - if (scsi_debug_dsense) + if (sdebug_dsense) ctrl_m_pg[2] |= 0x4; else ctrl_m_pg[2] &= ~0x4; - if (scsi_debug_ato) + if (sdebug_ato) ctrl_m_pg[5] |= 0x80; /* ATO=1 */ memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg)); @@ -1955,31 +1897,29 @@ static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target, { /* SAS phy control and discover mode page for mode_sense */ unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2, 0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0, - 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1, + 0, 0, 0, 0, 0, 0, 0, 0, /* insert SAS addr */ + 0, 0, 0, 0, 0, 0, 0, 0, /* insert SAS addr */ 0x2, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0, - 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1, + 0, 0, 0, 0, 0, 0, 0, 0, /* insert SAS addr */ + 0, 0, 0, 0, 0, 0, 0, 0, /* insert SAS addr */ 0x3, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; int port_a, port_b; + put_unaligned_be64(naa5_comp_a, sas_pcd_m_pg + 16); + put_unaligned_be64(naa5_comp_c + 1, sas_pcd_m_pg + 24); + put_unaligned_be64(naa5_comp_a, sas_pcd_m_pg + 64); + put_unaligned_be64(naa5_comp_c + 1, sas_pcd_m_pg + 72); port_a = target_dev_id + 1; port_b = port_a + 1; memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg)); - p[20] = (port_a >> 24); - p[21] = (port_a >> 16) & 0xff; - p[22] = (port_a >> 8) & 0xff; - p[23] = port_a & 0xff; - p[48 + 20] = (port_b >> 24); - p[48 + 21] = (port_b >> 16) & 0xff; - p[48 + 22] = (port_b >> 8) & 0xff; - p[48 + 23] = port_b & 0xff; + put_unaligned_be32(port_a, p + 20); + put_unaligned_be32(port_b, p + 48 + 20); if (1 == pcontrol) memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4); return sizeof(sas_pcd_m_pg); @@ -2005,7 +1945,7 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) unsigned char dbd, llbaa; int pcontrol, pcode, subpcode, bd_len; unsigned char dev_spec; - int k, alloc_len, msense_6, offset, len, target_dev_id; + int alloc_len, msense_6, offset, len, target_dev_id; int target = scp->device->id; unsigned char * ap; unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; @@ -2017,11 +1957,11 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) subpcode = cmd[3]; msense_6 = (MODE_SENSE == cmd[0]); llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10); - if ((0 == scsi_debug_ptype) && (0 == dbd)) + if ((0 == sdebug_ptype) && (0 == dbd)) bd_len = llbaa ? 16 : 8; else bd_len = 0; - alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]); + alloc_len = msense_6 ? cmd[4] : get_unaligned_be16(cmd + 7); memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); if (0x3 == pcontrol) { /* Saving values not supported */ mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0); @@ -2030,7 +1970,7 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + (devip->target * 1000) - 3; /* set DPOFUA bit for disks */ - if (0 == scsi_debug_ptype) + if (0 == sdebug_ptype) dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10; else dev_spec = 0x0; @@ -2050,30 +1990,16 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) sdebug_capacity = get_sdebug_capacity(); if (8 == bd_len) { - if (sdebug_capacity > 0xfffffffe) { - ap[0] = 0xff; - ap[1] = 0xff; - ap[2] = 0xff; - ap[3] = 0xff; - } else { - ap[0] = (sdebug_capacity >> 24) & 0xff; - ap[1] = (sdebug_capacity >> 16) & 0xff; - ap[2] = (sdebug_capacity >> 8) & 0xff; - ap[3] = sdebug_capacity & 0xff; - } - ap[6] = (scsi_debug_sector_size >> 8) & 0xff; - ap[7] = scsi_debug_sector_size & 0xff; + if (sdebug_capacity > 0xfffffffe) + put_unaligned_be32(0xffffffff, ap + 0); + else + put_unaligned_be32(sdebug_capacity, ap + 0); + put_unaligned_be16(sdebug_sector_size, ap + 6); offset += bd_len; ap = arr + offset; } else if (16 == bd_len) { - unsigned long long capac = sdebug_capacity; - - for (k = 0; k < 8; ++k, capac >>= 8) - ap[7 - k] = capac & 0xff; - ap[12] = (scsi_debug_sector_size >> 24) & 0xff; - ap[13] = (scsi_debug_sector_size >> 16) & 0xff; - ap[14] = (scsi_debug_sector_size >> 8) & 0xff; - ap[15] = scsi_debug_sector_size & 0xff; + put_unaligned_be64((u64)sdebug_capacity, ap + 0); + put_unaligned_be32(sdebug_sector_size, ap + 12); offset += bd_len; ap = arr + offset; } @@ -2149,10 +2075,8 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) } if (msense_6) arr[0] = offset - 1; - else { - arr[0] = ((offset - 2) >> 8) & 0xff; - arr[1] = (offset - 2) & 0xff; - } + else + put_unaligned_be16((offset - 2), arr + 0); return fill_from_dev_buffer(scp, arr, min(alloc_len, offset)); } @@ -2170,21 +2094,20 @@ resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) memset(arr, 0, sizeof(arr)); pf = cmd[1] & 0x10; sp = cmd[1] & 0x1; - param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]); + param_len = mselect6 ? cmd[4] : get_unaligned_be16(cmd + 7); if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) { mk_sense_invalid_fld(scp, SDEB_IN_CDB, mselect6 ? 4 : 7, -1); return check_condition_result; } res = fetch_to_dev_buffer(scp, arr, param_len); if (-1 == res) - return (DID_ERROR << 16); - else if ((res < param_len) && - (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) + return DID_ERROR << 16; + else if (sdebug_verbose && (res < param_len)) sdev_printk(KERN_INFO, scp->device, "%s: cdb indicated=%d, IO sent=%d bytes\n", __func__, param_len, res); - md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2); - bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]); + md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2); + bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6); if (md_len > 2) { mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1); return check_condition_result; @@ -2197,7 +2120,7 @@ resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return check_condition_result; } spf = !!(arr[off] & 0x40); - pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) : + pg_len = spf ? (get_unaligned_be16(arr + off + 2) + 4) : (arr[off + 1] + 2); if ((pg_len + off) > param_len) { mk_sense_buffer(scp, ILLEGAL_REQUEST, @@ -2216,7 +2139,7 @@ resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) if (ctrl_m_pg[1] == arr[off + 1]) { memcpy(ctrl_m_pg + 2, arr + off + 2, sizeof(ctrl_m_pg) - 2); - scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4); + sdebug_dsense = !!(ctrl_m_pg[2] & 0x4); goto set_mode_changed_ua; } break; @@ -2279,7 +2202,7 @@ static int resp_log_sense(struct scsi_cmnd * scp, pcontrol = (cmd[2] & 0xc0) >> 6; pcode = cmd[2] & 0x3f; subpcode = cmd[3] & 0xff; - alloc_len = (cmd[7] << 8) + cmd[8]; + alloc_len = get_unaligned_be16(cmd + 7); arr[0] = pcode; if (0 == subpcode) { switch (pcode) { @@ -2336,7 +2259,7 @@ static int resp_log_sense(struct scsi_cmnd * scp, mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); return check_condition_result; } - len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len); + len = min(get_unaligned_be16(arr + 2) + 4, alloc_len); return fill_from_dev_buffer(scp, arr, min(len, SDEBUG_MAX_INQ_ARR_SZ)); } @@ -2384,15 +2307,15 @@ do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write) rest = block + num - sdebug_store_sectors; ret = sg_copy_buffer(sdb->table.sgl, sdb->table.nents, - fake_storep + (block * scsi_debug_sector_size), - (num - rest) * scsi_debug_sector_size, 0, do_write); - if (ret != (num - rest) * scsi_debug_sector_size) + fake_storep + (block * sdebug_sector_size), + (num - rest) * sdebug_sector_size, 0, do_write); + if (ret != (num - rest) * sdebug_sector_size) return ret; if (rest) { ret += sg_copy_buffer(sdb->table.sgl, sdb->table.nents, - fake_storep, rest * scsi_debug_sector_size, - (num - rest) * scsi_debug_sector_size, do_write); + fake_storep, rest * sdebug_sector_size, + (num - rest) * sdebug_sector_size, do_write); } return ret; @@ -2407,7 +2330,7 @@ comp_write_worker(u64 lba, u32 num, const u8 *arr) bool res; u64 block, rest = 0; u32 store_blks = sdebug_store_sectors; - u32 lb_size = scsi_debug_sector_size; + u32 lb_size = sdebug_sector_size; block = do_div(lba, store_blks); if (block + num > store_blks) @@ -2434,7 +2357,7 @@ static __be16 dif_compute_csum(const void *buf, int len) { __be16 csum; - if (scsi_debug_guard) + if (sdebug_guard) csum = (__force __be16)ip_compute_csum(buf, len); else csum = cpu_to_be16(crc_t10dif(buf, len)); @@ -2445,7 +2368,7 @@ static __be16 dif_compute_csum(const void *buf, int len) static int dif_verify(struct sd_dif_tuple *sdt, const void *data, sector_t sector, u32 ei_lba) { - __be16 csum = dif_compute_csum(data, scsi_debug_sector_size); + __be16 csum = dif_compute_csum(data, sdebug_sector_size); if (sdt->guard_tag != csum) { pr_err("GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n", @@ -2454,13 +2377,13 @@ static int dif_verify(struct sd_dif_tuple *sdt, const void *data, be16_to_cpu(csum)); return 0x01; } - if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && + if (sdebug_dif == SD_DIF_TYPE1_PROTECTION && be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { pr_err("REF check failed on sector %lu\n", (unsigned long)sector); return 0x03; } - if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && + if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && be32_to_cpu(sdt->ref_tag) != ei_lba) { pr_err("REF check failed on sector %lu\n", (unsigned long)sector); @@ -2592,13 +2515,13 @@ resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) break; } if (check_prot) { - if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && + if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && (cmd[1] & 0xe0)) { mk_sense_invalid_opcode(scp); return check_condition_result; } - if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || - scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && + if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION || + sdebug_dif == SD_DIF_TYPE3_PROTECTION) && (cmd[1] & 0xe0) == 0) sdev_printk(KERN_ERR, scp->device, "Unprotected RD " "to DIF device\n"); @@ -2622,7 +2545,7 @@ resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return check_condition_result; } - if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && + if ((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) && (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) && ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { /* claim unrecoverable read error */ @@ -2641,7 +2564,7 @@ resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) read_lock_irqsave(&atomic_rw, iflags); /* DIX + T10 DIF */ - if (scsi_debug_dix && scsi_prot_sg_count(scp)) { + if (sdebug_dix && scsi_prot_sg_count(scp)) { int prot_ret = prot_verify_read(scp, lba, num, ei_lba); if (prot_ret) { @@ -2750,13 +2673,13 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, ret = dif_verify(sdt, daddr, sector, ei_lba); if (ret) { - dump_sector(daddr, scsi_debug_sector_size); + dump_sector(daddr, sdebug_sector_size); goto out; } sector++; ei_lba++; - dpage_offset += scsi_debug_sector_size; + dpage_offset += sdebug_sector_size; } diter.consumed = dpage_offset; sg_miter_stop(&diter); @@ -2777,24 +2700,18 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, static unsigned long lba_to_map_index(sector_t lba) { - if (scsi_debug_unmap_alignment) { - lba += scsi_debug_unmap_granularity - - scsi_debug_unmap_alignment; - } - sector_div(lba, scsi_debug_unmap_granularity); - + if (sdebug_unmap_alignment) + lba += sdebug_unmap_granularity - sdebug_unmap_alignment; + sector_div(lba, sdebug_unmap_granularity); return lba; } static sector_t map_index_to_lba(unsigned long index) { - sector_t lba = index * scsi_debug_unmap_granularity; - - if (scsi_debug_unmap_alignment) { - lba -= scsi_debug_unmap_granularity - - scsi_debug_unmap_alignment; - } + sector_t lba = index * sdebug_unmap_granularity; + if (sdebug_unmap_alignment) + lba -= sdebug_unmap_granularity - sdebug_unmap_alignment; return lba; } @@ -2815,7 +2732,6 @@ static unsigned int map_state(sector_t lba, unsigned int *num) end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next)); *num = end - lba; - return mapped; } @@ -2841,19 +2757,19 @@ static void unmap_region(sector_t lba, unsigned int len) unsigned long index = lba_to_map_index(lba); if (lba == map_index_to_lba(index) && - lba + scsi_debug_unmap_granularity <= end && + lba + sdebug_unmap_granularity <= end && index < map_size) { clear_bit(index, map_storep); - if (scsi_debug_lbprz) { + if (sdebug_lbprz) { memset(fake_storep + - lba * scsi_debug_sector_size, 0, - scsi_debug_sector_size * - scsi_debug_unmap_granularity); + lba * sdebug_sector_size, 0, + sdebug_sector_size * + sdebug_unmap_granularity); } if (dif_storep) { memset(dif_storep + lba, 0xff, sizeof(*dif_storep) * - scsi_debug_unmap_granularity); + sdebug_unmap_granularity); } } lba = map_index_to_lba(index + 1); @@ -2911,13 +2827,13 @@ resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) break; } if (check_prot) { - if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && + if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && (cmd[1] & 0xe0)) { mk_sense_invalid_opcode(scp); return check_condition_result; } - if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || - scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && + if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION || + sdebug_dif == SD_DIF_TYPE3_PROTECTION) && (cmd[1] & 0xe0) == 0) sdev_printk(KERN_ERR, scp->device, "Unprotected WR " "to DIF device\n"); @@ -2938,7 +2854,7 @@ resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) write_lock_irqsave(&atomic_rw, iflags); /* DIX + T10 DIF */ - if (scsi_debug_dix && scsi_prot_sg_count(scp)) { + if (sdebug_dix && scsi_prot_sg_count(scp)) { int prot_ret = prot_verify_write(scp, lba, num, ei_lba); if (prot_ret) { @@ -2953,12 +2869,11 @@ resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) map_region(lba, num); write_unlock_irqrestore(&atomic_rw, iflags); if (-1 == ret) - return (DID_ERROR << 16); - else if ((ret < (num * scsi_debug_sector_size)) && - (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) + return DID_ERROR << 16; + else if (sdebug_verbose && (ret < (num * sdebug_sector_size))) sdev_printk(KERN_INFO, scp->device, "%s: write: cdb indicated=%u, IO sent=%d bytes\n", - my_name, num * scsi_debug_sector_size, ret); + my_name, num * sdebug_sector_size, ret); if (sdebug_any_injecting_opt) { struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); @@ -2986,6 +2901,7 @@ resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba, unsigned long iflags; unsigned long long i; int ret; + u64 lba_off; ret = check_device_access_params(scp, lba, num); if (ret) @@ -2998,31 +2914,29 @@ resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba, goto out; } + lba_off = lba * sdebug_sector_size; /* if ndob then zero 1 logical block, else fetch 1 logical block */ if (ndob) { - memset(fake_storep + (lba * scsi_debug_sector_size), 0, - scsi_debug_sector_size); + memset(fake_storep + lba_off, 0, sdebug_sector_size); ret = 0; } else - ret = fetch_to_dev_buffer(scp, fake_storep + - (lba * scsi_debug_sector_size), - scsi_debug_sector_size); + ret = fetch_to_dev_buffer(scp, fake_storep + lba_off, + sdebug_sector_size); if (-1 == ret) { write_unlock_irqrestore(&atomic_rw, iflags); - return (DID_ERROR << 16); - } else if ((ret < (num * scsi_debug_sector_size)) && - (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) + return DID_ERROR << 16; + } else if (sdebug_verbose && (ret < (num * sdebug_sector_size))) sdev_printk(KERN_INFO, scp->device, "%s: %s: cdb indicated=%u, IO sent=%d bytes\n", my_name, "write same", - num * scsi_debug_sector_size, ret); + num * sdebug_sector_size, ret); /* Copy first sector to remaining blocks */ for (i = 1 ; i < num ; i++) - memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size), - fake_storep + (lba * scsi_debug_sector_size), - scsi_debug_sector_size); + memcpy(fake_storep + ((lba + i) * sdebug_sector_size), + fake_storep + lba_off, + sdebug_sector_size); if (scsi_debug_lbp()) map_region(lba, num); @@ -3042,7 +2956,7 @@ resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) bool unmap = false; if (cmd[1] & 0x8) { - if (scsi_debug_lbpws10 == 0) { + if (sdebug_lbpws10 == 0) { mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3); return check_condition_result; } else @@ -3050,7 +2964,7 @@ resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) } lba = get_unaligned_be32(cmd + 2); num = get_unaligned_be16(cmd + 7); - if (num > scsi_debug_write_same_length) { + if (num > sdebug_write_same_length) { mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1); return check_condition_result; } @@ -3068,7 +2982,7 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) bool ndob = false; if (cmd[1] & 0x8) { /* UNMAP */ - if (scsi_debug_lbpws == 0) { + if (sdebug_lbpws == 0) { mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3); return check_condition_result; } else @@ -3078,7 +2992,7 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) ndob = true; lba = get_unaligned_be64(cmd + 2); num = get_unaligned_be32(cmd + 10); - if (num > scsi_debug_write_same_length) { + if (num > sdebug_write_same_length) { mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1); return check_condition_result; } @@ -3142,7 +3056,7 @@ resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) u8 *fake_storep_hold; u64 lba; u32 dnum; - u32 lb_size = scsi_debug_sector_size; + u32 lb_size = sdebug_sector_size; u8 num; unsigned long iflags; int ret; @@ -3152,13 +3066,13 @@ resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) num = cmd[13]; /* 1 to a maximum of 255 logical blocks */ if (0 == num) return 0; /* degenerate case, not an error */ - if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && + if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && (cmd[1] & 0xe0)) { mk_sense_invalid_opcode(scp); return check_condition_result; } - if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || - scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && + if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION || + sdebug_dif == SD_DIF_TYPE3_PROTECTION) && (cmd[1] & 0xe0) == 0) sdev_printk(KERN_ERR, scp->device, "Unprotected WR " "to DIF device\n"); @@ -3193,8 +3107,7 @@ resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) if (ret == -1) { retval = DID_ERROR << 16; goto cleanup; - } else if ((ret < (dnum * lb_size)) && - (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) + } else if (sdebug_verbose && (ret < (dnum * lb_size))) sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb " "indicated=%u, IO sent=%d bytes\n", my_name, dnum * lb_size, ret); @@ -3233,7 +3146,7 @@ resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) BUG_ON(scsi_bufflen(scp) != payload_len); descriptors = (payload_len - 8) / 16; - if (descriptors > scsi_debug_unmap_max_desc) { + if (descriptors > sdebug_unmap_max_desc) { mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1); return check_condition_result; } @@ -3339,10 +3252,10 @@ static int resp_report_luns(struct scsi_cmnd * scp, } /* can produce response with up to 16k luns (lun 0 to lun 16383) */ memset(arr, 0, SDEBUG_RLUN_ARR_SZ); - lun_cnt = scsi_debug_max_luns; + lun_cnt = sdebug_max_luns; if (1 == select_report) lun_cnt = 0; - else if (scsi_debug_no_lun_0 && (lun_cnt > 0)) + else if (sdebug_no_lun_0 && (lun_cnt > 0)) --lun_cnt; want_wlun = (select_report > 0) ? 1 : 0; num = lun_cnt + want_wlun; @@ -3356,7 +3269,7 @@ static int resp_report_luns(struct scsi_cmnd * scp, } one_lun = (struct scsi_lun *) &arr[8]; max_addr = arr + SDEBUG_RLUN_ARR_SZ; - for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0); + for (i = 0, lun = (sdebug_no_lun_0 ? 1 : 0); ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr)); i++, lun++) { upper = (lun >> 8) & 0x3f; @@ -3486,7 +3399,7 @@ static void sdebug_q_cmd_complete(unsigned long indx) return; } k = find_last_bit(queued_in_use_bm, retval); - if ((k < scsi_debug_max_queue) || (k == retval)) + if ((k < sdebug_max_queue) || (k == retval)) atomic_set(&retired_max_queue, 0); else atomic_set(&retired_max_queue, k + 1); @@ -3546,7 +3459,7 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer) goto the_end; } k = find_last_bit(queued_in_use_bm, retval); - if ((k < scsi_debug_max_queue) || (k == retval)) + if ((k < sdebug_max_queue) || (k == retval)) atomic_set(&retired_max_queue, 0); else atomic_set(&retired_max_queue, k + 1); @@ -3614,7 +3527,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) static int scsi_debug_slave_alloc(struct scsi_device *sdp) { - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + if (sdebug_verbose) pr_info("slave_alloc <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue); @@ -3625,7 +3538,7 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp) { struct sdebug_dev_info *devip; - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + if (sdebug_verbose) pr_info("slave_configure <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) @@ -3635,7 +3548,7 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp) return 1; /* no resources, will be marked offline */ sdp->hostdata = devip; blk_queue_max_segment_size(sdp->request_queue, -1U); - if (scsi_debug_no_uld) + if (sdebug_no_uld) sdp->no_uld_attach = 1; return 0; } @@ -3645,7 +3558,7 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata; - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + if (sdebug_verbose) pr_info("slave_destroy <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (devip) { @@ -3664,7 +3577,7 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) struct sdebug_dev_info *devip; spin_lock_irqsave(&queued_arr_lock, iflags); - qmax = scsi_debug_max_queue; + qmax = sdebug_max_queue; r_qmax = atomic_read(&retired_max_queue); if (r_qmax > qmax) qmax = r_qmax; @@ -3679,15 +3592,15 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) sqcp->a_cmnd = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); - if (scsi_debug_ndelay > 0) { + if (sdebug_ndelay > 0) { if (sqcp->sd_hrtp) hrtimer_cancel( &sqcp->sd_hrtp->hrt); - } else if (scsi_debug_delay > 0) { + } else if (sdebug_delay > 0) { if (sqcp->cmnd_timerp) del_timer_sync( sqcp->cmnd_timerp); - } else if (scsi_debug_delay < 0) { + } else if (sdebug_delay < 0) { if (sqcp->tletp) tasklet_kill(sqcp->tletp); } @@ -3720,15 +3633,15 @@ static void stop_all_queued(void) sqcp->a_cmnd = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); - if (scsi_debug_ndelay > 0) { + if (sdebug_ndelay > 0) { if (sqcp->sd_hrtp) hrtimer_cancel( &sqcp->sd_hrtp->hrt); - } else if (scsi_debug_delay > 0) { + } else if (sdebug_delay > 0) { if (sqcp->cmnd_timerp) del_timer_sync( sqcp->cmnd_timerp); - } else if (scsi_debug_delay < 0) { + } else if (sdebug_delay < 0) { if (sqcp->tletp) tasklet_kill(sqcp->tletp); } @@ -3765,7 +3678,7 @@ static int scsi_debug_abort(struct scsi_cmnd *SCpnt) ++num_aborts; if (SCpnt) { if (SCpnt->device && - (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)) + (SDEBUG_OPT_ALL_NOISE & sdebug_opts)) sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__); stop_queued_cmnd(SCpnt); @@ -3781,7 +3694,7 @@ static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt) if (SCpnt && SCpnt->device) { struct scsi_device *sdp = SCpnt->device; - if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) + if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s\n", __func__); devip = devInfoReg(sdp); if (devip) @@ -3804,7 +3717,7 @@ static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt) sdp = SCpnt->device; if (!sdp) goto lie; - if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) + if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s\n", __func__); hp = sdp->host; if (!hp) @@ -3819,7 +3732,7 @@ static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt) ++k; } } - if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) + if (SDEBUG_OPT_RESET_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s: %d device(s) found in target\n", __func__, k); lie: @@ -3838,7 +3751,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) if (!(SCpnt && SCpnt->device)) goto lie; sdp = SCpnt->device; - if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) + if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s\n", __func__); hp = sdp->host; if (hp) { @@ -3852,7 +3765,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) } } } - if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) + if (SDEBUG_OPT_RESET_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s: %d device(s) found in host\n", __func__, k); lie: @@ -3866,7 +3779,7 @@ static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) int k = 0; ++num_host_resets; - if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)) + if ((SCpnt->device) && (SDEBUG_OPT_ALL_NOISE & sdebug_opts)) sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__); spin_lock(&sdebug_host_list_lock); list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { @@ -3878,7 +3791,7 @@ static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) } spin_unlock(&sdebug_host_list_lock); stop_all_queued(); - if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) + if (SDEBUG_OPT_RESET_NOISE & sdebug_opts) sdev_printk(KERN_INFO, SCpnt->device, "%s: %d device(s) found\n", __func__, k); return SUCCESS; @@ -3893,22 +3806,22 @@ static void __init sdebug_build_parts(unsigned char *ramp, int heads_by_sects, start_sec, end_sec; /* assume partition table already zeroed */ - if ((scsi_debug_num_parts < 1) || (store_size < 1048576)) + if ((sdebug_num_parts < 1) || (store_size < 1048576)) return; - if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) { - scsi_debug_num_parts = SDEBUG_MAX_PARTS; + if (sdebug_num_parts > SDEBUG_MAX_PARTS) { + sdebug_num_parts = SDEBUG_MAX_PARTS; pr_warn("reducing partitions to %d\n", SDEBUG_MAX_PARTS); } num_sectors = (int)sdebug_store_sectors; sectors_per_part = (num_sectors - sdebug_sectors_per) - / scsi_debug_num_parts; + / sdebug_num_parts; heads_by_sects = sdebug_heads * sdebug_sectors_per; starts[0] = sdebug_sectors_per; - for (k = 1; k < scsi_debug_num_parts; ++k) + for (k = 1; k < sdebug_num_parts; ++k) starts[k] = ((k * sectors_per_part) / heads_by_sects) * heads_by_sects; - starts[scsi_debug_num_parts] = num_sectors; - starts[scsi_debug_num_parts + 1] = 0; + starts[sdebug_num_parts] = num_sectors; + starts[sdebug_num_parts + 1] = 0; ramp[510] = 0x55; /* magic partition markings */ ramp[511] = 0xAA; @@ -3955,7 +3868,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, sdp = cmnd->device; - if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) + if (sdebug_verbose && scsi_result) sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", __func__, scsi_result); if (delta_jiff == 0) @@ -3972,29 +3885,29 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, goto respond_in_thread; } else scsi_result = device_qfull_result; - } else if ((scsi_debug_every_nth != 0) && - (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) && + } else if ((sdebug_every_nth != 0) && + (SDEBUG_OPT_RARE_TSF & sdebug_opts) && (scsi_result == 0)) { if ((num_in_q == (qdepth - 1)) && (atomic_inc_return(&sdebug_a_tsf) >= - abs(scsi_debug_every_nth))) { + abs(sdebug_every_nth))) { atomic_set(&sdebug_a_tsf, 0); inject = 1; scsi_result = device_qfull_result; } } - k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue); - if (k >= scsi_debug_max_queue) { + k = find_first_zero_bit(queued_in_use_bm, sdebug_max_queue); + if (k >= sdebug_max_queue) { spin_unlock_irqrestore(&queued_arr_lock, iflags); if (scsi_result) goto respond_in_thread; - else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts) + else if (SDEBUG_OPT_ALL_TSF & sdebug_opts) scsi_result = device_qfull_result; - if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) + if (SDEBUG_OPT_Q_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s: max_queue=%d exceeded, %s\n", - __func__, scsi_debug_max_queue, + __func__, sdebug_max_queue, (scsi_result ? "status: TASK SET FULL" : "report: host busy")); if (scsi_result) @@ -4020,8 +3933,8 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, sqcp->cmnd_timerp->data = k; sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff; add_timer(sqcp->cmnd_timerp); - } else if (scsi_debug_ndelay > 0) { - ktime_t kt = ktime_set(0, scsi_debug_ndelay); + } else if (sdebug_ndelay > 0) { + ktime_t kt = ktime_set(0, sdebug_ndelay); struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp; if (NULL == sd_hp) { @@ -4049,7 +3962,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, else tasklet_schedule(sqcp->tletp); } - if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) && + if ((SDEBUG_OPT_Q_NOISE & sdebug_opts) && (scsi_result == device_qfull_result)) sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, %s%s\n", __func__, @@ -4069,46 +3982,46 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, as it can when the corresponding attribute in the /sys/bus/pseudo/drivers/scsi_debug directory is changed. */ -module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR); -module_param_named(ato, scsi_debug_ato, int, S_IRUGO); -module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR); -module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR); -module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO); -module_param_named(dif, scsi_debug_dif, int, S_IRUGO); -module_param_named(dix, scsi_debug_dix, int, S_IRUGO); -module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR); -module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR); -module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR); -module_param_named(guard, scsi_debug_guard, uint, S_IRUGO); -module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR); -module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO); -module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO); -module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO); -module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO); -module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO); -module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR); -module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR); -module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR); -module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR); -module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO); -module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO); -module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR); -module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO); -module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR); -module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO); -module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR); -module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR); -module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO); -module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO); -module_param_named(strict, scsi_debug_strict, bool, S_IRUGO | S_IWUSR); -module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO); -module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO); -module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO); -module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO); -module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); -module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, +module_param_named(add_host, sdebug_add_host, int, S_IRUGO | S_IWUSR); +module_param_named(ato, sdebug_ato, int, S_IRUGO); +module_param_named(clustering, sdebug_clustering, bool, S_IRUGO | S_IWUSR); +module_param_named(delay, sdebug_delay, int, S_IRUGO | S_IWUSR); +module_param_named(dev_size_mb, sdebug_dev_size_mb, int, S_IRUGO); +module_param_named(dif, sdebug_dif, int, S_IRUGO); +module_param_named(dix, sdebug_dix, int, S_IRUGO); +module_param_named(dsense, sdebug_dsense, int, S_IRUGO | S_IWUSR); +module_param_named(every_nth, sdebug_every_nth, int, S_IRUGO | S_IWUSR); +module_param_named(fake_rw, sdebug_fake_rw, int, S_IRUGO | S_IWUSR); +module_param_named(guard, sdebug_guard, uint, S_IRUGO); +module_param_named(host_lock, sdebug_host_lock, bool, S_IRUGO | S_IWUSR); +module_param_named(lbpu, sdebug_lbpu, int, S_IRUGO); +module_param_named(lbpws, sdebug_lbpws, int, S_IRUGO); +module_param_named(lbpws10, sdebug_lbpws10, int, S_IRUGO); +module_param_named(lbprz, sdebug_lbprz, int, S_IRUGO); +module_param_named(lowest_aligned, sdebug_lowest_aligned, int, S_IRUGO); +module_param_named(max_luns, sdebug_max_luns, int, S_IRUGO | S_IWUSR); +module_param_named(max_queue, sdebug_max_queue, int, S_IRUGO | S_IWUSR); +module_param_named(ndelay, sdebug_ndelay, int, S_IRUGO | S_IWUSR); +module_param_named(no_lun_0, sdebug_no_lun_0, int, S_IRUGO | S_IWUSR); +module_param_named(no_uld, sdebug_no_uld, int, S_IRUGO); +module_param_named(num_parts, sdebug_num_parts, int, S_IRUGO); +module_param_named(num_tgts, sdebug_num_tgts, int, S_IRUGO | S_IWUSR); +module_param_named(opt_blks, sdebug_opt_blks, int, S_IRUGO); +module_param_named(opts, sdebug_opts, int, S_IRUGO | S_IWUSR); +module_param_named(physblk_exp, sdebug_physblk_exp, int, S_IRUGO); +module_param_named(ptype, sdebug_ptype, int, S_IRUGO | S_IWUSR); +module_param_named(removable, sdebug_removable, bool, S_IRUGO | S_IWUSR); +module_param_named(scsi_level, sdebug_scsi_level, int, S_IRUGO); +module_param_named(sector_size, sdebug_sector_size, int, S_IRUGO); +module_param_named(strict, sdebug_strict, bool, S_IRUGO | S_IWUSR); +module_param_named(unmap_alignment, sdebug_unmap_alignment, int, S_IRUGO); +module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO); +module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO); +module_param_named(unmap_max_desc, sdebug_unmap_max_desc, int, S_IRUGO); +module_param_named(virtual_gb, sdebug_virtual_gb, int, S_IRUGO | S_IWUSR); +module_param_named(vpd_use_hostno, sdebug_vpd_use_hostno, int, S_IRUGO | S_IWUSR); -module_param_named(write_same_length, scsi_debug_write_same_length, int, +module_param_named(write_same_length, sdebug_write_same_length, int, S_IRUGO | S_IWUSR); MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); @@ -4162,8 +4075,7 @@ static const char * scsi_debug_info(struct Scsi_Host * shp) { sprintf(sdebug_info, "scsi_debug, version %s [%s], " "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION, - scsi_debug_version_date, scsi_debug_dev_size_mb, - scsi_debug_opts); + sdebug_version_date, sdebug_dev_size_mb, sdebug_opts); return sdebug_info; } @@ -4180,8 +4092,10 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int lengt arr[minLen] = '\0'; if (1 != sscanf(arr, "%d", &opts)) return -EINVAL; - scsi_debug_opts = opts; - if (scsi_debug_every_nth != 0) + sdebug_opts = opts; + sdebug_verbose = !!(SDEBUG_OPT_NOISE & opts); + sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & opts); + if (sdebug_every_nth != 0) atomic_set(&sdebug_cmnd_count, 0); return length; } @@ -4194,9 +4108,9 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) int f, l; char b[32]; - if (scsi_debug_every_nth > 0) + if (sdebug_every_nth > 0) snprintf(b, sizeof(b), " (curr:%d)", - ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ? + ((SDEBUG_OPT_RARE_TSF & sdebug_opts) ? atomic_read(&sdebug_a_tsf) : atomic_read(&sdebug_cmnd_count))); else @@ -4210,18 +4124,18 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, " "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d " "usec_in_jiffy=%lu\n", - SCSI_DEBUG_VERSION, scsi_debug_version_date, - scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts, - scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay, - scsi_debug_max_luns, atomic_read(&sdebug_completions), - scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, + SCSI_DEBUG_VERSION, sdebug_version_date, + sdebug_num_tgts, sdebug_dev_size_mb, sdebug_opts, + sdebug_every_nth, b, sdebug_delay, sdebug_ndelay, + sdebug_max_luns, atomic_read(&sdebug_completions), + sdebug_sector_size, sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per, num_aborts, num_dev_resets, num_target_resets, num_bus_resets, num_host_resets, dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000); - f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue); - if (f != scsi_debug_max_queue) { - l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue); + f = find_first_bit(queued_in_use_bm, sdebug_max_queue); + if (f != sdebug_max_queue) { + l = find_last_bit(queued_in_use_bm, sdebug_max_queue); seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n", "queued_in_use_bm", f, l); } @@ -4230,7 +4144,7 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) static ssize_t delay_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_delay); } /* Returns -EBUSY if delay is being changed and commands are queued */ static ssize_t delay_store(struct device_driver *ddp, const char *buf, @@ -4240,18 +4154,17 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf, if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) { res = count; - if (scsi_debug_delay != delay) { + if (sdebug_delay != delay) { unsigned long iflags; int k; spin_lock_irqsave(&queued_arr_lock, iflags); - k = find_first_bit(queued_in_use_bm, - scsi_debug_max_queue); - if (k != scsi_debug_max_queue) + k = find_first_bit(queued_in_use_bm, sdebug_max_queue); + if (k != sdebug_max_queue) res = -EBUSY; /* have queued commands */ else { - scsi_debug_delay = delay; - scsi_debug_ndelay = 0; + sdebug_delay = delay; + sdebug_ndelay = 0; } spin_unlock_irqrestore(&queued_arr_lock, iflags); } @@ -4263,10 +4176,10 @@ static DRIVER_ATTR_RW(delay); static ssize_t ndelay_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_ndelay); } /* Returns -EBUSY if ndelay is being changed and commands are queued */ -/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */ +/* If > 0 and accepted then sdebug_delay is set to DELAY_OVERRIDDEN */ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, size_t count) { @@ -4276,15 +4189,14 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) && (ndelay >= 0) && (ndelay < 1000000000)) { res = count; - if (scsi_debug_ndelay != ndelay) { + if (sdebug_ndelay != ndelay) { spin_lock_irqsave(&queued_arr_lock, iflags); - k = find_first_bit(queued_in_use_bm, - scsi_debug_max_queue); - if (k != scsi_debug_max_queue) + k = find_first_bit(queued_in_use_bm, sdebug_max_queue); + if (k != sdebug_max_queue) res = -EBUSY; /* have queued commands */ else { - scsi_debug_ndelay = ndelay; - scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN + sdebug_ndelay = ndelay; + sdebug_delay = ndelay ? DELAY_OVERRIDDEN : DEF_DELAY; } spin_unlock_irqrestore(&queued_arr_lock, iflags); @@ -4297,7 +4209,7 @@ static DRIVER_ATTR_RW(ndelay); static ssize_t opts_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts); + return scnprintf(buf, PAGE_SIZE, "0x%x\n", sdebug_opts); } static ssize_t opts_store(struct device_driver *ddp, const char *buf, @@ -4317,17 +4229,9 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf, } return -EINVAL; opts_done: - scsi_debug_opts = opts; - if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts) - sdebug_any_injecting_opt = true; - else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts) - sdebug_any_injecting_opt = true; - else if (SCSI_DEBUG_OPT_DIF_ERR & opts) - sdebug_any_injecting_opt = true; - else if (SCSI_DEBUG_OPT_DIX_ERR & opts) - sdebug_any_injecting_opt = true; - else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts) - sdebug_any_injecting_opt = true; + sdebug_opts = opts; + sdebug_verbose = !!(SDEBUG_OPT_NOISE & opts); + sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & opts); atomic_set(&sdebug_cmnd_count, 0); atomic_set(&sdebug_a_tsf, 0); return count; @@ -4336,7 +4240,7 @@ static DRIVER_ATTR_RW(opts); static ssize_t ptype_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_ptype); } static ssize_t ptype_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4344,7 +4248,7 @@ static ssize_t ptype_store(struct device_driver *ddp, const char *buf, int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - scsi_debug_ptype = n; + sdebug_ptype = n; return count; } return -EINVAL; @@ -4353,7 +4257,7 @@ static DRIVER_ATTR_RW(ptype); static ssize_t dsense_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dsense); } static ssize_t dsense_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4361,7 +4265,7 @@ static ssize_t dsense_store(struct device_driver *ddp, const char *buf, int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - scsi_debug_dsense = n; + sdebug_dsense = n; return count; } return -EINVAL; @@ -4370,7 +4274,7 @@ static DRIVER_ATTR_RW(dsense); static ssize_t fake_rw_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_fake_rw); } static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4379,11 +4283,11 @@ static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { n = (n > 0); - scsi_debug_fake_rw = (scsi_debug_fake_rw > 0); - if (scsi_debug_fake_rw != n) { + sdebug_fake_rw = (sdebug_fake_rw > 0); + if (sdebug_fake_rw != n) { if ((0 == n) && (NULL == fake_storep)) { unsigned long sz = - (unsigned long)scsi_debug_dev_size_mb * + (unsigned long)sdebug_dev_size_mb * 1048576; fake_storep = vmalloc(sz); @@ -4393,7 +4297,7 @@ static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, } memset(fake_storep, 0, sz); } - scsi_debug_fake_rw = n; + sdebug_fake_rw = n; } return count; } @@ -4403,7 +4307,7 @@ static DRIVER_ATTR_RW(fake_rw); static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_no_lun_0); } static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4411,7 +4315,7 @@ static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf, int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - scsi_debug_no_lun_0 = n; + sdebug_no_lun_0 = n; return count; } return -EINVAL; @@ -4420,7 +4324,7 @@ static DRIVER_ATTR_RW(no_lun_0); static ssize_t num_tgts_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_num_tgts); } static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4428,7 +4332,7 @@ static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf, int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - scsi_debug_num_tgts = n; + sdebug_num_tgts = n; sdebug_max_tgts_luns(); return count; } @@ -4438,19 +4342,19 @@ static DRIVER_ATTR_RW(num_tgts); static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dev_size_mb); } static DRIVER_ATTR_RO(dev_size_mb); static ssize_t num_parts_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_num_parts); } static DRIVER_ATTR_RO(num_parts); static ssize_t every_nth_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_every_nth); } static ssize_t every_nth_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4458,7 +4362,7 @@ static ssize_t every_nth_store(struct device_driver *ddp, const char *buf, int nth; if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) { - scsi_debug_every_nth = nth; + sdebug_every_nth = nth; atomic_set(&sdebug_cmnd_count, 0); return count; } @@ -4468,7 +4372,7 @@ static DRIVER_ATTR_RW(every_nth); static ssize_t max_luns_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_max_luns); } static ssize_t max_luns_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4477,10 +4381,10 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf, bool changed; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - changed = (scsi_debug_max_luns != n); - scsi_debug_max_luns = n; + changed = (sdebug_max_luns != n); + sdebug_max_luns = n; sdebug_max_tgts_luns(); - if (changed && (scsi_debug_scsi_level >= 5)) { /* >= SPC-3 */ + if (changed && (sdebug_scsi_level >= 5)) { /* >= SPC-3 */ struct sdebug_host_info *sdhp; struct sdebug_dev_info *dp; @@ -4503,7 +4407,7 @@ static DRIVER_ATTR_RW(max_luns); static ssize_t max_queue_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_max_queue); } /* N.B. max_queue can be changed while there are queued commands. In flight * commands beyond the new max_queue will be completed. */ @@ -4517,7 +4421,7 @@ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, (n <= SCSI_DEBUG_CANQUEUE)) { spin_lock_irqsave(&queued_arr_lock, iflags); k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE); - scsi_debug_max_queue = n; + sdebug_max_queue = n; if (SCSI_DEBUG_CANQUEUE == k) atomic_set(&retired_max_queue, 0); else if (k >= n) @@ -4533,19 +4437,19 @@ static DRIVER_ATTR_RW(max_queue); static ssize_t no_uld_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_no_uld); } static DRIVER_ATTR_RO(no_uld); static ssize_t scsi_level_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_scsi_level); } static DRIVER_ATTR_RO(scsi_level); static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_virtual_gb); } static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4554,8 +4458,8 @@ static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf, bool changed; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - changed = (scsi_debug_virtual_gb != n); - scsi_debug_virtual_gb = n; + changed = (sdebug_virtual_gb != n); + sdebug_virtual_gb = n; sdebug_capacity = get_sdebug_capacity(); if (changed) { struct sdebug_host_info *sdhp; @@ -4580,7 +4484,7 @@ static DRIVER_ATTR_RW(virtual_gb); static ssize_t add_host_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_add_host); } static ssize_t add_host_store(struct device_driver *ddp, const char *buf, @@ -4605,7 +4509,7 @@ static DRIVER_ATTR_RW(add_host); static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_vpd_use_hostno); } static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4613,7 +4517,7 @@ static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf, int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - scsi_debug_vpd_use_hostno = n; + sdebug_vpd_use_hostno = n; return count; } return -EINVAL; @@ -4622,31 +4526,31 @@ static DRIVER_ATTR_RW(vpd_use_hostno); static ssize_t sector_size_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size); + return scnprintf(buf, PAGE_SIZE, "%u\n", sdebug_sector_size); } static DRIVER_ATTR_RO(sector_size); static ssize_t dix_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dix); } static DRIVER_ATTR_RO(dix); static ssize_t dif_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dif); } static DRIVER_ATTR_RO(dif); static ssize_t guard_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard); + return scnprintf(buf, PAGE_SIZE, "%u\n", sdebug_guard); } static DRIVER_ATTR_RO(guard); static ssize_t ato_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_ato); } static DRIVER_ATTR_RO(ato); @@ -4669,7 +4573,7 @@ static DRIVER_ATTR_RO(map); static ssize_t removable_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_removable ? 1 : 0); } static ssize_t removable_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4677,7 +4581,7 @@ static ssize_t removable_store(struct device_driver *ddp, const char *buf, int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - scsi_debug_removable = (n > 0); + sdebug_removable = (n > 0); return count; } return -EINVAL; @@ -4686,7 +4590,7 @@ static DRIVER_ATTR_RW(removable); static ssize_t host_lock_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock); + return scnprintf(buf, PAGE_SIZE, "%d\n", !!sdebug_host_lock); } /* Returns -EBUSY if host_lock is being changed and commands are queued */ static ssize_t host_lock_store(struct device_driver *ddp, const char *buf, @@ -4698,17 +4602,17 @@ static ssize_t host_lock_store(struct device_driver *ddp, const char *buf, bool new_host_lock = (n > 0); res = count; - if (new_host_lock != scsi_debug_host_lock) { + if (new_host_lock != sdebug_host_lock) { unsigned long iflags; int k; spin_lock_irqsave(&queued_arr_lock, iflags); k = find_first_bit(queued_in_use_bm, - scsi_debug_max_queue); - if (k != scsi_debug_max_queue) + sdebug_max_queue); + if (k != sdebug_max_queue) res = -EBUSY; /* have queued commands */ else - scsi_debug_host_lock = new_host_lock; + sdebug_host_lock = new_host_lock; spin_unlock_irqrestore(&queued_arr_lock, iflags); } return res; @@ -4719,7 +4623,7 @@ static DRIVER_ATTR_RW(host_lock); static ssize_t strict_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_strict); + return scnprintf(buf, PAGE_SIZE, "%d\n", !!sdebug_strict); } static ssize_t strict_store(struct device_driver *ddp, const char *buf, size_t count) @@ -4727,7 +4631,7 @@ static ssize_t strict_store(struct device_driver *ddp, const char *buf, int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - scsi_debug_strict = (n > 0); + sdebug_strict = (n > 0); return count; } return -EINVAL; @@ -4787,24 +4691,24 @@ static int __init scsi_debug_init(void) atomic_set(&sdebug_completions, 0); atomic_set(&retired_max_queue, 0); - if (scsi_debug_ndelay >= 1000000000) { + if (sdebug_ndelay >= 1000 * 1000 * 1000) { pr_warn("ndelay must be less than 1 second, ignored\n"); - scsi_debug_ndelay = 0; - } else if (scsi_debug_ndelay > 0) - scsi_debug_delay = DELAY_OVERRIDDEN; + sdebug_ndelay = 0; + } else if (sdebug_ndelay > 0) + sdebug_delay = DELAY_OVERRIDDEN; - switch (scsi_debug_sector_size) { + switch (sdebug_sector_size) { case 512: case 1024: case 2048: case 4096: break; default: - pr_err("invalid sector_size %d\n", scsi_debug_sector_size); + pr_err("invalid sector_size %d\n", sdebug_sector_size); return -EINVAL; } - switch (scsi_debug_dif) { + switch (sdebug_dif) { case SD_DIF_TYPE0_PROTECTION: case SD_DIF_TYPE1_PROTECTION: @@ -4817,39 +4721,38 @@ static int __init scsi_debug_init(void) return -EINVAL; } - if (scsi_debug_guard > 1) { + if (sdebug_guard > 1) { pr_err("guard must be 0 or 1\n"); return -EINVAL; } - if (scsi_debug_ato > 1) { + if (sdebug_ato > 1) { pr_err("ato must be 0 or 1\n"); return -EINVAL; } - if (scsi_debug_physblk_exp > 15) { - pr_err("invalid physblk_exp %u\n", scsi_debug_physblk_exp); + if (sdebug_physblk_exp > 15) { + pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp); return -EINVAL; } - if (scsi_debug_lowest_aligned > 0x3fff) { - pr_err("lowest_aligned too big: %u\n", - scsi_debug_lowest_aligned); + if (sdebug_lowest_aligned > 0x3fff) { + pr_err("lowest_aligned too big: %u\n", sdebug_lowest_aligned); return -EINVAL; } - if (scsi_debug_dev_size_mb < 1) - scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ - sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; - sdebug_store_sectors = sz / scsi_debug_sector_size; + if (sdebug_dev_size_mb < 1) + sdebug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ + sz = (unsigned long)sdebug_dev_size_mb * 1048576; + sdebug_store_sectors = sz / sdebug_sector_size; sdebug_capacity = get_sdebug_capacity(); /* play around with geometry, don't waste too much on track 0 */ sdebug_heads = 8; sdebug_sectors_per = 32; - if (scsi_debug_dev_size_mb >= 256) + if (sdebug_dev_size_mb >= 256) sdebug_heads = 64; - else if (scsi_debug_dev_size_mb >= 16) + else if (sdebug_dev_size_mb >= 16) sdebug_heads = 32; sdebug_cylinders_per = (unsigned long)sdebug_capacity / (sdebug_sectors_per * sdebug_heads); @@ -4861,18 +4764,18 @@ static int __init scsi_debug_init(void) (sdebug_sectors_per * sdebug_heads); } - if (0 == scsi_debug_fake_rw) { + if (0 == sdebug_fake_rw) { fake_storep = vmalloc(sz); if (NULL == fake_storep) { pr_err("out of memory, 1\n"); return -ENOMEM; } memset(fake_storep, 0, sz); - if (scsi_debug_num_parts > 0) + if (sdebug_num_parts > 0) sdebug_build_parts(fake_storep, sz); } - if (scsi_debug_dix) { + if (sdebug_dix) { int dif_size; dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); @@ -4891,18 +4794,18 @@ static int __init scsi_debug_init(void) /* Logical Block Provisioning */ if (scsi_debug_lbp()) { - scsi_debug_unmap_max_blocks = - clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU); + sdebug_unmap_max_blocks = + clamp(sdebug_unmap_max_blocks, 0U, 0xffffffffU); - scsi_debug_unmap_max_desc = - clamp(scsi_debug_unmap_max_desc, 0U, 256U); + sdebug_unmap_max_desc = + clamp(sdebug_unmap_max_desc, 0U, 256U); - scsi_debug_unmap_granularity = - clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU); + sdebug_unmap_granularity = + clamp(sdebug_unmap_granularity, 1U, 0xffffffffU); - if (scsi_debug_unmap_alignment && - scsi_debug_unmap_granularity <= - scsi_debug_unmap_alignment) { + if (sdebug_unmap_alignment && + sdebug_unmap_granularity <= + sdebug_unmap_alignment) { pr_err("ERR: unmap_granularity <= unmap_alignment\n"); return -EINVAL; } @@ -4921,7 +4824,7 @@ static int __init scsi_debug_init(void) bitmap_zero(map_storep, map_size); /* Map first 1KB for partition table */ - if (scsi_debug_num_parts) + if (sdebug_num_parts) map_region(0, 2); } @@ -4942,8 +4845,8 @@ static int __init scsi_debug_init(void) goto bus_unreg; } - host_to_add = scsi_debug_add_host; - scsi_debug_add_host = 0; + host_to_add = sdebug_add_host; + sdebug_add_host = 0; for (k = 0; k < host_to_add; k++) { if (sdebug_add_adapter()) { @@ -4952,8 +4855,8 @@ static int __init scsi_debug_init(void) } } - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - pr_info("built %d host(s)\n", scsi_debug_add_host); + if (sdebug_verbose) + pr_info("built %d host(s)\n", sdebug_add_host); return 0; @@ -4971,7 +4874,7 @@ static int __init scsi_debug_init(void) static void __exit scsi_debug_exit(void) { - int k = scsi_debug_add_host; + int k = sdebug_add_host; stop_all_queued(); free_all_queued(); @@ -5011,7 +4914,7 @@ static int sdebug_add_adapter(void) INIT_LIST_HEAD(&sdbg_host->dev_info_list); - devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns; + devs_per_host = sdebug_num_tgts * sdebug_max_luns; for (k = 0; k < devs_per_host; k++) { sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL); if (!sdbg_devinfo) { @@ -5028,14 +4931,14 @@ static int sdebug_add_adapter(void) sdbg_host->dev.bus = &pseudo_lld_bus; sdbg_host->dev.parent = pseudo_primary; sdbg_host->dev.release = &sdebug_release_adapter; - dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host); + dev_set_name(&sdbg_host->dev, "adapter%d", sdebug_add_host); error = device_register(&sdbg_host->dev); if (error) goto clean; - ++scsi_debug_add_host; + ++sdebug_add_host; return error; clean: @@ -5064,8 +4967,8 @@ static void sdebug_remove_adapter(void) if (!sdbg_host) return; - device_unregister(&sdbg_host->dev); - --scsi_debug_add_host; + device_unregister(&sdbg_host->dev); + --sdebug_add_host; } static int @@ -5091,7 +4994,7 @@ sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) qdepth = SCSI_DEBUG_CANQUEUE + 10; scsi_change_queue_depth(sdev, qdepth); - if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { + if (SDEBUG_OPT_Q_NOISE & sdebug_opts) { sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d, num_in_q=%d\n", __func__, qdepth, num_in_q); @@ -5106,28 +5009,25 @@ check_inject(struct scsi_cmnd *scp) memset(ep, 0, sizeof(struct sdebug_scmd_extra_t)); - if (atomic_inc_return(&sdebug_cmnd_count) >= - abs(scsi_debug_every_nth)) { + if (atomic_inc_return(&sdebug_cmnd_count) >= abs(sdebug_every_nth)) { atomic_set(&sdebug_cmnd_count, 0); - if (scsi_debug_every_nth < -1) - scsi_debug_every_nth = -1; - if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) + if (sdebug_every_nth < -1) + sdebug_every_nth = -1; + if (SDEBUG_OPT_TIMEOUT & sdebug_opts) return 1; /* ignore command causing timeout */ - else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts && + else if (SDEBUG_OPT_MAC_TIMEOUT & sdebug_opts && scsi_medium_access_command(scp)) return 1; /* time out reads and writes */ if (sdebug_any_injecting_opt) { - int opts = scsi_debug_opts; - - if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts) + if (SDEBUG_OPT_RECOVERED_ERR & sdebug_opts) ep->inj_recovered = true; - else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts) + if (SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts) ep->inj_transport = true; - else if (SCSI_DEBUG_OPT_DIF_ERR & opts) + if (SDEBUG_OPT_DIF_ERR & sdebug_opts) ep->inj_dif = true; - else if (SCSI_DEBUG_OPT_DIX_ERR & opts) + if (SDEBUG_OPT_DIX_ERR & sdebug_opts) ep->inj_dix = true; - else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts) + if (SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts) ep->inj_short = true; } } @@ -5146,15 +5046,13 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp) int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *); int k, na; int errsts = 0; - int errsts_no_connect = DID_NO_CONNECT << 16; u32 flags; u16 sa; u8 opcode = cmd[0]; bool has_wlun_rl; - bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts); scsi_set_resid(scp, 0); - if (debug && !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) { + if (sdebug_verbose && !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts)) { char b[120]; int n, len, sb; @@ -5170,8 +5068,8 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp) sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b); } has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS); - if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl) - return schedule_resp(scp, NULL, errsts_no_connect, 0); + if ((sdp->lun >= sdebug_max_luns) && !has_wlun_rl) + return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, 0); sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */ oip = &opcode_info_arr[sdeb_i]; /* safe if table consistent */ @@ -5179,7 +5077,8 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp) if (!devip) { devip = devInfoReg(sdp); if (NULL == devip) - return schedule_resp(scp, NULL, errsts_no_connect, 0); + return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, + 0); } na = oip->num_attached; r_pfp = oip->pfp; @@ -5216,13 +5115,13 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp) goto check_cond; } if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) { - if (debug) - sdev_printk(KERN_INFO, sdp, "scsi_debug: Opcode: " - "0x%x not supported for wlun\n", opcode); + if (sdebug_verbose) + sdev_printk(KERN_INFO, sdp, "%s: Opcode 0x%x not%s\n", + my_name, opcode, " supported for wlun"); mk_sense_invalid_opcode(scp); goto check_cond; } - if (scsi_debug_strict) { /* check cdb against mask */ + if (sdebug_strict) { /* check cdb against mask */ u8 rem; int j; @@ -5246,16 +5145,16 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp) } if ((F_M_ACCESS & flags) && devip->stopped) { mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); - if (debug) + if (sdebug_verbose) sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: " "%s\n", my_name, "initializing command " "required"); errsts = check_condition_result; goto fini; } - if (scsi_debug_fake_rw && (F_FAKE_RW & flags)) + if (sdebug_fake_rw && (F_FAKE_RW & flags)) goto fini; - if (scsi_debug_every_nth) { + if (sdebug_every_nth) { if (check_inject(scp)) return 0; /* ignore command: make trouble */ } @@ -5266,7 +5165,7 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp) fini: return schedule_resp(scp, devip, errsts, - ((F_DELAY_OVERR & flags) ? 0 : scsi_debug_delay)); + ((F_DELAY_OVERR & flags) ? 0 : sdebug_delay)); check_cond: return schedule_resp(scp, devip, check_condition_result, 0); } @@ -5274,7 +5173,7 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp) static int sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd) { - if (scsi_debug_host_lock) { + if (sdebug_host_lock) { unsigned long iflags; int rc; @@ -5317,15 +5216,14 @@ static struct scsi_host_template sdebug_driver_template = { static int sdebug_driver_probe(struct device * dev) { int error = 0; - int opts; struct sdebug_host_info *sdbg_host; struct Scsi_Host *hpnt; int host_prot; sdbg_host = to_sdebug_host(dev); - sdebug_driver_template.can_queue = scsi_debug_max_queue; - if (scsi_debug_clustering) + sdebug_driver_template.can_queue = sdebug_max_queue; + if (sdebug_clustering) sdebug_driver_template.use_clustering = ENABLE_CLUSTERING; hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); if (NULL == hpnt) { @@ -5336,37 +5234,37 @@ static int sdebug_driver_probe(struct device * dev) sdbg_host->shost = hpnt; *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; - if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id)) - hpnt->max_id = scsi_debug_num_tgts + 1; + if ((hpnt->this_id >= 0) && (sdebug_num_tgts > hpnt->this_id)) + hpnt->max_id = sdebug_num_tgts + 1; else - hpnt->max_id = scsi_debug_num_tgts; - /* = scsi_debug_max_luns; */ + hpnt->max_id = sdebug_num_tgts; + /* = sdebug_max_luns; */ hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1; host_prot = 0; - switch (scsi_debug_dif) { + switch (sdebug_dif) { case SD_DIF_TYPE1_PROTECTION: host_prot = SHOST_DIF_TYPE1_PROTECTION; - if (scsi_debug_dix) + if (sdebug_dix) host_prot |= SHOST_DIX_TYPE1_PROTECTION; break; case SD_DIF_TYPE2_PROTECTION: host_prot = SHOST_DIF_TYPE2_PROTECTION; - if (scsi_debug_dix) + if (sdebug_dix) host_prot |= SHOST_DIX_TYPE2_PROTECTION; break; case SD_DIF_TYPE3_PROTECTION: host_prot = SHOST_DIF_TYPE3_PROTECTION; - if (scsi_debug_dix) + if (sdebug_dix) host_prot |= SHOST_DIX_TYPE3_PROTECTION; break; default: - if (scsi_debug_dix) + if (sdebug_dix) host_prot |= SHOST_DIX_TYPE0_PROTECTION; break; } @@ -5382,23 +5280,13 @@ static int sdebug_driver_probe(struct device * dev) (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "", (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : ""); - if (scsi_debug_guard == 1) + if (sdebug_guard == 1) scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP); else scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC); - opts = scsi_debug_opts; - if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts) - sdebug_any_injecting_opt = true; - else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts) - sdebug_any_injecting_opt = true; - else if (SCSI_DEBUG_OPT_DIF_ERR & opts) - sdebug_any_injecting_opt = true; - else if (SCSI_DEBUG_OPT_DIX_ERR & opts) - sdebug_any_injecting_opt = true; - else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts) - sdebug_any_injecting_opt = true; - + sdebug_verbose = !!(SDEBUG_OPT_NOISE & sdebug_opts); + sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & sdebug_opts); error = scsi_add_host(hpnt, &sdbg_host->dev); if (error) { pr_err("scsi_add_host failed\n"); From 185dd2329785981d458690c78fd56b320fef4ea7 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Mon, 25 Apr 2016 12:16:29 -0400 Subject: [PATCH 113/138] scsi_debug: ignore host lock option Remove logic to optionally hold host_lock while each command is queued. Keep module and sysfs host_lock parameters for backward compatibility. Note in module parameter description that host_lock is ignored. Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 44 +++++++-------------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index ac74cbde7adf..88bfe0fb72ee 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -4040,7 +4040,7 @@ MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)"); MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)"); MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)"); MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); -MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)"); +MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)"); MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)"); MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)"); MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)"); @@ -4592,30 +4592,15 @@ static ssize_t host_lock_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", !!sdebug_host_lock); } -/* Returns -EBUSY if host_lock is being changed and commands are queued */ +/* N.B. sdebug_host_lock does nothing, kept for backward compatibility */ static ssize_t host_lock_store(struct device_driver *ddp, const char *buf, size_t count) { - int n, res; + int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - bool new_host_lock = (n > 0); - - res = count; - if (new_host_lock != sdebug_host_lock) { - unsigned long iflags; - int k; - - spin_lock_irqsave(&queued_arr_lock, iflags); - k = find_first_bit(queued_in_use_bm, - sdebug_max_queue); - if (k != sdebug_max_queue) - res = -EBUSY; /* have queued commands */ - else - sdebug_host_lock = new_host_lock; - spin_unlock_irqrestore(&queued_arr_lock, iflags); - } - return res; + sdebug_host_lock = (n > 0); + return count; } return -EINVAL; } @@ -5035,7 +5020,7 @@ check_inject(struct scsi_cmnd *scp) } static int -scsi_debug_queuecommand(struct scsi_cmnd *scp) +scsi_debug_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scp) { u8 sdeb_i; struct scsi_device *sdp = scp->device; @@ -5170,21 +5155,6 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp) return schedule_resp(scp, devip, check_condition_result, 0); } -static int -sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd) -{ - if (sdebug_host_lock) { - unsigned long iflags; - int rc; - - spin_lock_irqsave(shost->host_lock, iflags); - rc = scsi_debug_queuecommand(cmd); - spin_unlock_irqrestore(shost->host_lock, iflags); - return rc; - } else - return scsi_debug_queuecommand(cmd); -} - static struct scsi_host_template sdebug_driver_template = { .show_info = scsi_debug_show_info, .write_info = scsi_debug_write_info, @@ -5195,7 +5165,7 @@ static struct scsi_host_template sdebug_driver_template = { .slave_configure = scsi_debug_slave_configure, .slave_destroy = scsi_debug_slave_destroy, .ioctl = scsi_debug_ioctl, - .queuecommand = sdebug_queuecommand_lock_or_not, + .queuecommand = scsi_debug_queuecommand, .change_queue_depth = sdebug_change_qdepth, .eh_abort_handler = scsi_debug_abort, .eh_device_reset_handler = scsi_debug_device_reset, From b333a819813c756804034c93b05e43ccdd4025a5 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Mon, 25 Apr 2016 12:16:30 -0400 Subject: [PATCH 114/138] scsi_debug: replace jiffy timers with hr timers The driver supports two command delay interfaces, the original one whose unit is a jiffy, and a newer one whose unit is a nanosecond. Each had different implementations. Keep both interfaces but simplify the implemenation to use a single delay mechanism based on high resolution timers. Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 56 +++++++++++++++------------------------ 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 88bfe0fb72ee..90cd62e03337 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -518,7 +518,7 @@ struct sdebug_scmd_extra_t { static int sdebug_add_host = DEF_NUM_HOST; static int sdebug_ato = DEF_ATO; -static int sdebug_delay = DEF_DELAY; +static int sdebug_delay = DEF_DELAY; /* in jiffies */ static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB; static int sdebug_dif = DEF_DIF; static int sdebug_dix = DEF_DIX; @@ -530,7 +530,7 @@ static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED; static int sdebug_max_luns = DEF_MAX_LUNS; static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE; static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ -static int sdebug_ndelay = DEF_NDELAY; +static int sdebug_ndelay = DEF_NDELAY; /* in nanoseconds */ static int sdebug_no_lun_0 = DEF_NO_LUN_0; static int sdebug_no_uld; static int sdebug_num_parts = DEF_NUM_PARTS; @@ -617,7 +617,6 @@ struct sdebug_hrtimer { /* ... is derived from hrtimer */ struct sdebug_queued_cmd { /* in_use flagged by a bit in queued_in_use_bm[] */ - struct timer_list *cmnd_timerp; struct tasklet_struct *tletp; struct sdebug_hrtimer *sd_hrtp; struct scsi_cmnd * a_cmnd; @@ -3151,7 +3150,7 @@ resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return check_condition_result; } - buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); + buf = kzalloc(scsi_bufflen(scp), GFP_ATOMIC); if (!buf) { mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, INSUFF_RES_ASCQ); @@ -3298,7 +3297,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, struct sg_mapping_iter miter; /* better not to use temporary buffer. */ - buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); + buf = kzalloc(scsi_bufflen(scp), GFP_ATOMIC); if (!buf) { mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, INSUFF_RES_ASCQ); @@ -3350,7 +3349,7 @@ resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return resp_xdwriteread(scp, lba, num, devip); } -/* When timer or tasklet goes off this function is called. */ +/* When tasklet goes off this function is called. */ static void sdebug_q_cmd_complete(unsigned long indx) { int qa_indx; @@ -3592,14 +3591,11 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) sqcp->a_cmnd = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); - if (sdebug_ndelay > 0) { + if ((sdebug_delay > 0) || + (sdebug_ndelay > 0)) { if (sqcp->sd_hrtp) hrtimer_cancel( &sqcp->sd_hrtp->hrt); - } else if (sdebug_delay > 0) { - if (sqcp->cmnd_timerp) - del_timer_sync( - sqcp->cmnd_timerp); } else if (sdebug_delay < 0) { if (sqcp->tletp) tasklet_kill(sqcp->tletp); @@ -3633,14 +3629,11 @@ static void stop_all_queued(void) sqcp->a_cmnd = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); - if (sdebug_ndelay > 0) { + if ((sdebug_delay > 0) || + (sdebug_ndelay > 0)) { if (sqcp->sd_hrtp) hrtimer_cancel( &sqcp->sd_hrtp->hrt); - } else if (sdebug_delay > 0) { - if (sqcp->cmnd_timerp) - del_timer_sync( - sqcp->cmnd_timerp); } else if (sdebug_delay < 0) { if (sqcp->tletp) tasklet_kill(sqcp->tletp); @@ -3663,8 +3656,6 @@ static void free_all_queued(void) spin_lock_irqsave(&queued_arr_lock, iflags); for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { sqcp = &queued_arr[k]; - kfree(sqcp->cmnd_timerp); - sqcp->cmnd_timerp = NULL; kfree(sqcp->tletp); sqcp->tletp = NULL; kfree(sqcp->sd_hrtp); @@ -3921,24 +3912,19 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, sqcp->a_cmnd = cmnd; cmnd->result = scsi_result; spin_unlock_irqrestore(&queued_arr_lock, iflags); - if (delta_jiff > 0) { - if (NULL == sqcp->cmnd_timerp) { - sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list), - GFP_ATOMIC); - if (NULL == sqcp->cmnd_timerp) - return SCSI_MLQUEUE_HOST_BUSY; - init_timer(sqcp->cmnd_timerp); - } - sqcp->cmnd_timerp->function = sdebug_q_cmd_complete; - sqcp->cmnd_timerp->data = k; - sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff; - add_timer(sqcp->cmnd_timerp); - } else if (sdebug_ndelay > 0) { - ktime_t kt = ktime_set(0, sdebug_ndelay); + if ((delta_jiff > 0) || (sdebug_ndelay > 0)) { struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp; + ktime_t kt; + if (delta_jiff > 0) { + struct timespec ts; + + jiffies_to_timespec(delta_jiff, &ts); + kt = ktime_set(ts.tv_sec, ts.tv_nsec); + } else + kt = ktime_set(0, sdebug_ndelay); if (NULL == sd_hp) { - sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC); + sd_hp = kzalloc(sizeof(*sd_hp), GFP_ATOMIC); if (NULL == sd_hp) return SCSI_MLQUEUE_HOST_BUSY; sqcp->sd_hrtp = sd_hp; @@ -3950,7 +3936,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL); } else { /* delay < 0 */ if (NULL == sqcp->tletp) { - sqcp->tletp = kmalloc(sizeof(*sqcp->tletp), + sqcp->tletp = kzalloc(sizeof(*sqcp->tletp), GFP_ATOMIC); if (NULL == sqcp->tletp) return SCSI_MLQUEUE_HOST_BUSY; From c2206098972e8ca464040897c95bdf5b2f45ac32 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Mon, 25 Apr 2016 12:16:31 -0400 Subject: [PATCH 115/138] scsi_debug: make jiffy delay name clearer Add 'j' to delay names to make it clearer that its unit is jiffies and to differentiate it from sdebug_ndelay whose unit is nanoseconds. Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 90cd62e03337..e2fbac3b32aa 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -104,7 +104,7 @@ static const char *sdebug_version_date = "20160422"; * (id 0) containing 1 logical unit (lun 0). That is 1 device. */ #define DEF_ATO 1 -#define DEF_DELAY 1 /* if > 0 unit is a jiffy */ +#define DEF_JDELAY 1 /* if > 0 unit is a jiffy */ #define DEF_DEV_SIZE_MB 8 #define DEF_DIF 0 #define DEF_DIX 0 @@ -136,7 +136,7 @@ static const char *sdebug_version_date = "20160422"; #define DEF_VPD_USE_HOSTNO 1 #define DEF_WRITESAME_LENGTH 0xFFFF #define DEF_STRICT 0 -#define DELAY_OVERRIDDEN -9999 +#define JDELAY_OVERRIDDEN -9999 /* bit mask values for sdebug_opts */ #define SDEBUG_OPT_NOISE 1 @@ -206,7 +206,7 @@ static const char *sdebug_version_date = "20160422"; /* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued * (for response) at one time. Can be reduced by max_queue option. Command - * responses are not queued when delay=0 and ndelay=0. The per-device + * responses are not queued when jdelay=0 and ndelay=0. The per-device * DEF_CMD_PER_LUN can be changed via sysfs: * /sys/class/scsi_device//device/queue_depth but cannot exceed * SCSI_DEBUG_CANQUEUE. */ @@ -518,7 +518,7 @@ struct sdebug_scmd_extra_t { static int sdebug_add_host = DEF_NUM_HOST; static int sdebug_ato = DEF_ATO; -static int sdebug_delay = DEF_DELAY; /* in jiffies */ +static int sdebug_jdelay = DEF_JDELAY; /* if > 0 then unit is jiffies */ static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB; static int sdebug_dif = DEF_DIF; static int sdebug_dix = DEF_DIX; @@ -530,7 +530,7 @@ static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED; static int sdebug_max_luns = DEF_MAX_LUNS; static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE; static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ -static int sdebug_ndelay = DEF_NDELAY; /* in nanoseconds */ +static int sdebug_ndelay = DEF_NDELAY; /* if > 0 then unit is nanoseconds */ static int sdebug_no_lun_0 = DEF_NO_LUN_0; static int sdebug_no_uld; static int sdebug_num_parts = DEF_NUM_PARTS; @@ -3591,12 +3591,12 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) sqcp->a_cmnd = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); - if ((sdebug_delay > 0) || + if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) { if (sqcp->sd_hrtp) hrtimer_cancel( &sqcp->sd_hrtp->hrt); - } else if (sdebug_delay < 0) { + } else if (sdebug_jdelay < 0) { if (sqcp->tletp) tasklet_kill(sqcp->tletp); } @@ -3629,12 +3629,12 @@ static void stop_all_queued(void) sqcp->a_cmnd = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); - if ((sdebug_delay > 0) || + if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) { if (sqcp->sd_hrtp) hrtimer_cancel( &sqcp->sd_hrtp->hrt); - } else if (sdebug_delay < 0) { + } else if (sdebug_jdelay < 0) { if (sqcp->tletp) tasklet_kill(sqcp->tletp); } @@ -3934,7 +3934,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, sd_hp->qa_indx = k; } hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL); - } else { /* delay < 0 */ + } else { /* jdelay < 0 */ if (NULL == sqcp->tletp) { sqcp->tletp = kzalloc(sizeof(*sqcp->tletp), GFP_ATOMIC); @@ -3971,7 +3971,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, module_param_named(add_host, sdebug_add_host, int, S_IRUGO | S_IWUSR); module_param_named(ato, sdebug_ato, int, S_IRUGO); module_param_named(clustering, sdebug_clustering, bool, S_IRUGO | S_IWUSR); -module_param_named(delay, sdebug_delay, int, S_IRUGO | S_IWUSR); +module_param_named(delay, sdebug_jdelay, int, S_IRUGO | S_IWUSR); module_param_named(dev_size_mb, sdebug_dev_size_mb, int, S_IRUGO); module_param_named(dif, sdebug_dif, int, S_IRUGO); module_param_named(dix, sdebug_dix, int, S_IRUGO); @@ -4112,7 +4112,7 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) "usec_in_jiffy=%lu\n", SCSI_DEBUG_VERSION, sdebug_version_date, sdebug_num_tgts, sdebug_dev_size_mb, sdebug_opts, - sdebug_every_nth, b, sdebug_delay, sdebug_ndelay, + sdebug_every_nth, b, sdebug_jdelay, sdebug_ndelay, sdebug_max_luns, atomic_read(&sdebug_completions), sdebug_sector_size, sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per, num_aborts, num_dev_resets, @@ -4130,17 +4130,17 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) static ssize_t delay_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_delay); + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_jdelay); } -/* Returns -EBUSY if delay is being changed and commands are queued */ +/* Returns -EBUSY if jdelay is being changed and commands are queued */ static ssize_t delay_store(struct device_driver *ddp, const char *buf, size_t count) { - int delay, res; + int jdelay, res; - if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) { + if ((count > 0) && (1 == sscanf(buf, "%d", &jdelay))) { res = count; - if (sdebug_delay != delay) { + if (sdebug_jdelay != jdelay) { unsigned long iflags; int k; @@ -4149,7 +4149,7 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf, if (k != sdebug_max_queue) res = -EBUSY; /* have queued commands */ else { - sdebug_delay = delay; + sdebug_jdelay = jdelay; sdebug_ndelay = 0; } spin_unlock_irqrestore(&queued_arr_lock, iflags); @@ -4165,7 +4165,7 @@ static ssize_t ndelay_show(struct device_driver *ddp, char *buf) return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_ndelay); } /* Returns -EBUSY if ndelay is being changed and commands are queued */ -/* If > 0 and accepted then sdebug_delay is set to DELAY_OVERRIDDEN */ +/* If > 0 and accepted then sdebug_jdelay is set to JDELAY_OVERRIDDEN */ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, size_t count) { @@ -4182,8 +4182,8 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, res = -EBUSY; /* have queued commands */ else { sdebug_ndelay = ndelay; - sdebug_delay = ndelay ? DELAY_OVERRIDDEN - : DEF_DELAY; + sdebug_jdelay = ndelay ? JDELAY_OVERRIDDEN + : DEF_JDELAY; } spin_unlock_irqrestore(&queued_arr_lock, iflags); } @@ -4666,7 +4666,7 @@ static int __init scsi_debug_init(void) pr_warn("ndelay must be less than 1 second, ignored\n"); sdebug_ndelay = 0; } else if (sdebug_ndelay > 0) - sdebug_delay = DELAY_OVERRIDDEN; + sdebug_jdelay = JDELAY_OVERRIDDEN; switch (sdebug_sector_size) { case 512: @@ -5136,7 +5136,7 @@ scsi_debug_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scp) fini: return schedule_resp(scp, devip, errsts, - ((F_DELAY_OVERR & flags) ? 0 : sdebug_delay)); + ((F_DELAY_OVERR & flags) ? 0 : sdebug_jdelay)); check_cond: return schedule_resp(scp, devip, check_condition_result, 0); } From a10bc12af6347d2aa3a2ffbd5f8b7be260c12b85 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Mon, 25 Apr 2016 12:16:32 -0400 Subject: [PATCH 116/138] scsi_debug: replace tasklet with work queue When a negative value was placed in the delay parameter, a tasklet was scheduled. Change the tasklet to a work queue. Previously a delay of -1 scheduled a high priority tasklet; since there are no high priority work queues, treat -1 like other negative values in delay and schedule a work item. Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 230 ++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 135 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index e2fbac3b32aa..40de305de1d5 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -610,15 +610,15 @@ static LIST_HEAD(sdebug_host_list); static DEFINE_SPINLOCK(sdebug_host_list_lock); -struct sdebug_hrtimer { /* ... is derived from hrtimer */ - struct hrtimer hrt; /* must be first element */ +struct sdebug_defer { + struct hrtimer hrt; + struct execute_work ew; int qa_indx; }; struct sdebug_queued_cmd { /* in_use flagged by a bit in queued_in_use_bm[] */ - struct tasklet_struct *tletp; - struct sdebug_hrtimer *sd_hrtp; + struct sdebug_defer *sd_dp; struct scsi_cmnd * a_cmnd; }; static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; @@ -3349,8 +3349,9 @@ resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return resp_xdwriteread(scp, lba, num, devip); } -/* When tasklet goes off this function is called. */ -static void sdebug_q_cmd_complete(unsigned long indx) +/* Queued command completions converge here. */ +static void +sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) { int qa_indx; int retiring = 0; @@ -3360,7 +3361,7 @@ static void sdebug_q_cmd_complete(unsigned long indx) struct sdebug_dev_info *devip; atomic_inc(&sdebug_completions); - qa_indx = indx; + qa_indx = sd_dp->qa_indx; if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { pr_err("wild qa_indx=%d\n", qa_indx); return; @@ -3411,64 +3412,21 @@ static void sdebug_q_cmd_complete(unsigned long indx) static enum hrtimer_restart sdebug_q_cmd_hrt_complete(struct hrtimer *timer) { - int qa_indx; - int retiring = 0; - unsigned long iflags; - struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer; - struct sdebug_queued_cmd *sqcp; - struct scsi_cmnd *scp; - struct sdebug_dev_info *devip; - - atomic_inc(&sdebug_completions); - qa_indx = sd_hrtp->qa_indx; - if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { - pr_err("wild qa_indx=%d\n", qa_indx); - goto the_end; - } - spin_lock_irqsave(&queued_arr_lock, iflags); - sqcp = &queued_arr[qa_indx]; - scp = sqcp->a_cmnd; - if (NULL == scp) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); - pr_err("scp is NULL\n"); - goto the_end; - } - devip = (struct sdebug_dev_info *)scp->device->hostdata; - if (devip) - atomic_dec(&devip->num_in_q); - else - pr_err("devip=NULL\n"); - if (atomic_read(&retired_max_queue) > 0) - retiring = 1; - - sqcp->a_cmnd = NULL; - if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); - pr_err("Unexpected completion\n"); - goto the_end; - } - - if (unlikely(retiring)) { /* user has reduced max_queue */ - int k, retval; - - retval = atomic_read(&retired_max_queue); - if (qa_indx >= retval) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); - pr_err("index %d too large\n", retval); - goto the_end; - } - k = find_last_bit(queued_in_use_bm, retval); - if ((k < sdebug_max_queue) || (k == retval)) - atomic_set(&retired_max_queue, 0); - else - atomic_set(&retired_max_queue, k + 1); - } - spin_unlock_irqrestore(&queued_arr_lock, iflags); - scp->scsi_done(scp); /* callback to mid level */ -the_end: + struct sdebug_defer *sd_dp = container_of(timer, struct sdebug_defer, + hrt); + sdebug_q_cmd_complete(sd_dp); return HRTIMER_NORESTART; } +/* When work queue schedules work, it calls this function. */ +static void +sdebug_q_cmd_wq_complete(struct work_struct *work) +{ + struct sdebug_defer *sd_dp = container_of(work, struct sdebug_defer, + ew.work); + sdebug_q_cmd_complete(sd_dp); +} + static struct sdebug_dev_info * sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags) { @@ -3567,13 +3525,15 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) } } -/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */ -static int stop_queued_cmnd(struct scsi_cmnd *cmnd) +/* If @cmnd found deletes its timer or work queue and returns true; else + returns false */ +static bool stop_queued_cmnd(struct scsi_cmnd *cmnd) { unsigned long iflags; int k, qmax, r_qmax; struct sdebug_queued_cmd *sqcp; struct sdebug_dev_info *devip; + struct sdebug_defer *sd_dp; spin_lock_irqsave(&queued_arr_lock, iflags); qmax = sdebug_max_queue; @@ -3583,64 +3543,63 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) for (k = 0; k < qmax; ++k) { if (test_bit(k, queued_in_use_bm)) { sqcp = &queued_arr[k]; - if (cmnd == sqcp->a_cmnd) { - devip = (struct sdebug_dev_info *) - cmnd->device->hostdata; - if (devip) - atomic_dec(&devip->num_in_q); - sqcp->a_cmnd = NULL; - spin_unlock_irqrestore(&queued_arr_lock, - iflags); - if ((sdebug_jdelay > 0) || - (sdebug_ndelay > 0)) { - if (sqcp->sd_hrtp) - hrtimer_cancel( - &sqcp->sd_hrtp->hrt); - } else if (sdebug_jdelay < 0) { - if (sqcp->tletp) - tasklet_kill(sqcp->tletp); - } - clear_bit(k, queued_in_use_bm); - return 1; + if (cmnd != sqcp->a_cmnd) + continue; + /* found command */ + devip = (struct sdebug_dev_info *) + cmnd->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + sqcp->a_cmnd = NULL; + sd_dp = sqcp->sd_dp; + spin_unlock_irqrestore(&queued_arr_lock, + iflags); + if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) { + if (sd_dp) + hrtimer_cancel(&sd_dp->hrt); + } else if (sdebug_jdelay < 0) { + if (sd_dp) + cancel_work_sync(&sd_dp->ew.work); } + clear_bit(k, queued_in_use_bm); + return true; } } spin_unlock_irqrestore(&queued_arr_lock, iflags); - return 0; + return false; } -/* Deletes (stops) timers or tasklets of all queued commands */ +/* Deletes (stops) timers or work queues of all queued commands */ static void stop_all_queued(void) { unsigned long iflags; int k; struct sdebug_queued_cmd *sqcp; struct sdebug_dev_info *devip; + struct sdebug_defer *sd_dp; spin_lock_irqsave(&queued_arr_lock, iflags); for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { if (test_bit(k, queued_in_use_bm)) { sqcp = &queued_arr[k]; - if (sqcp->a_cmnd) { - devip = (struct sdebug_dev_info *) - sqcp->a_cmnd->device->hostdata; - if (devip) - atomic_dec(&devip->num_in_q); - sqcp->a_cmnd = NULL; - spin_unlock_irqrestore(&queued_arr_lock, - iflags); - if ((sdebug_jdelay > 0) || - (sdebug_ndelay > 0)) { - if (sqcp->sd_hrtp) - hrtimer_cancel( - &sqcp->sd_hrtp->hrt); - } else if (sdebug_jdelay < 0) { - if (sqcp->tletp) - tasklet_kill(sqcp->tletp); - } - clear_bit(k, queued_in_use_bm); - spin_lock_irqsave(&queued_arr_lock, iflags); + if (NULL == sqcp->a_cmnd) + continue; + devip = (struct sdebug_dev_info *) + sqcp->a_cmnd->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + sqcp->a_cmnd = NULL; + sd_dp = sqcp->sd_dp; + spin_unlock_irqrestore(&queued_arr_lock, iflags); + if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) { + if (sd_dp) + hrtimer_cancel(&sd_dp->hrt); + } else if (sdebug_jdelay < 0) { + if (sd_dp) + cancel_work_sync(&sd_dp->ew.work); } + clear_bit(k, queued_in_use_bm); + spin_lock_irqsave(&queued_arr_lock, iflags); } } spin_unlock_irqrestore(&queued_arr_lock, iflags); @@ -3649,30 +3608,27 @@ static void stop_all_queued(void) /* Free queued command memory on heap */ static void free_all_queued(void) { - unsigned long iflags; int k; struct sdebug_queued_cmd *sqcp; - spin_lock_irqsave(&queued_arr_lock, iflags); for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { sqcp = &queued_arr[k]; - kfree(sqcp->tletp); - sqcp->tletp = NULL; - kfree(sqcp->sd_hrtp); - sqcp->sd_hrtp = NULL; + kfree(sqcp->sd_dp); + sqcp->sd_dp = NULL; } - spin_unlock_irqrestore(&queued_arr_lock, iflags); } static int scsi_debug_abort(struct scsi_cmnd *SCpnt) { + bool ok; + ++num_aborts; if (SCpnt) { - if (SCpnt->device && - (SDEBUG_OPT_ALL_NOISE & sdebug_opts)) - sdev_printk(KERN_INFO, SCpnt->device, "%s\n", - __func__); - stop_queued_cmnd(SCpnt); + ok = stop_queued_cmnd(SCpnt); + if (SCpnt->device && (SDEBUG_OPT_ALL_NOISE & sdebug_opts)) + sdev_printk(KERN_INFO, SCpnt->device, + "%s: command%s found\n", __func__, + ok ? "" : " not"); } return SUCCESS; } @@ -3846,6 +3802,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, int k, num_in_q, qdepth, inject; struct sdebug_queued_cmd *sqcp = NULL; struct scsi_device *sdp; + struct sdebug_defer *sd_dp; /* this should never happen */ if (WARN_ON(!cmnd)) @@ -3912,8 +3869,8 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, sqcp->a_cmnd = cmnd; cmnd->result = scsi_result; spin_unlock_irqrestore(&queued_arr_lock, iflags); + sd_dp = sqcp->sd_dp; if ((delta_jiff > 0) || (sdebug_ndelay > 0)) { - struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp; ktime_t kt; if (delta_jiff > 0) { @@ -3923,30 +3880,27 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, kt = ktime_set(ts.tv_sec, ts.tv_nsec); } else kt = ktime_set(0, sdebug_ndelay); - if (NULL == sd_hp) { - sd_hp = kzalloc(sizeof(*sd_hp), GFP_ATOMIC); - if (NULL == sd_hp) + if (NULL == sd_dp) { + sd_dp = kzalloc(sizeof(*sd_dp), GFP_ATOMIC); + if (NULL == sd_dp) return SCSI_MLQUEUE_HOST_BUSY; - sqcp->sd_hrtp = sd_hp; - hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC, + sqcp->sd_dp = sd_dp; + hrtimer_init(&sd_dp->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - sd_hp->hrt.function = sdebug_q_cmd_hrt_complete; - sd_hp->qa_indx = k; + sd_dp->hrt.function = sdebug_q_cmd_hrt_complete; + sd_dp->qa_indx = k; } - hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL); + hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL); } else { /* jdelay < 0 */ - if (NULL == sqcp->tletp) { - sqcp->tletp = kzalloc(sizeof(*sqcp->tletp), - GFP_ATOMIC); - if (NULL == sqcp->tletp) + if (NULL == sd_dp) { + sd_dp = kzalloc(sizeof(*sqcp->sd_dp), GFP_ATOMIC); + if (NULL == sd_dp) return SCSI_MLQUEUE_HOST_BUSY; - tasklet_init(sqcp->tletp, - sdebug_q_cmd_complete, k); + sqcp->sd_dp = sd_dp; + sd_dp->qa_indx = k; + INIT_WORK(&sd_dp->ew.work, sdebug_q_cmd_wq_complete); } - if (-1 == delta_jiff) - tasklet_hi_schedule(sqcp->tletp); - else - tasklet_schedule(sqcp->tletp); + schedule_work(&sd_dp->ew.work); } if ((SDEBUG_OPT_Q_NOISE & sdebug_opts) && (scsi_result == device_qfull_result)) @@ -4149,6 +4103,9 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf, if (k != sdebug_max_queue) res = -EBUSY; /* have queued commands */ else { + /* make sure sdebug_defer instances get + * re-allocated for new delay variant */ + free_all_queued(); sdebug_jdelay = jdelay; sdebug_ndelay = 0; } @@ -4181,6 +4138,9 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, if (k != sdebug_max_queue) res = -EBUSY; /* have queued commands */ else { + /* make sure sdebug_defer instances get + * re-allocated for new delay variant */ + free_all_queued(); sdebug_ndelay = ndelay; sdebug_jdelay = ndelay ? JDELAY_OVERRIDDEN : DEF_JDELAY; From fd32119b0deac1af90ca3bed145f17d5ad68d5a7 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Mon, 25 Apr 2016 12:16:33 -0400 Subject: [PATCH 117/138] scsi_debug: re-order file scope declarations Group most defines together first; followed by struct definitions and then table and variable definitions. Normalize all function headers. [mkp: Corrected hex value in WP/DPOFUA MODE SENSE comment] Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 314 ++++++++++++++++++-------------------- 1 file changed, 151 insertions(+), 163 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 40de305de1d5..f952803ea966 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -95,7 +95,6 @@ static const char *sdebug_version_date = "20160422"; /* Additional Sense Code Qualifier (ASCQ) */ #define ACK_NAK_TO 0x3 - /* Default values for driver parameters */ #define DEF_NUM_HOST 1 #define DEF_NUM_TGTS 1 @@ -161,14 +160,14 @@ static const char *sdebug_version_date = "20160422"; SDEBUG_OPT_DIF_ERR | SDEBUG_OPT_DIX_ERR | \ SDEBUG_OPT_SHORT_TRANSFER) /* When "every_nth" > 0 then modulo "every_nth" commands: - * - a no response is simulated if SDEBUG_OPT_TIMEOUT is set + * - a missing response is simulated if SDEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SDEBUG_OPT_RECOVERED_ERR is set. * - a TRANSPORT_ERROR is simulated on successful read and write * commands if SDEBUG_OPT_TRANSPORT_ERR is set. * * When "every_nth" < 0 then after "- every_nth" commands: - * - a no response is simulated if SDEBUG_OPT_TIMEOUT is set + * - a missing response is simulated if SDEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SDEBUG_OPT_RECOVERED_ERR is set. * - a TRANSPORT_ERROR is simulated on successful read and write @@ -178,7 +177,7 @@ static const char *sdebug_version_date = "20160422"; * every_nth via sysfs). */ -/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in +/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs) are returned in * priority order. In the subset implemented here lower numbers have higher * priority. The UA numbers should be a sequence starting from 0 with * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */ @@ -218,7 +217,83 @@ static const char *sdebug_version_date = "20160422"; #warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE" #endif -/* SCSI opcodes (first byte of cdb) mapped onto these indexes */ +#define F_D_IN 1 +#define F_D_OUT 2 +#define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */ +#define F_D_UNKN 8 +#define F_RL_WLUN_OK 0x10 +#define F_SKIP_UA 0x20 +#define F_DELAY_OVERR 0x40 +#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */ +#define F_SA_HIGH 0x100 /* as used by variable length cdbs */ +#define F_INV_OP 0x200 +#define F_FAKE_RW 0x400 +#define F_M_ACCESS 0x800 /* media access */ + +#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR) +#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW) +#define FF_SA (F_SA_HIGH | F_SA_LOW) + +#define SDEBUG_MAX_PARTS 4 + +#define SCSI_DEBUG_MAX_CMD_LEN 32 + + +struct sdebug_dev_info { + struct list_head dev_list; + unsigned int channel; + unsigned int target; + u64 lun; + struct sdebug_host_info *sdbg_host; + unsigned long uas_bm[1]; + atomic_t num_in_q; + char stopped; /* TODO: should be atomic */ + bool used; +}; + +struct sdebug_host_info { + struct list_head host_list; + struct Scsi_Host *shost; + struct device dev; + struct list_head dev_info_list; +}; + +#define to_sdebug_host(d) \ + container_of(d, struct sdebug_host_info, dev) + +struct sdebug_defer { + struct hrtimer hrt; + struct execute_work ew; + int qa_indx; +}; + +struct sdebug_queued_cmd { + /* in_use flagged by a bit in queued_in_use_bm[] */ + struct sdebug_defer *sd_dp; + struct scsi_cmnd *a_cmnd; +}; + +struct sdebug_scmd_extra_t { + bool inj_recovered; + bool inj_transport; + bool inj_dif; + bool inj_dix; + bool inj_short; +}; + +struct opcode_info_t { + u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff + * for terminating element */ + u8 opcode; /* if num_attached > 0, preferred */ + u16 sa; /* service action */ + u32 flags; /* OR-ed set of SDEB_F_* */ + int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *); + const struct opcode_info_t *arrp; /* num_attached elements or NULL */ + u8 len_mask[16]; /* len=len_mask[0], then mask for cdb[1]... */ + /* ignore cdb bytes after position 15 */ +}; + +/* SCSI opcodes (first byte of cdb) of interest mapped onto these indexes */ enum sdeb_opcode_index { SDEB_I_INVALID_OPCODE = 0, SDEB_I_INQUIRY = 1, @@ -273,7 +348,7 @@ static const unsigned char opcode_ind_arr[256] = { 0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE, SDEB_I_RELEASE, 0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0, -/* 0x60; 0x60->0x7d are reserved */ +/* 0x60; 0x60->0x7d are reserved, 0x7e is "extended cdb" */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SDEB_I_VARIABLE_LEN, @@ -296,24 +371,6 @@ static const unsigned char opcode_ind_arr[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -#define F_D_IN 1 -#define F_D_OUT 2 -#define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */ -#define F_D_UNKN 8 -#define F_RL_WLUN_OK 0x10 -#define F_SKIP_UA 0x20 -#define F_DELAY_OVERR 0x40 -#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */ -#define F_SA_HIGH 0x100 /* as used by variable length cdbs */ -#define F_INV_OP 0x200 -#define F_FAKE_RW 0x400 -#define F_M_ACCESS 0x800 /* media access */ - -#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR) -#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW) -#define FF_SA (F_SA_HIGH | F_SA_LOW) - -struct sdebug_dev_info; static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *); @@ -336,18 +393,6 @@ static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *); -struct opcode_info_t { - u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff - * for terminating element */ - u8 opcode; /* if num_attached > 0, preferred */ - u16 sa; /* service action */ - u32 flags; /* OR-ed set of SDEB_F_* */ - int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *); - const struct opcode_info_t *arrp; /* num_attached elements or NULL */ - u8 len_mask[16]; /* len=len_mask[0], then mask for cdb[1]... */ - /* ignore cdb bytes after position 15 */ -}; - static const struct opcode_info_t msense_iarr[1] = { {0, 0x1a, 0, F_D_IN, NULL, NULL, {6, 0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, @@ -508,14 +553,6 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, }; -struct sdebug_scmd_extra_t { - bool inj_recovered; - bool inj_transport; - bool inj_dif; - bool inj_dix; - bool inj_short; -}; - static int sdebug_add_host = DEF_NUM_HOST; static int sdebug_ato = DEF_ATO; static int sdebug_jdelay = DEF_JDELAY; /* if > 0 then unit is jiffies */ @@ -563,8 +600,6 @@ static atomic_t sdebug_cmnd_count; static atomic_t sdebug_completions; static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */ -#define DEV_READONLY(TGT) (0) - static unsigned int sdebug_store_sectors; static sector_t sdebug_capacity; /* in sectors */ @@ -574,58 +609,10 @@ static int sdebug_heads; /* heads per disk */ static int sdebug_cylinders_per; /* cylinders per surface */ static int sdebug_sectors_per; /* sectors per cylinder */ -#define SDEBUG_MAX_PARTS 4 - -#define SCSI_DEBUG_MAX_CMD_LEN 32 - -static unsigned int scsi_debug_lbp(void) -{ - return 0 == sdebug_fake_rw && - (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10); -} - -struct sdebug_dev_info { - struct list_head dev_list; - unsigned int channel; - unsigned int target; - u64 lun; - struct sdebug_host_info *sdbg_host; - unsigned long uas_bm[1]; - atomic_t num_in_q; - char stopped; /* TODO: should be atomic */ - bool used; -}; - -struct sdebug_host_info { - struct list_head host_list; - struct Scsi_Host *shost; - struct device dev; - struct list_head dev_info_list; -}; - -#define to_sdebug_host(d) \ - container_of(d, struct sdebug_host_info, dev) - static LIST_HEAD(sdebug_host_list); static DEFINE_SPINLOCK(sdebug_host_list_lock); - -struct sdebug_defer { - struct hrtimer hrt; - struct execute_work ew; - int qa_indx; -}; - -struct sdebug_queued_cmd { - /* in_use flagged by a bit in queued_in_use_bm[] */ - struct sdebug_defer *sd_dp; - struct scsi_cmnd * a_cmnd; -}; -static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; -static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS]; - - -static unsigned char * fake_storep; /* ramdisk storage */ +static unsigned char *fake_storep; /* ramdisk storage */ static struct sd_dif_tuple *dif_storep; /* protection info */ static void *map_storep; /* provisioning map */ @@ -639,6 +626,9 @@ static int dix_writes; static int dix_reads; static int dif_errors; +static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; +static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS]; + static DEFINE_SPINLOCK(queued_arr_lock); static DEFINE_RWLOCK(atomic_rw); @@ -661,13 +651,12 @@ static const int illegal_condition_result = static const int device_qfull_result = (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL; -static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, - 0, 0, 0, 0}; -static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, - 0, 0, 0x2, 0x4b}; -static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, - 0, 0, 0x0, 0x0}; + +static unsigned int scsi_debug_lbp(void) +{ + return 0 == sdebug_fake_rw && + (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10); +} static void *fake_store(unsigned long long lba) { @@ -683,9 +672,6 @@ static struct sd_dif_tuple *dif_store(sector_t sector) return dif_storep + sector; } -static int sdebug_add_adapter(void); -static void sdebug_remove_adapter(void); - static void sdebug_max_tgts_luns(void) { struct sdebug_host_info *sdbg_host; @@ -708,9 +694,9 @@ static void sdebug_max_tgts_luns(void) enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1}; /* Set in_bit to -1 to indicate no bit position of invalid field */ -static void -mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d, - int in_byte, int in_bit) +static void mk_sense_invalid_fld(struct scsi_cmnd *scp, + enum sdeb_cmd_data c_d, + int in_byte, int in_bit) { unsigned char *sbuff; u8 sks[4]; @@ -768,8 +754,7 @@ static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq) my_name, key, asc, asq); } -static void -mk_sense_invalid_opcode(struct scsi_cmnd *scp) +static void mk_sense_invalid_opcode(struct scsi_cmnd *scp) { mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0); } @@ -1385,6 +1370,9 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return ret; } +static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, + 0, 0, 0x0, 0x0}; + static int resp_requests(struct scsi_cmnd * scp, struct sdebug_dev_info * devip) { @@ -1605,8 +1593,8 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp, return ret; } -static int -resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_rsup_opcodes(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { bool rctd; u8 reporting_opts, req_opcode, sdeb_i, supp; @@ -1756,8 +1744,8 @@ resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return errsts; } -static int -resp_rsup_tmfs(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_rsup_tmfs(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { bool repd; u32 alloc_len, len; @@ -1823,6 +1811,10 @@ static int resp_format_pg(unsigned char * p, int pcontrol, int target) return sizeof(format_pg); } +static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, + 0, 0, 0, 0}; + static int resp_caching_pg(unsigned char * p, int pcontrol, int target) { /* Caching page for mode_sense */ unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0, @@ -1840,6 +1832,9 @@ static int resp_caching_pg(unsigned char * p, int pcontrol, int target) return sizeof(caching_pg); } +static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, + 0, 0, 0x2, 0x4b}; + static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target) { /* Control mode page for mode_sense */ unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0, @@ -1938,8 +1933,8 @@ static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol) #define SDEBUG_MAX_MSENSE_SZ 256 -static int -resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_mode_sense(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { unsigned char dbd, llbaa; int pcontrol, pcode, subpcode, bd_len; @@ -1970,7 +1965,7 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) (devip->target * 1000) - 3; /* set DPOFUA bit for disks */ if (0 == sdebug_ptype) - dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10; + dev_spec = 0x10; /* would be 0x90 if read-only */ else dev_spec = 0x0; if (msense_6) { @@ -2081,8 +2076,8 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) #define SDEBUG_MAX_MSELECT_SZ 512 -static int -resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_mode_select(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { int pf, sp, ps, md_len, bd_len, off, spf, pg_len; int param_len, res, mpage; @@ -2280,8 +2275,8 @@ static int check_device_access_params(struct scsi_cmnd *scp, } /* Returns number of bytes copied or -1 if error. */ -static int -do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write) +static int do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, + bool do_write) { int ret; u64 block, rest = 0; @@ -2323,8 +2318,7 @@ do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write) /* If fake_store(lba,num) compares equal to arr(num), then copy top half of * arr into fake_store(lba,num) and return true. If comparison fails then * return false. */ -static bool -comp_write_worker(u64 lba, u32 num, const u8 *arr) +static bool comp_write_worker(u64 lba, u32 num, const u8 *arr) { bool res; u64 block, rest = 0; @@ -2463,8 +2457,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, return 0; } -static int -resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { u8 *cmd = scp->cmnd; u64 lba; @@ -2775,8 +2768,7 @@ static void unmap_region(sector_t lba, unsigned int len) } } -static int -resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { u8 *cmd = scp->cmnd; u64 lba; @@ -2893,9 +2885,8 @@ resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return 0; } -static int -resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba, - bool unmap, bool ndob) +static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, + u32 ei_lba, bool unmap, bool ndob) { unsigned long iflags; unsigned long long i; @@ -2945,8 +2936,8 @@ resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba, return 0; } -static int -resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_write_same_10(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { u8 *cmd = scp->cmnd; u32 lba; @@ -2970,8 +2961,8 @@ resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return resp_write_same(scp, lba, num, ei_lba, unmap, false); } -static int -resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_write_same_16(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { u8 *cmd = scp->cmnd; u64 lba; @@ -3001,8 +2992,8 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) /* Note the mode field is in the same position as the (lower) service action * field. For the Report supported operation codes command, SPC-4 suggests * each mode of this command should be reported separately; for future. */ -static int -resp_write_buffer(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_write_buffer(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { u8 *cmd = scp->cmnd; struct scsi_device *sdp = scp->device; @@ -3047,8 +3038,8 @@ resp_write_buffer(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return 0; } -static int -resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_comp_write(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { u8 *cmd = scp->cmnd; u8 *arr; @@ -3129,8 +3120,7 @@ struct unmap_block_desc { __be32 __reserved; }; -static int -resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { unsigned char *buf; struct unmap_block_desc *desc; @@ -3188,8 +3178,8 @@ resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) #define SDEBUG_GET_LBA_STATUS_LEN 32 -static int -resp_get_lba_status(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_get_lba_status(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { u8 *cmd = scp->cmnd; u64 lba; @@ -3323,8 +3313,8 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, return 0; } -static int -resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +static int resp_xdwriteread_10(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { u8 *cmd = scp->cmnd; u64 lba; @@ -3350,8 +3340,7 @@ resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) } /* Queued command completions converge here. */ -static void -sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) +static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) { int qa_indx; int retiring = 0; @@ -3409,8 +3398,7 @@ sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) } /* When high resolution timer goes off this function is called. */ -static enum hrtimer_restart -sdebug_q_cmd_hrt_complete(struct hrtimer *timer) +static enum hrtimer_restart sdebug_q_cmd_hrt_complete(struct hrtimer *timer) { struct sdebug_defer *sd_dp = container_of(timer, struct sdebug_defer, hrt); @@ -3419,16 +3407,15 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer) } /* When work queue schedules work, it calls this function. */ -static void -sdebug_q_cmd_wq_complete(struct work_struct *work) +static void sdebug_q_cmd_wq_complete(struct work_struct *work) { struct sdebug_defer *sd_dp = container_of(work, struct sdebug_defer, ew.work); sdebug_q_cmd_complete(sd_dp); } -static struct sdebug_dev_info * -sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags) +static struct sdebug_dev_info *sdebug_device_create( + struct sdebug_host_info *sdbg_host, gfp_t flags) { struct sdebug_dev_info *devip; @@ -3794,9 +3781,8 @@ static void __init sdebug_build_parts(unsigned char *ramp, } } -static int -schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, - int scsi_result, int delta_jiff) +static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, + int scsi_result, int delta_jiff) { unsigned long iflags; int k, num_in_q, qdepth, inject; @@ -4020,7 +4006,8 @@ static const char * scsi_debug_info(struct Scsi_Host * shp) } /* 'echo > /proc/scsi/scsi_debug/' writes to opts */ -static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length) +static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, + int length) { char arr[16]; int opts; @@ -4124,7 +4111,7 @@ static ssize_t ndelay_show(struct device_driver *ddp, char *buf) /* Returns -EBUSY if ndelay is being changed and commands are queued */ /* If > 0 and accepted then sdebug_jdelay is set to JDELAY_OVERRIDDEN */ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, - size_t count) + size_t count) { unsigned long iflags; int ndelay, res, k; @@ -4433,6 +4420,9 @@ static ssize_t add_host_show(struct device_driver *ddp, char *buf) return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_add_host); } +static int sdebug_add_adapter(void); +static void sdebug_remove_adapter(void); + static ssize_t add_host_store(struct device_driver *ddp, const char *buf, size_t count) { @@ -4902,8 +4892,7 @@ static void sdebug_remove_adapter(void) --sdebug_add_host; } -static int -sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) +static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) { int num_in_q = 0; unsigned long iflags; @@ -4933,8 +4922,7 @@ sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) return sdev->queue_depth; } -static int -check_inject(struct scsi_cmnd *scp) +static int check_inject(struct scsi_cmnd *scp) { struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); @@ -4965,8 +4953,8 @@ check_inject(struct scsi_cmnd *scp) return 0; } -static int -scsi_debug_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scp) +static int scsi_debug_queuecommand(struct Scsi_Host *shost, + struct scsi_cmnd *scp) { u8 sdeb_i; struct scsi_device *sdp = scp->device; From f46eb0e9fc763b7b66c325eb94e6aefa960146d2 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Mon, 25 Apr 2016 12:16:34 -0400 Subject: [PATCH 118/138] scsi_debug: use likely hints on fast path The most common commands in normal use are the READ and WRITE SCSI commands. Use likely and unlikely hints along the path taken by these commands. Rename check_readiness() to make_ua() and remove associated dead code. Rename devInfoReg() to find_build_dev_info(). Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 219 ++++++++++++++++++-------------------- 1 file changed, 105 insertions(+), 114 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index f952803ea966..6b2d00675ee2 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -190,10 +190,6 @@ static const char *sdebug_version_date = "20160422"; #define SDEBUG_UA_MICROCODE_CHANGED_WO_RESET 6 #define SDEBUG_NUM_UAS 7 -/* for check_readiness() */ -#define UAS_ONLY 1 /* check for UAs only */ -#define UAS_TUR 0 /* if no UAs then check if media access possible */ - /* when 1==SDEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this * sector on read commands: */ #define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ @@ -595,6 +591,7 @@ static bool sdebug_host_lock = DEF_HOST_LOCK; static bool sdebug_strict = DEF_STRICT; static bool sdebug_any_injecting_opt; static bool sdebug_verbose; +static bool have_dif_prot; static atomic_t sdebug_cmnd_count; static atomic_t sdebug_completions; @@ -793,8 +790,7 @@ static void clear_luns_changed_on_target(struct sdebug_dev_info *devip) spin_unlock(&sdebug_host_list_lock); } -static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, - struct sdebug_dev_info * devip) +static int make_ua(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { int k; @@ -804,37 +800,37 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, switch (k) { case SDEBUG_UA_POR: - mk_sense_buffer(SCpnt, UNIT_ATTENTION, - UA_RESET_ASC, POWER_ON_RESET_ASCQ); + mk_sense_buffer(scp, UNIT_ATTENTION, UA_RESET_ASC, + POWER_ON_RESET_ASCQ); if (sdebug_verbose) cp = "power on reset"; break; case SDEBUG_UA_BUS_RESET: - mk_sense_buffer(SCpnt, UNIT_ATTENTION, - UA_RESET_ASC, BUS_RESET_ASCQ); + mk_sense_buffer(scp, UNIT_ATTENTION, UA_RESET_ASC, + BUS_RESET_ASCQ); if (sdebug_verbose) cp = "bus reset"; break; case SDEBUG_UA_MODE_CHANGED: - mk_sense_buffer(SCpnt, UNIT_ATTENTION, - UA_CHANGED_ASC, MODE_CHANGED_ASCQ); + mk_sense_buffer(scp, UNIT_ATTENTION, UA_CHANGED_ASC, + MODE_CHANGED_ASCQ); if (sdebug_verbose) cp = "mode parameters changed"; break; case SDEBUG_UA_CAPACITY_CHANGED: - mk_sense_buffer(SCpnt, UNIT_ATTENTION, - UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ); + mk_sense_buffer(scp, UNIT_ATTENTION, UA_CHANGED_ASC, + CAPACITY_CHANGED_ASCQ); if (sdebug_verbose) cp = "capacity data changed"; break; case SDEBUG_UA_MICROCODE_CHANGED: - mk_sense_buffer(SCpnt, UNIT_ATTENTION, - TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ); + mk_sense_buffer(scp, UNIT_ATTENTION, + TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ); if (sdebug_verbose) cp = "microcode has been changed"; break; case SDEBUG_UA_MICROCODE_CHANGED_WO_RESET: - mk_sense_buffer(SCpnt, UNIT_ATTENTION, + mk_sense_buffer(scp, UNIT_ATTENTION, TARGET_CHANGED_ASC, MICROCODE_CHANGED_WO_RESET_ASCQ); if (sdebug_verbose) @@ -851,7 +847,7 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, */ if (sdebug_scsi_level >= 6) /* SPC-4 and above */ clear_luns_changed_on_target(devip); - mk_sense_buffer(SCpnt, UNIT_ATTENTION, + mk_sense_buffer(scp, UNIT_ATTENTION, TARGET_CHANGED_ASC, LUNS_CHANGED_ASCQ); if (sdebug_verbose) @@ -865,20 +861,11 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, } clear_bit(k, devip->uas_bm); if (sdebug_verbose) - sdev_printk(KERN_INFO, SCpnt->device, + sdev_printk(KERN_INFO, scp->device, "%s reports: Unit attention: %s\n", my_name, cp); return check_condition_result; } - if ((UAS_TUR == uas_only) && devip->stopped) { - mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY, - 0x2); - if (sdebug_verbose) - sdev_printk(KERN_INFO, SCpnt->device, - "%s reports: Not ready: %s\n", my_name, - "initializing command required"); - return check_condition_result; - } return 0; } @@ -1345,7 +1332,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) arr[2] = sdebug_scsi_level; arr[3] = 2; /* response_data_format==2 */ arr[4] = SDEBUG_LONG_INQ_SZ - 5; - arr[5] = sdebug_dif ? 1 : 0; /* PROTECT bit */ + arr[5] = (int)have_dif_prot; /* PROTECT bit */ if (0 == sdebug_vpd_use_hostno) arr[5] = 0x10; /* claim: implicit TGPS */ arr[6] = 0x10; /* claim: MultiP */ @@ -2506,7 +2493,7 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) check_prot = false; break; } - if (check_prot) { + if (unlikely(have_dif_prot && check_prot)) { if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && (cmd[1] & 0xe0)) { mk_sense_invalid_opcode(scp); @@ -2518,7 +2505,7 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) sdev_printk(KERN_ERR, scp->device, "Unprotected RD " "to DIF device\n"); } - if (sdebug_any_injecting_opt) { + if (unlikely(sdebug_any_injecting_opt)) { struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); if (ep->inj_short) @@ -2526,20 +2513,20 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) } /* inline check_device_access_params() */ - if (lba + num > sdebug_capacity) { + if (unlikely(lba + num > sdebug_capacity)) { mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); return check_condition_result; } /* transfer length excessive (tie in to block limits VPD page) */ - if (num > sdebug_store_sectors) { + if (unlikely(num > sdebug_store_sectors)) { /* needs work to find which cdb byte 'num' comes from */ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } - if ((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) && - (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) && - ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { + if (unlikely((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) && + (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) && + ((lba + num) > OPT_MEDIUM_ERR_ADDR))) { /* claim unrecoverable read error */ mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0); /* set info field and valid bit for fixed descriptor */ @@ -2556,7 +2543,7 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) read_lock_irqsave(&atomic_rw, iflags); /* DIX + T10 DIF */ - if (sdebug_dix && scsi_prot_sg_count(scp)) { + if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) { int prot_ret = prot_verify_read(scp, lba, num, ei_lba); if (prot_ret) { @@ -2568,12 +2555,12 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) ret = do_device_access(scp, lba, num, false); read_unlock_irqrestore(&atomic_rw, iflags); - if (ret == -1) + if (unlikely(ret == -1)) return DID_ERROR << 16; scsi_in(scp)->resid = scsi_bufflen(scp) - ret; - if (sdebug_any_injecting_opt) { + if (unlikely(sdebug_any_injecting_opt)) { struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); if (ep->inj_recovered) { @@ -2817,7 +2804,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) check_prot = false; break; } - if (check_prot) { + if (unlikely(have_dif_prot && check_prot)) { if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && (cmd[1] & 0xe0)) { mk_sense_invalid_opcode(scp); @@ -2831,12 +2818,12 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) } /* inline check_device_access_params() */ - if (lba + num > sdebug_capacity) { + if (unlikely(lba + num > sdebug_capacity)) { mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); return check_condition_result; } /* transfer length excessive (tie in to block limits VPD page) */ - if (num > sdebug_store_sectors) { + if (unlikely(num > sdebug_store_sectors)) { /* needs work to find which cdb byte 'num' comes from */ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; @@ -2845,7 +2832,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) write_lock_irqsave(&atomic_rw, iflags); /* DIX + T10 DIF */ - if (sdebug_dix && scsi_prot_sg_count(scp)) { + if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) { int prot_ret = prot_verify_write(scp, lba, num, ei_lba); if (prot_ret) { @@ -2856,17 +2843,17 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) } ret = do_device_access(scp, lba, num, true); - if (scsi_debug_lbp()) + if (unlikely(scsi_debug_lbp())) map_region(lba, num); write_unlock_irqrestore(&atomic_rw, iflags); - if (-1 == ret) + if (unlikely(-1 == ret)) return DID_ERROR << 16; else if (sdebug_verbose && (ret < (num * sdebug_sector_size))) sdev_printk(KERN_INFO, scp->device, "%s: write: cdb indicated=%u, IO sent=%d bytes\n", my_name, num * sdebug_sector_size, ret); - if (sdebug_any_injecting_opt) { + if (unlikely(sdebug_any_injecting_opt)) { struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); if (ep->inj_recovered) { @@ -3351,28 +3338,28 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) atomic_inc(&sdebug_completions); qa_indx = sd_dp->qa_indx; - if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { + if (unlikely((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE))) { pr_err("wild qa_indx=%d\n", qa_indx); return; } spin_lock_irqsave(&queued_arr_lock, iflags); sqcp = &queued_arr[qa_indx]; scp = sqcp->a_cmnd; - if (NULL == scp) { + if (unlikely(NULL == scp)) { spin_unlock_irqrestore(&queued_arr_lock, iflags); pr_err("scp is NULL\n"); return; } devip = (struct sdebug_dev_info *)scp->device->hostdata; - if (devip) + if (likely(devip)) atomic_dec(&devip->num_in_q); else pr_err("devip=NULL\n"); - if (atomic_read(&retired_max_queue) > 0) + if (unlikely(atomic_read(&retired_max_queue) > 0)) retiring = 1; sqcp->a_cmnd = NULL; - if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { + if (unlikely(!test_and_clear_bit(qa_indx, queued_in_use_bm))) { spin_unlock_irqrestore(&queued_arr_lock, iflags); pr_err("Unexpected completion\n"); return; @@ -3427,15 +3414,12 @@ static struct sdebug_dev_info *sdebug_device_create( return devip; } -static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) +static struct sdebug_dev_info *find_build_dev_info(struct scsi_device *sdev) { - struct sdebug_host_info * sdbg_host; - struct sdebug_dev_info * open_devip = NULL; - struct sdebug_dev_info * devip = - (struct sdebug_dev_info *)sdev->hostdata; + struct sdebug_host_info *sdbg_host; + struct sdebug_dev_info *open_devip = NULL; + struct sdebug_dev_info *devip; - if (devip) - return devip; sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host); if (!sdbg_host) { pr_err("Host info NULL\n"); @@ -3480,16 +3464,19 @@ static int scsi_debug_slave_alloc(struct scsi_device *sdp) static int scsi_debug_slave_configure(struct scsi_device *sdp) { - struct sdebug_dev_info *devip; + struct sdebug_dev_info *devip = + (struct sdebug_dev_info *)sdp->hostdata; if (sdebug_verbose) pr_info("slave_configure <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; - devip = devInfoReg(sdp); - if (NULL == devip) - return 1; /* no resources, will be marked offline */ + if (NULL == devip) { + devip = find_build_dev_info(sdp); + if (NULL == devip) + return 1; /* no resources, will be marked offline */ + } sdp->hostdata = devip; blk_queue_max_segment_size(sdp->request_queue, -1U); if (sdebug_no_uld) @@ -3622,15 +3609,14 @@ static int scsi_debug_abort(struct scsi_cmnd *SCpnt) static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt) { - struct sdebug_dev_info * devip; - ++num_dev_resets; if (SCpnt && SCpnt->device) { struct scsi_device *sdp = SCpnt->device; + struct sdebug_dev_info *devip = + (struct sdebug_dev_info *)sdp->hostdata; if (SDEBUG_OPT_ALL_NOISE & sdebug_opts) sdev_printk(KERN_INFO, sdp, "%s\n", __func__); - devip = devInfoReg(sdp); if (devip) set_bit(SDEBUG_UA_POR, devip->uas_bm); } @@ -3790,19 +3776,18 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, struct scsi_device *sdp; struct sdebug_defer *sd_dp; - /* this should never happen */ - if (WARN_ON(!cmnd)) + if (unlikely(WARN_ON(!cmnd))) return SCSI_MLQUEUE_HOST_BUSY; - if (NULL == devip) { - pr_warn("called devip == NULL\n"); - /* no particularly good error to report back */ - return SCSI_MLQUEUE_HOST_BUSY; + if (unlikely(NULL == devip)) { + if (0 == scsi_result) + scsi_result = DID_NO_CONNECT << 16; + goto respond_in_thread; } sdp = cmnd->device; - if (sdebug_verbose && scsi_result) + if (unlikely(sdebug_verbose && scsi_result)) sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", __func__, scsi_result); if (delta_jiff == 0) @@ -3813,15 +3798,15 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, num_in_q = atomic_read(&devip->num_in_q); qdepth = cmnd->device->queue_depth; inject = 0; - if ((qdepth > 0) && (num_in_q >= qdepth)) { + if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) { if (scsi_result) { spin_unlock_irqrestore(&queued_arr_lock, iflags); goto respond_in_thread; } else scsi_result = device_qfull_result; - } else if ((sdebug_every_nth != 0) && - (SDEBUG_OPT_RARE_TSF & sdebug_opts) && - (scsi_result == 0)) { + } else if (unlikely((sdebug_every_nth != 0) && + (SDEBUG_OPT_RARE_TSF & sdebug_opts) && + (scsi_result == 0))) { if ((num_in_q == (qdepth - 1)) && (atomic_inc_return(&sdebug_a_tsf) >= abs(sdebug_every_nth))) { @@ -3832,7 +3817,7 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, } k = find_first_zero_bit(queued_in_use_bm, sdebug_max_queue); - if (k >= sdebug_max_queue) { + if (unlikely(k >= sdebug_max_queue)) { spin_unlock_irqrestore(&queued_arr_lock, iflags); if (scsi_result) goto respond_in_thread; @@ -3888,8 +3873,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, } schedule_work(&sd_dp->ew.work); } - if ((SDEBUG_OPT_Q_NOISE & sdebug_opts) && - (scsi_result == device_qfull_result)) + if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && + (scsi_result == device_qfull_result))) sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, %s%s\n", __func__, num_in_q, (inject ? " " : ""), @@ -4632,9 +4617,11 @@ static int __init scsi_debug_init(void) switch (sdebug_dif) { case SD_DIF_TYPE0_PROTECTION: + break; case SD_DIF_TYPE1_PROTECTION: case SD_DIF_TYPE2_PROTECTION: case SD_DIF_TYPE3_PROTECTION: + have_dif_prot = true; break; default: @@ -4971,7 +4958,8 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, bool has_wlun_rl; scsi_set_resid(scp, 0); - if (sdebug_verbose && !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts)) { + if (unlikely(sdebug_verbose && + !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts))) { char b[120]; int n, len, sb; @@ -4987,17 +4975,16 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b); } has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS); - if ((sdp->lun >= sdebug_max_luns) && !has_wlun_rl) - return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, 0); + if (unlikely((sdp->lun >= sdebug_max_luns) && !has_wlun_rl)) + goto err_out; sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */ oip = &opcode_info_arr[sdeb_i]; /* safe if table consistent */ devip = (struct sdebug_dev_info *)sdp->hostdata; - if (!devip) { - devip = devInfoReg(sdp); + if (unlikely(!devip)) { + devip = find_build_dev_info(sdp); if (NULL == devip) - return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, - 0); + goto err_out; } na = oip->num_attached; r_pfp = oip->pfp; @@ -5029,18 +5016,18 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, } } /* else (when na==0) we assume the oip is a match */ flags = oip->flags; - if (F_INV_OP & flags) { + if (unlikely(F_INV_OP & flags)) { mk_sense_invalid_opcode(scp); goto check_cond; } - if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) { + if (unlikely(has_wlun_rl && !(F_RL_WLUN_OK & flags))) { if (sdebug_verbose) sdev_printk(KERN_INFO, sdp, "%s: Opcode 0x%x not%s\n", my_name, opcode, " supported for wlun"); mk_sense_invalid_opcode(scp); goto check_cond; } - if (sdebug_strict) { /* check cdb against mask */ + if (unlikely(sdebug_strict)) { /* check cdb against mask */ u8 rem; int j; @@ -5056,13 +5043,14 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, } } } - if (!(F_SKIP_UA & flags) && - SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS)) { - errsts = check_readiness(scp, UAS_ONLY, devip); + if (unlikely(!(F_SKIP_UA & flags) && + SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, + SDEBUG_NUM_UAS))) { + errsts = make_ua(scp, devip); if (errsts) goto check_cond; } - if ((F_M_ACCESS & flags) && devip->stopped) { + if (unlikely((F_M_ACCESS & flags) && devip->stopped)) { mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); if (sdebug_verbose) sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: " @@ -5073,12 +5061,12 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, } if (sdebug_fake_rw && (F_FAKE_RW & flags)) goto fini; - if (sdebug_every_nth) { + if (unlikely(sdebug_every_nth)) { if (check_inject(scp)) return 0; /* ignore command: make trouble */ } - if (oip->pfp) /* if this command has a resp_* function, call it */ - errsts = oip->pfp(scp, devip); + if (likely(oip->pfp)) + errsts = oip->pfp(scp, devip); /* calls a resp_* function */ else if (r_pfp) /* if leaf function ptr NULL, try the root's */ errsts = r_pfp(scp, devip); @@ -5087,6 +5075,8 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, ((F_DELAY_OVERR & flags) ? 0 : sdebug_jdelay)); check_cond: return schedule_resp(scp, devip, check_condition_result, 0); +err_out: + return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, 0); } static struct scsi_host_template sdebug_driver_template = { @@ -5122,7 +5112,7 @@ static int sdebug_driver_probe(struct device * dev) int error = 0; struct sdebug_host_info *sdbg_host; struct Scsi_Host *hpnt; - int host_prot; + int hprot; sdbg_host = to_sdebug_host(dev); @@ -5145,44 +5135,45 @@ static int sdebug_driver_probe(struct device * dev) /* = sdebug_max_luns; */ hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1; - host_prot = 0; + hprot = 0; switch (sdebug_dif) { case SD_DIF_TYPE1_PROTECTION: - host_prot = SHOST_DIF_TYPE1_PROTECTION; + hprot = SHOST_DIF_TYPE1_PROTECTION; if (sdebug_dix) - host_prot |= SHOST_DIX_TYPE1_PROTECTION; + hprot |= SHOST_DIX_TYPE1_PROTECTION; break; case SD_DIF_TYPE2_PROTECTION: - host_prot = SHOST_DIF_TYPE2_PROTECTION; + hprot = SHOST_DIF_TYPE2_PROTECTION; if (sdebug_dix) - host_prot |= SHOST_DIX_TYPE2_PROTECTION; + hprot |= SHOST_DIX_TYPE2_PROTECTION; break; case SD_DIF_TYPE3_PROTECTION: - host_prot = SHOST_DIF_TYPE3_PROTECTION; + hprot = SHOST_DIF_TYPE3_PROTECTION; if (sdebug_dix) - host_prot |= SHOST_DIX_TYPE3_PROTECTION; + hprot |= SHOST_DIX_TYPE3_PROTECTION; break; default: if (sdebug_dix) - host_prot |= SHOST_DIX_TYPE0_PROTECTION; + hprot |= SHOST_DIX_TYPE0_PROTECTION; break; } - scsi_host_set_prot(hpnt, host_prot); + scsi_host_set_prot(hpnt, hprot); - pr_info("host protection%s%s%s%s%s%s%s\n", - (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "", - (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "", - (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "", - (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "", - (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "", - (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "", - (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : ""); + if (have_dif_prot || sdebug_dix) + pr_info("host protection%s%s%s%s%s%s%s\n", + (hprot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "", + (hprot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "", + (hprot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "", + (hprot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "", + (hprot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "", + (hprot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "", + (hprot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : ""); if (sdebug_guard == 1) scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP); From b01f6f8316af5226b0cada03e3b121e72dd4c17f Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Sat, 30 Apr 2016 22:44:42 -0400 Subject: [PATCH 119/138] scsi_debug: use pdt constants Use TYPE_* constants for SCSI peripheral device types instead of numbers. Further cleanups requested by checkpatch.pl. Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinicke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 86 ++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 6b2d00675ee2..fc0246c32294 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -59,8 +59,8 @@ #include "scsi_logging.h" /* make sure inq_product_rev string corresponds to this version */ -#define SCSI_DEBUG_VERSION "1.86" -static const char *sdebug_version_date = "20160422"; +#define SDEBUG_VERSION "1.86" +static const char *sdebug_version_date = "20160430"; #define MY_NAME "scsi_debug" @@ -123,7 +123,7 @@ static const char *sdebug_version_date = "20160422"; #define DEF_OPTS 0 #define DEF_OPT_BLKS 1024 #define DEF_PHYSBLK_EXP 0 -#define DEF_PTYPE 0 +#define DEF_PTYPE TYPE_DISK #define DEF_REMOVABLE false #define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */ #define DEF_SECTOR_SIZE 512 @@ -137,6 +137,8 @@ static const char *sdebug_version_date = "20160422"; #define DEF_STRICT 0 #define JDELAY_OVERRIDDEN -9999 +#define SDEBUG_LUN_0_VAL 0 + /* bit mask values for sdebug_opts */ #define SDEBUG_OPT_NOISE 1 #define SDEBUG_OPT_MEDIUM_ERR 2 @@ -232,7 +234,7 @@ static const char *sdebug_version_date = "20160422"; #define SDEBUG_MAX_PARTS 4 -#define SCSI_DEBUG_MAX_CMD_LEN 32 +#define SDEBUG_MAX_CMD_LEN 32 struct sdebug_dev_info { @@ -278,8 +280,8 @@ struct sdebug_scmd_extra_t { }; struct opcode_info_t { - u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff - * for terminating element */ + u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff */ + /* for terminating element */ u8 opcode; /* if num_attached > 0, preferred */ u16 sa; /* service action */ u32 flags; /* OR-ed set of SDEB_F_* */ @@ -571,7 +573,7 @@ static int sdebug_num_tgts = DEF_NUM_TGTS; /* targets per host */ static int sdebug_opt_blks = DEF_OPT_BLKS; static int sdebug_opts = DEF_OPTS; static int sdebug_physblk_exp = DEF_PHYSBLK_EXP; -static int sdebug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */ +static int sdebug_ptype = DEF_PTYPE; /* SCSI peripheral device type */ static int sdebug_scsi_level = DEF_SCSI_LEVEL; static int sdebug_sector_size = DEF_SECTOR_SIZE; static int sdebug_virtual_gb = DEF_VIRTUAL_GB; @@ -649,7 +651,7 @@ static const int device_qfull_result = (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL; -static unsigned int scsi_debug_lbp(void) +static inline unsigned int scsi_debug_lbp(void) { return 0 == sdebug_fake_rw && (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10); @@ -825,7 +827,8 @@ static int make_ua(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) break; case SDEBUG_UA_MICROCODE_CHANGED: mk_sense_buffer(scp, UNIT_ATTENTION, - TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ); + TARGET_CHANGED_ASC, + MICROCODE_CHANGED_ASCQ); if (sdebug_verbose) cp = "microcode has been changed"; break; @@ -1225,11 +1228,11 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); if (! arr) return DID_REQUEUE << 16; - have_wlun = (scp->device->lun == SCSI_W_LUN_REPORT_LUNS); + have_wlun = scsi_is_wlun(scp->device->lun); if (have_wlun) - pq_pdt = 0x1e; /* present, wlun */ - else if (sdebug_no_lun_0 && (0 == devip->lun)) - pq_pdt = 0x7f; /* not present, no device type */ + pq_pdt = TYPE_WLUN; /* present, wlun */ + else if (sdebug_no_lun_0 && (devip->lun == SDEBUG_LUN_0_VAL)) + pq_pdt = 0x7f; /* not present, PQ=3, PDT=0x1f */ else pq_pdt = (sdebug_ptype & 0x1f); arr[0] = pq_pdt; @@ -1244,7 +1247,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) port_group_id = (((host_no + 1) & 0x7f) << 8) + (devip->channel & 0x7f); - if (0 == sdebug_vpd_use_hostno) + if (sdebug_vpd_use_hostno == 0) host_no = 0; lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) + (devip->target * 1000) + devip->lun); @@ -1333,7 +1336,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) arr[3] = 2; /* response_data_format==2 */ arr[4] = SDEBUG_LONG_INQ_SZ - 5; arr[5] = (int)have_dif_prot; /* PROTECT bit */ - if (0 == sdebug_vpd_use_hostno) + if (sdebug_vpd_use_hostno == 0) arr[5] = 0x10; /* claim: implicit TGPS */ arr[6] = 0x10; /* claim: MultiP */ /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */ @@ -1345,9 +1348,9 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */ arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */ n = 62; - if (sdebug_ptype == 0) { + if (sdebug_ptype == TYPE_DISK) { arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */ - } else if (sdebug_ptype == 1) { + } else if (sdebug_ptype == TYPE_TAPE) { arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */ } arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */ @@ -1534,7 +1537,7 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp, * The asymmetric access state is cycled according to the host_id. */ n = 4; - if (0 == sdebug_vpd_use_hostno) { + if (sdebug_vpd_use_hostno == 0) { arr[n++] = host_no % 3; /* Asymm access state */ arr[n++] = 0x0F; /* claim: all states are supported */ } else { @@ -1938,7 +1941,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, subpcode = cmd[3]; msense_6 = (MODE_SENSE == cmd[0]); llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10); - if ((0 == sdebug_ptype) && (0 == dbd)) + if ((sdebug_ptype == TYPE_DISK) && (dbd == 0)) bd_len = llbaa ? 16 : 8; else bd_len = 0; @@ -1950,9 +1953,9 @@ static int resp_mode_sense(struct scsi_cmnd *scp, } target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + (devip->target * 1000) - 3; - /* set DPOFUA bit for disks */ - if (0 == sdebug_ptype) - dev_spec = 0x10; /* would be 0x90 if read-only */ + /* for disks set DPOFUA bit and clear write protect (WP) bit */ + if (sdebug_ptype == TYPE_DISK) + dev_spec = 0x10; /* =0x90 if WP=1 implies read-only */ else dev_spec = 0x0; if (msense_6) { @@ -3345,7 +3348,7 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) spin_lock_irqsave(&queued_arr_lock, iflags); sqcp = &queued_arr[qa_indx]; scp = sqcp->a_cmnd; - if (unlikely(NULL == scp)) { + if (unlikely(scp == NULL)) { spin_unlock_irqrestore(&queued_arr_lock, iflags); pr_err("scp is NULL\n"); return; @@ -3470,11 +3473,11 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp) if (sdebug_verbose) pr_info("slave_configure <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); - if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) - sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; - if (NULL == devip) { + if (sdp->host->max_cmd_len != SDEBUG_MAX_CMD_LEN) + sdp->host->max_cmd_len = SDEBUG_MAX_CMD_LEN; + if (devip == NULL) { devip = find_build_dev_info(sdp); - if (NULL == devip) + if (devip == NULL) return 1; /* no resources, will be marked offline */ } sdp->hostdata = devip; @@ -3528,7 +3531,7 @@ static bool stop_queued_cmnd(struct scsi_cmnd *cmnd) sd_dp = sqcp->sd_dp; spin_unlock_irqrestore(&queued_arr_lock, iflags); - if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) { + if (sdebug_jdelay > 0 || sdebug_ndelay > 0) { if (sd_dp) hrtimer_cancel(&sd_dp->hrt); } else if (sdebug_jdelay < 0) { @@ -3565,7 +3568,7 @@ static void stop_all_queued(void) sqcp->a_cmnd = NULL; sd_dp = sqcp->sd_dp; spin_unlock_irqrestore(&queued_arr_lock, iflags); - if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) { + if (sdebug_jdelay > 0 || sdebug_ndelay > 0) { if (sd_dp) hrtimer_cancel(&sd_dp->hrt); } else if (sdebug_jdelay < 0) { @@ -3779,8 +3782,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, if (unlikely(WARN_ON(!cmnd))) return SCSI_MLQUEUE_HOST_BUSY; - if (unlikely(NULL == devip)) { - if (0 == scsi_result) + if (unlikely(devip == NULL)) { + if (scsi_result == 0) scsi_result = DID_NO_CONNECT << 16; goto respond_in_thread; } @@ -3841,7 +3844,7 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, cmnd->result = scsi_result; spin_unlock_irqrestore(&queued_arr_lock, iflags); sd_dp = sqcp->sd_dp; - if ((delta_jiff > 0) || (sdebug_ndelay > 0)) { + if (delta_jiff > 0 || sdebug_ndelay > 0) { ktime_t kt; if (delta_jiff > 0) { @@ -3938,7 +3941,7 @@ module_param_named(write_same_length, sdebug_write_same_length, int, MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); MODULE_DESCRIPTION("SCSI debug adapter driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(SCSI_DEBUG_VERSION); +MODULE_VERSION(SDEBUG_VERSION); MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)"); MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); @@ -3984,9 +3987,10 @@ static char sdebug_info[256]; static const char * scsi_debug_info(struct Scsi_Host * shp) { - sprintf(sdebug_info, "scsi_debug, version %s [%s], " - "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION, - sdebug_version_date, sdebug_dev_size_mb, sdebug_opts); + sprintf(sdebug_info, + "scsi_debug, version %s [%s], dev_size_mb=%d, opts=0x%x", + SDEBUG_VERSION, sdebug_version_date, sdebug_dev_size_mb, + sdebug_opts); return sdebug_info; } @@ -4036,7 +4040,7 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, " "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d " "usec_in_jiffy=%lu\n", - SCSI_DEBUG_VERSION, sdebug_version_date, + SDEBUG_VERSION, sdebug_version_date, sdebug_num_tgts, sdebug_dev_size_mb, sdebug_opts, sdebug_every_nth, b, sdebug_jdelay, sdebug_ndelay, sdebug_max_luns, atomic_read(&sdebug_completions), @@ -4064,7 +4068,7 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf, { int jdelay, res; - if ((count > 0) && (1 == sscanf(buf, "%d", &jdelay))) { + if (count > 0 && sscanf(buf, "%d", &jdelay) == 1) { res = count; if (sdebug_jdelay != jdelay) { unsigned long iflags; @@ -4672,7 +4676,7 @@ static int __init scsi_debug_init(void) (sdebug_sectors_per * sdebug_heads); } - if (0 == sdebug_fake_rw) { + if (sdebug_fake_rw == 0) { fake_storep = vmalloc(sz); if (NULL == fake_storep) { pr_err("out of memory, 1\n"); @@ -5044,8 +5048,8 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, } } if (unlikely(!(F_SKIP_UA & flags) && - SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, - SDEBUG_NUM_UAS))) { + find_first_bit(devip->uas_bm, + SDEBUG_NUM_UAS) != SDEBUG_NUM_UAS)) { errsts = make_ua(scp, devip); if (errsts) goto check_cond; From 8d039e22b516c4c0ecaeb91f7566b5860fda14e7 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Sat, 30 Apr 2016 22:44:43 -0400 Subject: [PATCH 120/138] scsi_debug: rework resp_report_luns Based on "[PATH V2] scsi_debug: rework resp_report_luns" patch sent by Tomas Winkler on Thursday, 26 Feb 2015. His notes: 1. Remove duplicated boundary checks which simplify the fill-in loop 2. Use more of scsi generic API Replace fixed length response array a with heap allocation allowing up to 256 normal LUNs per target. Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinicke Reviewed-by: Tomas Winkler Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 135 ++++++++++++++++++++++++-------------- 1 file changed, 87 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index fc0246c32294..e97ddf0574c8 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -3208,63 +3208,94 @@ static int resp_get_lba_status(struct scsi_cmnd *scp, return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN); } -#define SDEBUG_RLUN_ARR_SZ 256 - -static int resp_report_luns(struct scsi_cmnd * scp, - struct sdebug_dev_info * devip) +/* Even though each pseudo target has a REPORT LUNS "well known logical unit" + * (W-LUN), the normal Linux scanning logic does not associate it with a + * device (e.g. /dev/sg7). The following magic will make that association: + * "cd /sys/class/scsi_host/host ; echo '- - 49409' > scan" + * where is a host number. If there are multiple targets in a host then + * the above will associate a W-LUN to each target. To only get a W-LUN + * for target 2, then use "echo '- 2 49409' > scan" . + */ +static int resp_report_luns(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { - unsigned int alloc_len; - int lun_cnt, i, upper, num, n, want_wlun, shortish; - u64 lun; unsigned char *cmd = scp->cmnd; - int select_report = (int)cmd[2]; - struct scsi_lun *one_lun; - unsigned char arr[SDEBUG_RLUN_ARR_SZ]; - unsigned char * max_addr; + unsigned int alloc_len; + unsigned char select_report; + u64 lun; + struct scsi_lun *lun_p; + u8 *arr; + unsigned int lun_cnt; /* normal LUN count (max: 256) */ + unsigned int wlun_cnt; /* report luns W-LUN count */ + unsigned int tlun_cnt; /* total LUN count */ + unsigned int rlen; /* response length (in bytes) */ + int i, res; clear_luns_changed_on_target(devip); - alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); - shortish = (alloc_len < 4); - if (shortish || (select_report > 2)) { - mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1); + + select_report = cmd[2]; + alloc_len = get_unaligned_be32(cmd + 6); + + if (alloc_len < 4) { + pr_err("alloc len too small %d\n", alloc_len); + mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1); return check_condition_result; } - /* can produce response with up to 16k luns (lun 0 to lun 16383) */ - memset(arr, 0, SDEBUG_RLUN_ARR_SZ); - lun_cnt = sdebug_max_luns; - if (1 == select_report) + + switch (select_report) { + case 0: /* all LUNs apart from W-LUNs */ + lun_cnt = sdebug_max_luns; + wlun_cnt = 0; + break; + case 1: /* only W-LUNs */ lun_cnt = 0; - else if (sdebug_no_lun_0 && (lun_cnt > 0)) + wlun_cnt = 1; + break; + case 2: /* all LUNs */ + lun_cnt = sdebug_max_luns; + wlun_cnt = 1; + break; + case 0x10: /* only administrative LUs */ + case 0x11: /* see SPC-5 */ + case 0x12: /* only subsiduary LUs owned by referenced LU */ + default: + pr_debug("select report invalid %d\n", select_report); + mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1); + return check_condition_result; + } + + if (sdebug_no_lun_0 && (lun_cnt > 0)) --lun_cnt; - want_wlun = (select_report > 0) ? 1 : 0; - num = lun_cnt + want_wlun; - arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff; - arr[3] = (sizeof(struct scsi_lun) * num) & 0xff; - n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) / - sizeof(struct scsi_lun)), num); - if (n < num) { - want_wlun = 0; - lun_cnt = n; + + tlun_cnt = lun_cnt + wlun_cnt; + + rlen = (tlun_cnt * sizeof(struct scsi_lun)) + 8; + arr = vmalloc(rlen); + if (!arr) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, + INSUFF_RES_ASCQ); + return check_condition_result; } - one_lun = (struct scsi_lun *) &arr[8]; - max_addr = arr + SDEBUG_RLUN_ARR_SZ; - for (i = 0, lun = (sdebug_no_lun_0 ? 1 : 0); - ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr)); - i++, lun++) { - upper = (lun >> 8) & 0x3f; - if (upper) - one_lun[i].scsi_lun[0] = - (upper | (SAM2_LUN_ADDRESS_METHOD << 6)); - one_lun[i].scsi_lun[1] = lun & 0xff; - } - if (want_wlun) { - one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff; - one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff; - i++; - } - alloc_len = (unsigned char *)(one_lun + i) - arr; - return fill_from_dev_buffer(scp, arr, - min((int)alloc_len, SDEBUG_RLUN_ARR_SZ)); + memset(arr, 0, rlen); + pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n", + select_report, lun_cnt, wlun_cnt, sdebug_no_lun_0); + + /* luns start at byte 8 in response following the header */ + lun_p = (struct scsi_lun *)&arr[8]; + + /* LUNs use single level peripheral device addressing method */ + lun = sdebug_no_lun_0 ? 1 : 0; + for (i = 0; i < lun_cnt; i++) + int_to_scsilun(lun++, lun_p++); + + if (wlun_cnt) + int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, lun_p++); + + put_unaligned_be32(rlen - 8, &arr[0]); + + res = fill_from_dev_buffer(scp, arr, rlen); + vfree(arr); + return res; } static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, @@ -4303,6 +4334,10 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf, bool changed; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { + if (n > 256) { + pr_warn("max_luns can be no more than 256\n"); + return -EINVAL; + } changed = (sdebug_max_luns != n); sdebug_max_luns = n; sdebug_max_tgts_luns(); @@ -4647,6 +4682,10 @@ static int __init scsi_debug_init(void) pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp); return -EINVAL; } + if (sdebug_max_luns > 256) { + pr_warn("max_luns can be no more than 256, use default\n"); + sdebug_max_luns = DEF_MAX_LUNS; + } if (sdebug_lowest_aligned > 0x3fff) { pr_err("lowest_aligned too big: %u\n", sdebug_lowest_aligned); From 635f6b0893cff193a1774881ebb1e4a4b9a7fead Mon Sep 17 00:00:00 2001 From: "Manoj N. Kumar" Date: Tue, 3 May 2016 11:27:34 -0500 Subject: [PATCH 121/138] cxlflash: Fix to resolve dead-lock during EEH recovery When a cxlflash adapter goes into EEH recovery and multiple processes (each having established its own context) are active, the EEH recovery can hang if the processes attempt to recover in parallel. The symptom logged after a couple of minutes is: INFO: task eehd:48 blocked for more than 120 seconds. Not tainted 4.5.0-491-26f710d+ #1 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. eehd 0 48 2 Call Trace: __switch_to+0x2f0/0x410 __schedule+0x300/0x980 schedule+0x48/0xc0 rwsem_down_write_failed+0x294/0x410 down_write+0x88/0xb0 cxlflash_pci_error_detected+0x100/0x1c0 [cxlflash] cxl_vphb_error_detected+0x88/0x110 [cxl] cxl_pci_error_detected+0xb0/0x1d0 [cxl] eeh_report_error+0xbc/0x130 eeh_pe_dev_traverse+0x94/0x160 eeh_handle_normal_event+0x17c/0x450 eeh_handle_event+0x184/0x370 eeh_event_handler+0x1c8/0x1d0 kthread+0x110/0x130 ret_from_kernel_thread+0x5c/0xa4 INFO: task blockio:33215 blocked for more than 120 seconds. Not tainted 4.5.0-491-26f710d+ #1 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. blockio 0 33215 33213 Call Trace: 0x1 (unreliable) __switch_to+0x2f0/0x410 __schedule+0x300/0x980 schedule+0x48/0xc0 rwsem_down_read_failed+0x124/0x1d0 down_read+0x68/0x80 cxlflash_ioctl+0x70/0x6f0 [cxlflash] scsi_ioctl+0x3b0/0x4c0 sg_ioctl+0x960/0x1010 do_vfs_ioctl+0xd8/0x8c0 SyS_ioctl+0xd4/0xf0 system_call+0x38/0xb4 INFO: task eehd:48 blocked for more than 120 seconds. The hang is because of a 3 way dead-lock: Process A holds the recovery mutex, and waits for eehd to complete. Process B holds the semaphore and waits for the recovery mutex. eehd waits for semaphore. The fix is to have Process B above release the semaphore before attempting to acquire the recovery mutex. This will allow eehd to proceed to completion. Signed-off-by: Manoj N. Kumar Reviewed-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/superpipe.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c index d8a5cb3cd2bd..ce1507023132 100644 --- a/drivers/scsi/cxlflash/superpipe.c +++ b/drivers/scsi/cxlflash/superpipe.c @@ -1615,6 +1615,13 @@ static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi) * place at the same time and the failure was due to CXL services being * unable to keep up. * + * As this routine is called on ioctl context, it holds the ioctl r/w + * semaphore that is used to drain ioctls in recovery scenarios. The + * implementation to achieve the pacing described above (a local mutex) + * requires that the ioctl r/w semaphore be dropped and reacquired to + * avoid a 3-way deadlock when multiple process recoveries operate in + * parallel. + * * Because a user can detect an error condition before the kernel, it is * quite possible for this routine to act as the kernel's EEH detection * source (MMIO read of mbox_r). Because of this, there is a window of @@ -1642,9 +1649,17 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, int rc = 0; atomic_inc(&cfg->recovery_threads); + up_read(&cfg->ioctl_rwsem); rc = mutex_lock_interruptible(mutex); + down_read(&cfg->ioctl_rwsem); if (rc) goto out; + rc = check_state(cfg); + if (rc) { + dev_err(dev, "%s: Failed state! rc=%d\n", __func__, rc); + rc = -ENODEV; + goto out; + } dev_dbg(dev, "%s: reason 0x%016llX rctxid=%016llX\n", __func__, recover->reason, rctxid); From 13f307711b127d30fcf333a04365a217baf9ca2b Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 3 May 2016 10:24:31 -0700 Subject: [PATCH 122/138] megaraid_sas: Downgrade two success messages to info I actually read the error messages in my logs, and successful initialization is not an error. Arguably these log lines could be deleted entirely. Signed-off-by: Andy Lutomirski Reviewed-by: Hannes Reinicke Acked-by: Sumit Saxena Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- drivers/scsi/megaraid/megaraid_sas_fusion.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index b84756c1d230..f4b0690450d2 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -5185,7 +5185,7 @@ static int megasas_init_fw(struct megasas_instance *instance) instance->instancet->enable_intr(instance); - dev_err(&instance->pdev->dev, "INIT adapter done\n"); + dev_info(&instance->pdev->dev, "INIT adapter done\n"); megasas_setup_jbod_map(instance); diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index e2dc20566ab7..ec837544f784 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -854,7 +854,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) ret = 1; goto fail_fw_init; } - dev_err(&instance->pdev->dev, "Init cmd success\n"); + dev_info(&instance->pdev->dev, "Init cmd success\n"); ret = 0; From 4e51af9ee7afa0ecf4829e7a44f7055db7968e02 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Apr 2016 14:14:41 +0300 Subject: [PATCH 123/138] bfa: fix bfa_fcb_itnim_alloc() error handling The caller assumes that "itnim" is NULL on error and non-NULL on success but really "itnim" is uninitialized on error. This function should just use normal error handling where it returns zero on success and negative on failure. Signed-off-by: Dan Carpenter Acked-by: Anil Gurumurthy Signed-off-by: Martin K. Petersen --- drivers/scsi/bfa/bfa_fcs.h | 4 ++-- drivers/scsi/bfa/bfa_fcs_fcpim.c | 5 +++-- drivers/scsi/bfa/bfad_im.c | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index 06dc215ea050..0f797a55d504 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -874,8 +874,8 @@ bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad, /* * itnim callbacks */ -void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim, - struct bfad_itnim_s **itnim_drv); +int bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim, + struct bfad_itnim_s **itnim_drv); void bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv); void bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv); diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c index 4f089d76afb1..2e3b19e7e079 100644 --- a/drivers/scsi/bfa/bfa_fcs_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c @@ -588,12 +588,13 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport) struct bfa_fcs_lport_s *port = rport->port; struct bfa_fcs_itnim_s *itnim; struct bfad_itnim_s *itnim_drv; + int ret; /* * call bfad to allocate the itnim */ - bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv); - if (itnim == NULL) { + ret = bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv); + if (ret) { bfa_trc(port->fcs, rport->pwwn); return NULL; } diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 6c805e13f8dd..02d806012fa1 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -440,13 +440,13 @@ bfad_im_slave_destroy(struct scsi_device *sdev) * BFA FCS itnim alloc callback, after successful PRLI * Context: Interrupt */ -void +int bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim, struct bfad_itnim_s **itnim_drv) { *itnim_drv = kzalloc(sizeof(struct bfad_itnim_s), GFP_ATOMIC); if (*itnim_drv == NULL) - return; + return -ENOMEM; (*itnim_drv)->im = bfad->im; *itnim = &(*itnim_drv)->fcs_itnim; @@ -457,6 +457,7 @@ bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim, */ INIT_WORK(&(*itnim_drv)->itnim_work, bfad_im_itnim_work_handler); bfad->bfad_flags |= BFAD_RPORT_ONLINE; + return 0; } /* From c483739430f107c14b3fa316e9cdd3d1e065864a Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Fri, 6 May 2016 00:40:26 -0400 Subject: [PATCH 124/138] scsi_debug: add multiple queue support Add submit_queue parameter (minimum and default: 1; maximum: nr_cpu_ids) that controls how many queues are built, each with their own lock and in_use bit vector. Add statistics parameter which is default off. Signed-off-by: Douglas Gilbert Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 696 ++++++++++++++++++++++++-------------- 1 file changed, 443 insertions(+), 253 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index e97ddf0574c8..2ee55d54d125 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -135,6 +135,8 @@ static const char *sdebug_version_date = "20160430"; #define DEF_VPD_USE_HOSTNO 1 #define DEF_WRITESAME_LENGTH 0xFFFF #define DEF_STRICT 0 +#define DEF_STATISTICS false +#define DEF_SUBMIT_QUEUES 1 #define JDELAY_OVERRIDDEN -9999 #define SDEBUG_LUN_0_VAL 0 @@ -201,20 +203,17 @@ static const char *sdebug_version_date = "20160430"; * or "peripheral device" addressing (value 0) */ #define SAM2_LUN_ADDRESS_METHOD 0 -/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued - * (for response) at one time. Can be reduced by max_queue option. Command - * responses are not queued when jdelay=0 and ndelay=0. The per-device - * DEF_CMD_PER_LUN can be changed via sysfs: - * /sys/class/scsi_device//device/queue_depth but cannot exceed - * SCSI_DEBUG_CANQUEUE. */ -#define SCSI_DEBUG_CANQUEUE_WORDS 9 /* a WORD is bits in a long */ -#define SCSI_DEBUG_CANQUEUE (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG) +/* SDEBUG_CANQUEUE is the maximum number of commands that can be queued + * (for response) per submit queue at one time. Can be reduced by max_queue + * option. Command responses are not queued when jdelay=0 and ndelay=0. The + * per-device DEF_CMD_PER_LUN can be changed via sysfs: + * /sys/class/scsi_device//device/queue_depth + * but cannot exceed SDEBUG_CANQUEUE . + */ +#define SDEBUG_CANQUEUE_WORDS 3 /* a WORD is bits in a long */ +#define SDEBUG_CANQUEUE (SDEBUG_CANQUEUE_WORDS * BITS_PER_LONG) #define DEF_CMD_PER_LUN 255 -#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE -#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE" -#endif - #define F_D_IN 1 #define F_D_OUT 2 #define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */ @@ -245,7 +244,7 @@ struct sdebug_dev_info { struct sdebug_host_info *sdbg_host; unsigned long uas_bm[1]; atomic_t num_in_q; - char stopped; /* TODO: should be atomic */ + atomic_t stopped; bool used; }; @@ -262,23 +261,36 @@ struct sdebug_host_info { struct sdebug_defer { struct hrtimer hrt; struct execute_work ew; - int qa_indx; + int sqa_idx; /* index of sdebug_queue array */ + int qc_idx; /* index of sdebug_queued_cmd array within sqa_idx */ + int issuing_cpu; }; struct sdebug_queued_cmd { - /* in_use flagged by a bit in queued_in_use_bm[] */ + /* corresponding bit set in in_use_bm[] in owning struct sdebug_queue + * instance indicates this slot is in use. + */ struct sdebug_defer *sd_dp; struct scsi_cmnd *a_cmnd; + unsigned int inj_recovered:1; + unsigned int inj_transport:1; + unsigned int inj_dif:1; + unsigned int inj_dix:1; + unsigned int inj_short:1; }; -struct sdebug_scmd_extra_t { - bool inj_recovered; - bool inj_transport; - bool inj_dif; - bool inj_dix; - bool inj_short; +struct sdebug_queue { + struct sdebug_queued_cmd qc_arr[SDEBUG_CANQUEUE]; + unsigned long in_use_bm[SDEBUG_CANQUEUE_WORDS]; + spinlock_t qc_lock; + atomic_t blocked; /* to temporarily stop more being queued */ }; +static atomic_t sdebug_cmnd_count; /* number of incoming commands */ +static atomic_t sdebug_completions; /* count of deferred completions */ +static atomic_t sdebug_miss_cpus; /* submission + completion cpus differ */ +static atomic_t sdebug_a_tsf; /* 'almost task set full' counter */ + struct opcode_info_t { u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff */ /* for terminating element */ @@ -326,6 +338,7 @@ enum sdeb_opcode_index { SDEB_I_LAST_ELEMENT = 30, /* keep this last */ }; + static const unsigned char opcode_ind_arr[256] = { /* 0x0; 0x0->0x1f: 6 byte cdbs */ SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE, @@ -563,7 +576,7 @@ static int sdebug_fake_rw = DEF_FAKE_RW; static unsigned int sdebug_guard = DEF_GUARD; static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED; static int sdebug_max_luns = DEF_MAX_LUNS; -static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE; +static int sdebug_max_queue = SDEBUG_CANQUEUE; /* per submit queue */ static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ static int sdebug_ndelay = DEF_NDELAY; /* if > 0 then unit is nanoseconds */ static int sdebug_no_lun_0 = DEF_NO_LUN_0; @@ -594,10 +607,8 @@ static bool sdebug_strict = DEF_STRICT; static bool sdebug_any_injecting_opt; static bool sdebug_verbose; static bool have_dif_prot; - -static atomic_t sdebug_cmnd_count; -static atomic_t sdebug_completions; -static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */ +static bool sdebug_statistics = DEF_STATISTICS; +static bool sdebug_mq_active; static unsigned int sdebug_store_sectors; static sector_t sdebug_capacity; /* in sectors */ @@ -625,10 +636,9 @@ static int dix_writes; static int dix_reads; static int dif_errors; -static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; -static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS]; +static int submit_queues = DEF_SUBMIT_QUEUES; /* > 1 for multi-queue (mq) */ +static struct sdebug_queue *sdebug_q_arr; /* ptr to array of submit queues */ -static DEFINE_SPINLOCK(queued_arr_lock); static DEFINE_RWLOCK(atomic_rw); static char sdebug_proc_name[] = MY_NAME; @@ -1428,16 +1438,15 @@ static int resp_start_stop(struct scsi_cmnd * scp, struct sdebug_dev_info * devip) { unsigned char *cmd = scp->cmnd; - int power_cond, start; + int power_cond, stop; power_cond = (cmd[4] & 0xf0) >> 4; if (power_cond) { mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7); return check_condition_result; } - start = cmd[4] & 1; - if (start == devip->stopped) - devip->stopped = !start; + stop = !(cmd[4] & 1); + atomic_xchg(&devip->stopped, stop); return 0; } @@ -2450,6 +2459,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { u8 *cmd = scp->cmnd; + struct sdebug_queued_cmd *sqcp; u64 lba; u32 num; u32 ei_lba; @@ -2509,11 +2519,14 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) "to DIF device\n"); } if (unlikely(sdebug_any_injecting_opt)) { - struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); + sqcp = (struct sdebug_queued_cmd *)scp->host_scribble; - if (ep->inj_short) - num /= 2; - } + if (sqcp) { + if (sqcp->inj_short) + num /= 2; + } + } else + sqcp = NULL; /* inline check_device_access_params() */ if (unlikely(lba + num > sdebug_capacity)) { @@ -2563,22 +2576,20 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) scsi_in(scp)->resid = scsi_bufflen(scp) - ret; - if (unlikely(sdebug_any_injecting_opt)) { - struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); - - if (ep->inj_recovered) { + if (unlikely(sqcp)) { + if (sqcp->inj_recovered) { mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); return check_condition_result; - } else if (ep->inj_transport) { + } else if (sqcp->inj_transport) { mk_sense_buffer(scp, ABORTED_COMMAND, TRANSPORT_PROBLEM, ACK_NAK_TO); return check_condition_result; - } else if (ep->inj_dif) { + } else if (sqcp->inj_dif) { /* Logical block guard check failed */ mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); return illegal_condition_result; - } else if (ep->inj_dix) { + } else if (sqcp->inj_dix) { mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); return illegal_condition_result; } @@ -2851,25 +2862,29 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) write_unlock_irqrestore(&atomic_rw, iflags); if (unlikely(-1 == ret)) return DID_ERROR << 16; - else if (sdebug_verbose && (ret < (num * sdebug_sector_size))) + else if (unlikely(sdebug_verbose && + (ret < (num * sdebug_sector_size)))) sdev_printk(KERN_INFO, scp->device, "%s: write: cdb indicated=%u, IO sent=%d bytes\n", my_name, num * sdebug_sector_size, ret); if (unlikely(sdebug_any_injecting_opt)) { - struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); + struct sdebug_queued_cmd *sqcp = + (struct sdebug_queued_cmd *)scp->host_scribble; - if (ep->inj_recovered) { - mk_sense_buffer(scp, RECOVERED_ERROR, - THRESHOLD_EXCEEDED, 0); - return check_condition_result; - } else if (ep->inj_dif) { - /* Logical block guard check failed */ - mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); - return illegal_condition_result; - } else if (ep->inj_dix) { - mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); - return illegal_condition_result; + if (sqcp) { + if (sqcp->inj_recovered) { + mk_sense_buffer(scp, RECOVERED_ERROR, + THRESHOLD_EXCEEDED, 0); + return check_condition_result; + } else if (sqcp->inj_dif) { + /* Logical block guard check failed */ + mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); + return illegal_condition_result; + } else if (sqcp->inj_dix) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); + return illegal_condition_result; + } } } return 0; @@ -3360,28 +3375,53 @@ static int resp_xdwriteread_10(struct scsi_cmnd *scp, return resp_xdwriteread(scp, lba, num, devip); } -/* Queued command completions converge here. */ +static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd) +{ + struct sdebug_queue *sqp = sdebug_q_arr; + + if (sdebug_mq_active) { + u32 tag = blk_mq_unique_tag(cmnd->request); + u16 hwq = blk_mq_unique_tag_to_hwq(tag); + + if (unlikely(hwq >= submit_queues)) { + pr_warn("Unexpected hwq=%d, apply modulo\n", hwq); + hwq %= submit_queues; + } + pr_debug("tag=%u, hwq=%d\n", tag, hwq); + return sqp + hwq; + } else + return sqp; +} + +/* Queued (deferred) command completions converge here. */ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) { - int qa_indx; + int qc_idx; int retiring = 0; unsigned long iflags; + struct sdebug_queue *sqp; struct sdebug_queued_cmd *sqcp; struct scsi_cmnd *scp; struct sdebug_dev_info *devip; - atomic_inc(&sdebug_completions); - qa_indx = sd_dp->qa_indx; - if (unlikely((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE))) { - pr_err("wild qa_indx=%d\n", qa_indx); + qc_idx = sd_dp->qc_idx; + sqp = sdebug_q_arr + sd_dp->sqa_idx; + if (sdebug_statistics) { + atomic_inc(&sdebug_completions); + if (raw_smp_processor_id() != sd_dp->issuing_cpu) + atomic_inc(&sdebug_miss_cpus); + } + if (unlikely((qc_idx < 0) || (qc_idx >= SDEBUG_CANQUEUE))) { + pr_err("wild qc_idx=%d\n", qc_idx); return; } - spin_lock_irqsave(&queued_arr_lock, iflags); - sqcp = &queued_arr[qa_indx]; + spin_lock_irqsave(&sqp->qc_lock, iflags); + sqcp = &sqp->qc_arr[qc_idx]; scp = sqcp->a_cmnd; if (unlikely(scp == NULL)) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); - pr_err("scp is NULL\n"); + spin_unlock_irqrestore(&sqp->qc_lock, iflags); + pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d\n", + sd_dp->sqa_idx, qc_idx); return; } devip = (struct sdebug_dev_info *)scp->device->hostdata; @@ -3393,8 +3433,8 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) retiring = 1; sqcp->a_cmnd = NULL; - if (unlikely(!test_and_clear_bit(qa_indx, queued_in_use_bm))) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (unlikely(!test_and_clear_bit(qc_idx, sqp->in_use_bm))) { + spin_unlock_irqrestore(&sqp->qc_lock, iflags); pr_err("Unexpected completion\n"); return; } @@ -3403,18 +3443,18 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) int k, retval; retval = atomic_read(&retired_max_queue); - if (qa_indx >= retval) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (qc_idx >= retval) { + spin_unlock_irqrestore(&sqp->qc_lock, iflags); pr_err("index %d too large\n", retval); return; } - k = find_last_bit(queued_in_use_bm, retval); + k = find_last_bit(sqp->in_use_bm, retval); if ((k < sdebug_max_queue) || (k == retval)) atomic_set(&retired_max_queue, 0); else atomic_set(&retired_max_queue, k + 1); } - spin_unlock_irqrestore(&queued_arr_lock, iflags); + spin_unlock_irqrestore(&sqp->qc_lock, iflags); scp->scsi_done(scp); /* callback to mid level */ } @@ -3533,47 +3573,53 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) } } +static void stop_qc_helper(struct sdebug_defer *sd_dp) +{ + if (!sd_dp) + return; + if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) + hrtimer_cancel(&sd_dp->hrt); + else if (sdebug_jdelay < 0) + cancel_work_sync(&sd_dp->ew.work); +} + /* If @cmnd found deletes its timer or work queue and returns true; else returns false */ static bool stop_queued_cmnd(struct scsi_cmnd *cmnd) { unsigned long iflags; - int k, qmax, r_qmax; + int j, k, qmax, r_qmax; + struct sdebug_queue *sqp; struct sdebug_queued_cmd *sqcp; struct sdebug_dev_info *devip; struct sdebug_defer *sd_dp; - spin_lock_irqsave(&queued_arr_lock, iflags); - qmax = sdebug_max_queue; - r_qmax = atomic_read(&retired_max_queue); - if (r_qmax > qmax) - qmax = r_qmax; - for (k = 0; k < qmax; ++k) { - if (test_bit(k, queued_in_use_bm)) { - sqcp = &queued_arr[k]; - if (cmnd != sqcp->a_cmnd) - continue; - /* found command */ - devip = (struct sdebug_dev_info *) - cmnd->device->hostdata; - if (devip) - atomic_dec(&devip->num_in_q); - sqcp->a_cmnd = NULL; - sd_dp = sqcp->sd_dp; - spin_unlock_irqrestore(&queued_arr_lock, - iflags); - if (sdebug_jdelay > 0 || sdebug_ndelay > 0) { - if (sd_dp) - hrtimer_cancel(&sd_dp->hrt); - } else if (sdebug_jdelay < 0) { - if (sd_dp) - cancel_work_sync(&sd_dp->ew.work); + for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) { + spin_lock_irqsave(&sqp->qc_lock, iflags); + qmax = sdebug_max_queue; + r_qmax = atomic_read(&retired_max_queue); + if (r_qmax > qmax) + qmax = r_qmax; + for (k = 0; k < qmax; ++k) { + if (test_bit(k, sqp->in_use_bm)) { + sqcp = &sqp->qc_arr[k]; + if (cmnd != sqcp->a_cmnd) + continue; + /* found */ + devip = (struct sdebug_dev_info *) + cmnd->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + sqcp->a_cmnd = NULL; + sd_dp = sqcp->sd_dp; + spin_unlock_irqrestore(&sqp->qc_lock, iflags); + stop_qc_helper(sd_dp); + clear_bit(k, sqp->in_use_bm); + return true; } - clear_bit(k, queued_in_use_bm); - return true; } + spin_unlock_irqrestore(&sqp->qc_lock, iflags); } - spin_unlock_irqrestore(&queued_arr_lock, iflags); return false; } @@ -3581,48 +3627,48 @@ static bool stop_queued_cmnd(struct scsi_cmnd *cmnd) static void stop_all_queued(void) { unsigned long iflags; - int k; + int j, k; + struct sdebug_queue *sqp; struct sdebug_queued_cmd *sqcp; struct sdebug_dev_info *devip; struct sdebug_defer *sd_dp; - spin_lock_irqsave(&queued_arr_lock, iflags); - for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { - if (test_bit(k, queued_in_use_bm)) { - sqcp = &queued_arr[k]; - if (NULL == sqcp->a_cmnd) - continue; - devip = (struct sdebug_dev_info *) - sqcp->a_cmnd->device->hostdata; - if (devip) - atomic_dec(&devip->num_in_q); - sqcp->a_cmnd = NULL; - sd_dp = sqcp->sd_dp; - spin_unlock_irqrestore(&queued_arr_lock, iflags); - if (sdebug_jdelay > 0 || sdebug_ndelay > 0) { - if (sd_dp) - hrtimer_cancel(&sd_dp->hrt); - } else if (sdebug_jdelay < 0) { - if (sd_dp) - cancel_work_sync(&sd_dp->ew.work); + for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) { + spin_lock_irqsave(&sqp->qc_lock, iflags); + for (k = 0; k < SDEBUG_CANQUEUE; ++k) { + if (test_bit(k, sqp->in_use_bm)) { + sqcp = &sqp->qc_arr[k]; + if (sqcp->a_cmnd == NULL) + continue; + devip = (struct sdebug_dev_info *) + sqcp->a_cmnd->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + sqcp->a_cmnd = NULL; + sd_dp = sqcp->sd_dp; + spin_unlock_irqrestore(&sqp->qc_lock, iflags); + stop_qc_helper(sd_dp); + clear_bit(k, sqp->in_use_bm); + spin_lock_irqsave(&sqp->qc_lock, iflags); } - clear_bit(k, queued_in_use_bm); - spin_lock_irqsave(&queued_arr_lock, iflags); } + spin_unlock_irqrestore(&sqp->qc_lock, iflags); } - spin_unlock_irqrestore(&queued_arr_lock, iflags); } /* Free queued command memory on heap */ static void free_all_queued(void) { - int k; + int j, k; + struct sdebug_queue *sqp; struct sdebug_queued_cmd *sqcp; - for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { - sqcp = &queued_arr[k]; - kfree(sqcp->sd_dp); - sqcp->sd_dp = NULL; + for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) { + for (k = 0; k < SDEBUG_CANQUEUE; ++k) { + sqcp = &sqp->qc_arr[k]; + kfree(sqcp->sd_dp); + sqcp->sd_dp = NULL; + } } } @@ -3801,24 +3847,71 @@ static void __init sdebug_build_parts(unsigned char *ramp, } } +static void block_unblock_all_queues(bool block) +{ + int j; + struct sdebug_queue *sqp; + + for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) + atomic_set(&sqp->blocked, (int)block); +} + +/* Adjust (by rounding down) the sdebug_cmnd_count so abs(every_nth)-1 + * commands will be processed normally before triggers occur. + */ +static void tweak_cmnd_count(void) +{ + int count, modulo; + + modulo = abs(sdebug_every_nth); + if (modulo < 2) + return; + block_unblock_all_queues(true); + count = atomic_read(&sdebug_cmnd_count); + atomic_set(&sdebug_cmnd_count, (count / modulo) * modulo); + block_unblock_all_queues(false); +} + +static void clear_queue_stats(void) +{ + atomic_set(&sdebug_cmnd_count, 0); + atomic_set(&sdebug_completions, 0); + atomic_set(&sdebug_miss_cpus, 0); + atomic_set(&sdebug_a_tsf, 0); +} + +static void setup_inject(struct sdebug_queue *sqp, + struct sdebug_queued_cmd *sqcp) +{ + if ((atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) > 0) + return; + sqcp->inj_recovered = !!(SDEBUG_OPT_RECOVERED_ERR & sdebug_opts); + sqcp->inj_transport = !!(SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts); + sqcp->inj_dif = !!(SDEBUG_OPT_DIF_ERR & sdebug_opts); + sqcp->inj_dix = !!(SDEBUG_OPT_DIX_ERR & sdebug_opts); + sqcp->inj_short = !!(SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts); +} + +/* Complete the processing of the thread that queued a SCSI command to this + * driver. It either completes the command by calling cmnd_done() or + * schedules a hr timer or work queue then returns 0. Returns + * SCSI_MLQUEUE_HOST_BUSY if temporarily out of resources. + */ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, int scsi_result, int delta_jiff) { unsigned long iflags; int k, num_in_q, qdepth, inject; - struct sdebug_queued_cmd *sqcp = NULL; + struct sdebug_queue *sqp; + struct sdebug_queued_cmd *sqcp; struct scsi_device *sdp; struct sdebug_defer *sd_dp; - if (unlikely(WARN_ON(!cmnd))) - return SCSI_MLQUEUE_HOST_BUSY; - if (unlikely(devip == NULL)) { if (scsi_result == 0) scsi_result = DID_NO_CONNECT << 16; goto respond_in_thread; } - sdp = cmnd->device; if (unlikely(sdebug_verbose && scsi_result)) @@ -3828,17 +3921,22 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, goto respond_in_thread; /* schedule the response at a later time if resources permit */ - spin_lock_irqsave(&queued_arr_lock, iflags); + sqp = get_queue(cmnd); + spin_lock_irqsave(&sqp->qc_lock, iflags); + if (unlikely(atomic_read(&sqp->blocked))) { + spin_unlock_irqrestore(&sqp->qc_lock, iflags); + return SCSI_MLQUEUE_HOST_BUSY; + } num_in_q = atomic_read(&devip->num_in_q); qdepth = cmnd->device->queue_depth; inject = 0; if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) { if (scsi_result) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); + spin_unlock_irqrestore(&sqp->qc_lock, iflags); goto respond_in_thread; } else scsi_result = device_qfull_result; - } else if (unlikely((sdebug_every_nth != 0) && + } else if (unlikely(sdebug_every_nth && (SDEBUG_OPT_RARE_TSF & sdebug_opts) && (scsi_result == 0))) { if ((num_in_q == (qdepth - 1)) && @@ -3850,9 +3948,9 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, } } - k = find_first_zero_bit(queued_in_use_bm, sdebug_max_queue); + k = find_first_zero_bit(sqp->in_use_bm, sdebug_max_queue); if (unlikely(k >= sdebug_max_queue)) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); + spin_unlock_irqrestore(&sqp->qc_lock, iflags); if (scsi_result) goto respond_in_thread; else if (SDEBUG_OPT_ALL_TSF & sdebug_opts) @@ -3868,13 +3966,16 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, else return SCSI_MLQUEUE_HOST_BUSY; } - __set_bit(k, queued_in_use_bm); + __set_bit(k, sqp->in_use_bm); atomic_inc(&devip->num_in_q); - sqcp = &queued_arr[k]; + sqcp = &sqp->qc_arr[k]; sqcp->a_cmnd = cmnd; + cmnd->host_scribble = (unsigned char *)sqcp; cmnd->result = scsi_result; - spin_unlock_irqrestore(&queued_arr_lock, iflags); sd_dp = sqcp->sd_dp; + spin_unlock_irqrestore(&sqp->qc_lock, iflags); + if (unlikely(sdebug_every_nth && sdebug_any_injecting_opt)) + setup_inject(sqp, sqcp); if (delta_jiff > 0 || sdebug_ndelay > 0) { ktime_t kt; @@ -3891,20 +3992,26 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, return SCSI_MLQUEUE_HOST_BUSY; sqcp->sd_dp = sd_dp; hrtimer_init(&sd_dp->hrt, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); + HRTIMER_MODE_REL_PINNED); sd_dp->hrt.function = sdebug_q_cmd_hrt_complete; - sd_dp->qa_indx = k; + sd_dp->sqa_idx = sqp - sdebug_q_arr; + sd_dp->qc_idx = k; } - hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL); - } else { /* jdelay < 0 */ + if (sdebug_statistics) + sd_dp->issuing_cpu = raw_smp_processor_id(); + hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL_PINNED); + } else { /* jdelay < 0, use work queue */ if (NULL == sd_dp) { sd_dp = kzalloc(sizeof(*sqcp->sd_dp), GFP_ATOMIC); if (NULL == sd_dp) return SCSI_MLQUEUE_HOST_BUSY; sqcp->sd_dp = sd_dp; - sd_dp->qa_indx = k; + sd_dp->sqa_idx = sqp - sdebug_q_arr; + sd_dp->qc_idx = k; INIT_WORK(&sd_dp->ew.work, sdebug_q_cmd_wq_complete); } + if (sdebug_statistics) + sd_dp->issuing_cpu = raw_smp_processor_id(); schedule_work(&sd_dp->ew.work); } if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && @@ -3958,7 +4065,9 @@ module_param_named(ptype, sdebug_ptype, int, S_IRUGO | S_IWUSR); module_param_named(removable, sdebug_removable, bool, S_IRUGO | S_IWUSR); module_param_named(scsi_level, sdebug_scsi_level, int, S_IRUGO); module_param_named(sector_size, sdebug_sector_size, int, S_IRUGO); +module_param_named(statistics, sdebug_statistics, bool, S_IRUGO | S_IWUSR); module_param_named(strict, sdebug_strict, bool, S_IRUGO | S_IWUSR); +module_param_named(submit_queues, submit_queues, int, S_IRUGO); module_param_named(unmap_alignment, sdebug_unmap_alignment, int, S_IRUGO); module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO); module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO); @@ -4005,7 +4114,9 @@ MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); MODULE_PARM_DESC(removable, "claim to have removable media (def=0)"); MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])"); MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)"); +MODULE_PARM_DESC(statistics, "collect statistics on commands, queues (def=0)"); MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)"); +MODULE_PARM_DESC(submit_queues, "support for block multi-queue (def=1)"); MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"); MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)"); MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)"); @@ -4018,10 +4129,17 @@ static char sdebug_info[256]; static const char * scsi_debug_info(struct Scsi_Host * shp) { - sprintf(sdebug_info, - "scsi_debug, version %s [%s], dev_size_mb=%d, opts=0x%x", - SDEBUG_VERSION, sdebug_version_date, sdebug_dev_size_mb, - sdebug_opts); + int k; + + k = scnprintf(sdebug_info, sizeof(sdebug_info), + "%s: version %s [%s], dev_size_mb=%d, opts=0x%x\n", + my_name, SDEBUG_VERSION, sdebug_version_date, + sdebug_dev_size_mb, sdebug_opts); + if (k >= (sizeof(sdebug_info) - 1)) + return sdebug_info; + scnprintf(sdebug_info + k, sizeof(sdebug_info) - k, + "%s: submit_queues=%d, statistics=%d\n", my_name, + submit_queues, (int)sdebug_statistics); return sdebug_info; } @@ -4043,7 +4161,7 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, sdebug_verbose = !!(SDEBUG_OPT_NOISE & opts); sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & opts); if (sdebug_every_nth != 0) - atomic_set(&sdebug_cmnd_count, 0); + tweak_cmnd_count(); return length; } @@ -4052,39 +4170,43 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, * output are not atomics so might be inaccurate in a busy system. */ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) { - int f, l; - char b[32]; + int f, j, l; + struct sdebug_queue *sqp; - if (sdebug_every_nth > 0) - snprintf(b, sizeof(b), " (curr:%d)", - ((SDEBUG_OPT_RARE_TSF & sdebug_opts) ? - atomic_read(&sdebug_a_tsf) : - atomic_read(&sdebug_cmnd_count))); - else - b[0] = '\0'; + seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n", + SDEBUG_VERSION, sdebug_version_date); + seq_printf(m, "num_tgts=%d, %ssize=%d MB, opts=0x%x, every_nth=%d\n", + sdebug_num_tgts, "shared (ram) ", sdebug_dev_size_mb, + sdebug_opts, sdebug_every_nth); + seq_printf(m, "delay=%d, ndelay=%d, max_luns=%d, sector_size=%d %s\n", + sdebug_jdelay, sdebug_ndelay, sdebug_max_luns, + sdebug_sector_size, "bytes"); + seq_printf(m, "cylinders=%d, heads=%d, sectors=%d, command aborts=%d\n", + sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per, + num_aborts); + seq_printf(m, "RESETs: device=%d, target=%d, bus=%d, host=%d\n", + num_dev_resets, num_target_resets, num_bus_resets, + num_host_resets); + seq_printf(m, "dix_reads=%d, dix_writes=%d, dif_errors=%d\n", + dix_reads, dix_writes, dif_errors); + seq_printf(m, "usec_in_jiffy=%lu, %s=%d, mq_active=%d\n", + TICK_NSEC / 1000, "statistics", sdebug_statistics, + sdebug_mq_active); + seq_printf(m, "cmnd_count=%d, completions=%d, %s=%d, a_tsf=%d\n", + atomic_read(&sdebug_cmnd_count), + atomic_read(&sdebug_completions), + "miss_cpus", atomic_read(&sdebug_miss_cpus), + atomic_read(&sdebug_a_tsf)); - seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n" - "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, " - "every_nth=%d%s\n" - "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n" - "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" - "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, " - "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d " - "usec_in_jiffy=%lu\n", - SDEBUG_VERSION, sdebug_version_date, - sdebug_num_tgts, sdebug_dev_size_mb, sdebug_opts, - sdebug_every_nth, b, sdebug_jdelay, sdebug_ndelay, - sdebug_max_luns, atomic_read(&sdebug_completions), - sdebug_sector_size, sdebug_cylinders_per, sdebug_heads, - sdebug_sectors_per, num_aborts, num_dev_resets, - num_target_resets, num_bus_resets, num_host_resets, - dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000); - - f = find_first_bit(queued_in_use_bm, sdebug_max_queue); - if (f != sdebug_max_queue) { - l = find_last_bit(queued_in_use_bm, sdebug_max_queue); - seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n", - "queued_in_use_bm", f, l); + seq_printf(m, "submit_queues=%d\n", submit_queues); + for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) { + seq_printf(m, " queue %d:\n", j); + f = find_first_bit(sqp->in_use_bm, sdebug_max_queue); + if (f != sdebug_max_queue) { + l = find_last_bit(sqp->in_use_bm, sdebug_max_queue); + seq_printf(m, " in_use_bm BUSY: %s: %d,%d\n", + "first,last bits", f, l); + } } return 0; } @@ -4093,7 +4215,9 @@ static ssize_t delay_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_jdelay); } -/* Returns -EBUSY if jdelay is being changed and commands are queued */ +/* Returns -EBUSY if jdelay is being changed and commands are queued. The unit + * of delay is jiffies. + */ static ssize_t delay_store(struct device_driver *ddp, const char *buf, size_t count) { @@ -4102,21 +4226,27 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf, if (count > 0 && sscanf(buf, "%d", &jdelay) == 1) { res = count; if (sdebug_jdelay != jdelay) { - unsigned long iflags; - int k; + int j, k; + struct sdebug_queue *sqp; - spin_lock_irqsave(&queued_arr_lock, iflags); - k = find_first_bit(queued_in_use_bm, sdebug_max_queue); - if (k != sdebug_max_queue) - res = -EBUSY; /* have queued commands */ - else { + block_unblock_all_queues(true); + for (j = 0, sqp = sdebug_q_arr; j < submit_queues; + ++j, ++sqp) { + k = find_first_bit(sqp->in_use_bm, + sdebug_max_queue); + if (k != sdebug_max_queue) { + res = -EBUSY; /* queued commands */ + break; + } + } + if (res > 0) { /* make sure sdebug_defer instances get * re-allocated for new delay variant */ free_all_queued(); sdebug_jdelay = jdelay; sdebug_ndelay = 0; } - spin_unlock_irqrestore(&queued_arr_lock, iflags); + block_unblock_all_queues(false); } return res; } @@ -4133,18 +4263,26 @@ static ssize_t ndelay_show(struct device_driver *ddp, char *buf) static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, size_t count) { - unsigned long iflags; - int ndelay, res, k; + int ndelay, res; if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) && - (ndelay >= 0) && (ndelay < 1000000000)) { + (ndelay >= 0) && (ndelay < (1000 * 1000 * 1000))) { res = count; if (sdebug_ndelay != ndelay) { - spin_lock_irqsave(&queued_arr_lock, iflags); - k = find_first_bit(queued_in_use_bm, sdebug_max_queue); - if (k != sdebug_max_queue) - res = -EBUSY; /* have queued commands */ - else { + int j, k; + struct sdebug_queue *sqp; + + block_unblock_all_queues(true); + for (j = 0, sqp = sdebug_q_arr; j < submit_queues; + ++j, ++sqp) { + k = find_first_bit(sqp->in_use_bm, + sdebug_max_queue); + if (k != sdebug_max_queue) { + res = -EBUSY; /* queued commands */ + break; + } + } + if (res > 0) { /* make sure sdebug_defer instances get * re-allocated for new delay variant */ free_all_queued(); @@ -4152,7 +4290,7 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, sdebug_jdelay = ndelay ? JDELAY_OVERRIDDEN : DEF_JDELAY; } - spin_unlock_irqrestore(&queued_arr_lock, iflags); + block_unblock_all_queues(false); } return res; } @@ -4185,8 +4323,7 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf, sdebug_opts = opts; sdebug_verbose = !!(SDEBUG_OPT_NOISE & opts); sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & opts); - atomic_set(&sdebug_cmnd_count, 0); - atomic_set(&sdebug_a_tsf, 0); + tweak_cmnd_count(); return count; } static DRIVER_ATTR_RW(opts); @@ -4316,7 +4453,11 @@ static ssize_t every_nth_store(struct device_driver *ddp, const char *buf, if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) { sdebug_every_nth = nth; - atomic_set(&sdebug_cmnd_count, 0); + if (nth && !sdebug_statistics) { + pr_info("every_nth needs statistics=1, set it\n"); + sdebug_statistics = true; + } + tweak_cmnd_count(); return count; } return -EINVAL; @@ -4371,21 +4512,27 @@ static ssize_t max_queue_show(struct device_driver *ddp, char *buf) static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, size_t count) { - unsigned long iflags; - int n, k; + int j, n, k, a; + struct sdebug_queue *sqp; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) && - (n <= SCSI_DEBUG_CANQUEUE)) { - spin_lock_irqsave(&queued_arr_lock, iflags); - k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE); + (n <= SDEBUG_CANQUEUE)) { + block_unblock_all_queues(true); + k = 0; + for (j = 0, sqp = sdebug_q_arr; j < submit_queues; + ++j, ++sqp) { + a = find_last_bit(sqp->in_use_bm, SDEBUG_CANQUEUE); + if (a > k) + k = a; + } sdebug_max_queue = n; - if (SCSI_DEBUG_CANQUEUE == k) + if (k == SDEBUG_CANQUEUE) atomic_set(&retired_max_queue, 0); else if (k >= n) atomic_set(&retired_max_queue, k + 1); else atomic_set(&retired_max_queue, 0); - spin_unlock_irqrestore(&queued_arr_lock, iflags); + block_unblock_all_queues(false); return count; } return -EINVAL; @@ -4484,12 +4631,40 @@ static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf, } static DRIVER_ATTR_RW(vpd_use_hostno); +static ssize_t statistics_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", (int)sdebug_statistics); +} +static ssize_t statistics_store(struct device_driver *ddp, const char *buf, + size_t count) +{ + int n; + + if ((count > 0) && (sscanf(buf, "%d", &n) == 1) && (n >= 0)) { + if (n > 0) + sdebug_statistics = true; + else { + clear_queue_stats(); + sdebug_statistics = false; + } + return count; + } + return -EINVAL; +} +static DRIVER_ATTR_RW(statistics); + static ssize_t sector_size_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%u\n", sdebug_sector_size); } static DRIVER_ATTR_RO(sector_size); +static ssize_t submit_queues_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", submit_queues); +} +static DRIVER_ATTR_RO(submit_queues); + static ssize_t dix_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dix); @@ -4610,6 +4785,8 @@ static struct attribute *sdebug_drv_attrs[] = { &driver_attr_add_host.attr, &driver_attr_vpd_use_hostno.attr, &driver_attr_sector_size.attr, + &driver_attr_statistics.attr, + &driver_attr_submit_queues.attr, &driver_attr_dix.attr, &driver_attr_dif.attr, &driver_attr_guard.attr, @@ -4632,8 +4809,6 @@ static int __init scsi_debug_init(void) int k; int ret; - atomic_set(&sdebug_cmnd_count, 0); - atomic_set(&sdebug_completions, 0); atomic_set(&retired_max_queue, 0); if (sdebug_ndelay >= 1000 * 1000 * 1000) { @@ -4692,6 +4867,17 @@ static int __init scsi_debug_init(void) return -EINVAL; } + if (submit_queues < 1) { + pr_err("submit_queues must be 1 or more\n"); + return -EINVAL; + } + sdebug_q_arr = kcalloc(submit_queues, sizeof(struct sdebug_queue), + GFP_KERNEL); + if (sdebug_q_arr == NULL) + return -ENOMEM; + for (k = 0; k < submit_queues; ++k) + spin_lock_init(&sdebug_q_arr[k].qc_lock); + if (sdebug_dev_size_mb < 1) sdebug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ sz = (unsigned long)sdebug_dev_size_mb * 1048576; @@ -4719,7 +4905,8 @@ static int __init scsi_debug_init(void) fake_storep = vmalloc(sz); if (NULL == fake_storep) { pr_err("out of memory, 1\n"); - return -ENOMEM; + ret = -ENOMEM; + goto free_q_arr; } memset(fake_storep, 0, sz); if (sdebug_num_parts > 0) @@ -4758,7 +4945,8 @@ static int __init scsi_debug_init(void) sdebug_unmap_granularity <= sdebug_unmap_alignment) { pr_err("ERR: unmap_granularity <= unmap_alignment\n"); - return -EINVAL; + ret = -EINVAL; + goto free_vm; } map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; @@ -4819,7 +5007,8 @@ static int __init scsi_debug_init(void) vfree(map_storep); vfree(dif_storep); vfree(fake_storep); - +free_q_arr: + kfree(sdebug_q_arr); return ret; } @@ -4837,6 +5026,7 @@ static void __exit scsi_debug_exit(void) vfree(dif_storep); vfree(fake_storep); + kfree(sdebug_q_arr); } device_initcall(scsi_debug_init); @@ -4925,62 +5115,43 @@ static void sdebug_remove_adapter(void) static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) { int num_in_q = 0; - unsigned long iflags; struct sdebug_dev_info *devip; - spin_lock_irqsave(&queued_arr_lock, iflags); + block_unblock_all_queues(true); devip = (struct sdebug_dev_info *)sdev->hostdata; if (NULL == devip) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); + block_unblock_all_queues(false); return -ENODEV; } num_in_q = atomic_read(&devip->num_in_q); - spin_unlock_irqrestore(&queued_arr_lock, iflags); if (qdepth < 1) qdepth = 1; - /* allow to exceed max host queued_arr elements for testing */ - if (qdepth > SCSI_DEBUG_CANQUEUE + 10) - qdepth = SCSI_DEBUG_CANQUEUE + 10; + /* allow to exceed max host qc_arr elements for testing */ + if (qdepth > SDEBUG_CANQUEUE + 10) + qdepth = SDEBUG_CANQUEUE + 10; scsi_change_queue_depth(sdev, qdepth); if (SDEBUG_OPT_Q_NOISE & sdebug_opts) { - sdev_printk(KERN_INFO, sdev, - "%s: qdepth=%d, num_in_q=%d\n", + sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d, num_in_q=%d\n", __func__, qdepth, num_in_q); } + block_unblock_all_queues(false); return sdev->queue_depth; } -static int check_inject(struct scsi_cmnd *scp) +static bool fake_timeout(struct scsi_cmnd *scp) { - struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); - - memset(ep, 0, sizeof(struct sdebug_scmd_extra_t)); - - if (atomic_inc_return(&sdebug_cmnd_count) >= abs(sdebug_every_nth)) { - atomic_set(&sdebug_cmnd_count, 0); + if (0 == (atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth))) { if (sdebug_every_nth < -1) sdebug_every_nth = -1; if (SDEBUG_OPT_TIMEOUT & sdebug_opts) - return 1; /* ignore command causing timeout */ + return true; /* ignore command causing timeout */ else if (SDEBUG_OPT_MAC_TIMEOUT & sdebug_opts && scsi_medium_access_command(scp)) - return 1; /* time out reads and writes */ - if (sdebug_any_injecting_opt) { - if (SDEBUG_OPT_RECOVERED_ERR & sdebug_opts) - ep->inj_recovered = true; - if (SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts) - ep->inj_transport = true; - if (SDEBUG_OPT_DIF_ERR & sdebug_opts) - ep->inj_dif = true; - if (SDEBUG_OPT_DIX_ERR & sdebug_opts) - ep->inj_dix = true; - if (SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts) - ep->inj_short = true; - } + return true; /* time out reads and writes */ } - return 0; + return false; } static int scsi_debug_queuecommand(struct Scsi_Host *shost, @@ -5001,6 +5172,8 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, bool has_wlun_rl; scsi_set_resid(scp, 0); + if (sdebug_statistics) + atomic_inc(&sdebug_cmnd_count); if (unlikely(sdebug_verbose && !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts))) { char b[120]; @@ -5015,7 +5188,13 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, n += scnprintf(b + n, sb - n, "%02x ", (u32)cmd[k]); } - sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b); + if (sdebug_mq_active) + sdev_printk(KERN_INFO, sdp, "%s: tag=%u, cmd %s\n", + my_name, blk_mq_unique_tag(scp->request), + b); + else + sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, + b); } has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS); if (unlikely((sdp->lun >= sdebug_max_luns) && !has_wlun_rl)) @@ -5093,7 +5272,7 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, if (errsts) goto check_cond; } - if (unlikely((F_M_ACCESS & flags) && devip->stopped)) { + if (unlikely((F_M_ACCESS & flags) && atomic_read(&devip->stopped))) { mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); if (sdebug_verbose) sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: " @@ -5105,7 +5284,7 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, if (sdebug_fake_rw && (F_FAKE_RW & flags)) goto fini; if (unlikely(sdebug_every_nth)) { - if (check_inject(scp)) + if (fake_timeout(scp)) return 0; /* ignore command: make trouble */ } if (likely(oip->pfp)) @@ -5139,7 +5318,7 @@ static struct scsi_host_template sdebug_driver_template = { .eh_target_reset_handler = scsi_debug_target_reset, .eh_bus_reset_handler = scsi_debug_bus_reset, .eh_host_reset_handler = scsi_debug_host_reset, - .can_queue = SCSI_DEBUG_CANQUEUE, + .can_queue = SDEBUG_CANQUEUE, .this_id = 7, .sg_tablesize = SG_MAX_SEGMENTS, .cmd_per_lun = DEF_CMD_PER_LUN, @@ -5147,7 +5326,6 @@ static struct scsi_host_template sdebug_driver_template = { .use_clustering = DISABLE_CLUSTERING, .module = THIS_MODULE, .track_queue_depth = 1, - .cmd_size = sizeof(struct sdebug_scmd_extra_t), }; static int sdebug_driver_probe(struct device * dev) @@ -5168,6 +5346,16 @@ static int sdebug_driver_probe(struct device * dev) error = -ENODEV; return error; } + if (submit_queues > nr_cpu_ids) { + pr_warn("%s: trim submit_queues (was %d) to nr_cpu_ids=%d\n", + my_name, submit_queues, nr_cpu_ids); + submit_queues = nr_cpu_ids; + } + /* Decide whether to tell scsi subsystem that we want mq */ + /* Following should give the same answer for each host */ + sdebug_mq_active = shost_use_blk_mq(hpnt) && (submit_queues > 1); + if (sdebug_mq_active) + hpnt->nr_hw_queues = submit_queues; sdbg_host->shost = hpnt; *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; @@ -5225,6 +5413,8 @@ static int sdebug_driver_probe(struct device * dev) sdebug_verbose = !!(SDEBUG_OPT_NOISE & sdebug_opts); sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & sdebug_opts); + if (sdebug_every_nth) /* need stats counters for every_nth */ + sdebug_statistics = true; error = scsi_add_host(hpnt, &sdbg_host->dev); if (error) { pr_err("scsi_add_host failed\n"); From 760f3b0342df19c2cfe53fffcc5ff5e2311447a6 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Fri, 6 May 2016 00:40:27 -0400 Subject: [PATCH 125/138] scsi_debug: vpd and mode page work Cleanup some mode and vpd pages. Stop reporting SBC (disk) pages when peripheral type is something else (e.g. tape). Update version descriptors. Expand LBPRZ flag handling. Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 185 ++++++++++++++++++++++---------------- 1 file changed, 107 insertions(+), 78 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 2ee55d54d125..afbbfaa20a34 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -125,7 +125,7 @@ static const char *sdebug_version_date = "20160430"; #define DEF_PHYSBLK_EXP 0 #define DEF_PTYPE TYPE_DISK #define DEF_REMOVABLE false -#define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */ +#define DEF_SCSI_LEVEL 7 /* INQUIRY, byte2 [6->SPC-4; 7->SPC-5] */ #define DEF_SECTOR_SIZE 512 #define DEF_UNMAP_ALIGNMENT 0 #define DEF_UNMAP_GRANULARITY 1 @@ -661,7 +661,11 @@ static const int device_qfull_result = (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL; -static inline unsigned int scsi_debug_lbp(void) +/* Only do the extra work involved in logical block provisioning if one or + * more of the lbpu, lbpws or lbpws10 parameters are given and we are doing + * real reads and writes (i.e. not skipping them for speed). + */ +static inline bool scsi_debug_lbp(void) { return 0 == sdebug_fake_rw && (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10); @@ -922,10 +926,10 @@ static const u64 naa5_comp_b = 0x5333333000000000ULL; static const u64 naa5_comp_c = 0x5111111000000000ULL; /* Device identification VPD page. Returns number of bytes placed in arr */ -static int inquiry_evpd_83(unsigned char * arr, int port_group_id, - int target_dev_id, int dev_id_num, - const char * dev_id_str, - int dev_id_str_len) +static int inquiry_vpd_83(unsigned char *arr, int port_group_id, + int target_dev_id, int dev_id_num, + const char *dev_id_str, + int dev_id_str_len) { int num, port_a; char b[32]; @@ -1004,14 +1008,14 @@ static unsigned char vpd84_data[] = { }; /* Software interface identification VPD page */ -static int inquiry_evpd_84(unsigned char * arr) +static int inquiry_vpd_84(unsigned char *arr) { memcpy(arr, vpd84_data, sizeof(vpd84_data)); return sizeof(vpd84_data); } /* Management network addresses VPD page */ -static int inquiry_evpd_85(unsigned char * arr) +static int inquiry_vpd_85(unsigned char *arr) { int num = 0; const char * na1 = "https://www.kernel.org/config"; @@ -1046,7 +1050,7 @@ static int inquiry_evpd_85(unsigned char * arr) } /* SCSI ports VPD page */ -static int inquiry_evpd_88(unsigned char * arr, int target_dev_id) +static int inquiry_vpd_88(unsigned char *arr, int target_dev_id) { int num = 0; int port_a, port_b; @@ -1133,7 +1137,7 @@ static unsigned char vpd89_data[] = { }; /* ATA Information VPD page */ -static int inquiry_evpd_89(unsigned char * arr) +static int inquiry_vpd_89(unsigned char *arr) { memcpy(arr, vpd89_data, sizeof(vpd89_data)); return sizeof(vpd89_data); @@ -1148,7 +1152,7 @@ static unsigned char vpdb0_data[] = { }; /* Block limits VPD page (SBC-3) */ -static int inquiry_evpd_b0(unsigned char * arr) +static int inquiry_vpd_b0(unsigned char *arr) { unsigned int gran; @@ -1191,7 +1195,7 @@ static int inquiry_evpd_b0(unsigned char * arr) } /* Block device characteristics VPD page (SBC-3) */ -static int inquiry_evpd_b1(unsigned char *arr) +static int inquiry_vpd_b1(unsigned char *arr) { memset(arr, 0, 0x3c); arr[0] = 0; @@ -1202,24 +1206,22 @@ static int inquiry_evpd_b1(unsigned char *arr) return 0x3c; } -/* Logical block provisioning VPD page (SBC-3) */ -static int inquiry_evpd_b2(unsigned char *arr) +/* Logical block provisioning VPD page (SBC-4) */ +static int inquiry_vpd_b2(unsigned char *arr) { memset(arr, 0, 0x4); arr[0] = 0; /* threshold exponent */ - if (sdebug_lbpu) arr[1] = 1 << 7; - if (sdebug_lbpws) arr[1] |= 1 << 6; - if (sdebug_lbpws10) arr[1] |= 1 << 5; - - if (sdebug_lbprz) - arr[1] |= 1 << 2; - + if (sdebug_lbprz && scsi_debug_lbp()) + arr[1] |= (sdebug_lbprz & 0x7) << 2; /* sbc4r07 and later */ + /* anc_sup=0; dp=0 (no provisioning group descriptor) */ + /* minimum_percentage=0; provisioning_type=0 (unknown) */ + /* threshold_percentage=0 */ return 0x4; } @@ -1232,12 +1234,13 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) unsigned char * arr; unsigned char *cmd = scp->cmnd; int alloc_len, n, ret; - bool have_wlun; + bool have_wlun, is_disk; alloc_len = get_unaligned_be16(cmd + 3); arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); if (! arr) return DID_REQUEUE << 16; + is_disk = (sdebug_ptype == TYPE_DISK); have_wlun = scsi_is_wlun(scp->device->lun); if (have_wlun) pq_pdt = TYPE_WLUN; /* present, wlun */ @@ -1275,11 +1278,12 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) arr[n++] = 0x86; /* extended inquiry */ arr[n++] = 0x87; /* mode page policy */ arr[n++] = 0x88; /* SCSI ports */ - arr[n++] = 0x89; /* ATA information */ - arr[n++] = 0xb0; /* Block limits (SBC) */ - arr[n++] = 0xb1; /* Block characteristics (SBC) */ - if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */ - arr[n++] = 0xb2; + if (is_disk) { /* SBC only */ + arr[n++] = 0x89; /* ATA information */ + arr[n++] = 0xb0; /* Block limits */ + arr[n++] = 0xb1; /* Block characteristics */ + arr[n++] = 0xb2; /* Logical Block Prov */ + } arr[3] = n - 4; /* number of supported VPD pages */ } else if (0x80 == cmd[2]) { /* unit serial number */ arr[1] = cmd[2]; /*sanity */ @@ -1287,21 +1291,21 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) memcpy(&arr[4], lu_id_str, len); } else if (0x83 == cmd[2]) { /* device identification */ arr[1] = cmd[2]; /*sanity */ - arr[3] = inquiry_evpd_83(&arr[4], port_group_id, - target_dev_id, lu_id_num, - lu_id_str, len); + arr[3] = inquiry_vpd_83(&arr[4], port_group_id, + target_dev_id, lu_id_num, + lu_id_str, len); } else if (0x84 == cmd[2]) { /* Software interface ident. */ arr[1] = cmd[2]; /*sanity */ - arr[3] = inquiry_evpd_84(&arr[4]); + arr[3] = inquiry_vpd_84(&arr[4]); } else if (0x85 == cmd[2]) { /* Management network addresses */ arr[1] = cmd[2]; /*sanity */ - arr[3] = inquiry_evpd_85(&arr[4]); + arr[3] = inquiry_vpd_85(&arr[4]); } else if (0x86 == cmd[2]) { /* extended inquiry */ arr[1] = cmd[2]; /*sanity */ arr[3] = 0x3c; /* number of following entries */ if (sdebug_dif == SD_DIF_TYPE3_PROTECTION) arr[4] = 0x4; /* SPT: GRD_CHK:1 */ - else if (sdebug_dif) + else if (have_dif_prot) arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */ else arr[4] = 0x0; /* no protection stuff */ @@ -1315,20 +1319,20 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) arr[10] = 0x82; /* mlus, per initiator port */ } else if (0x88 == cmd[2]) { /* SCSI Ports */ arr[1] = cmd[2]; /*sanity */ - arr[3] = inquiry_evpd_88(&arr[4], target_dev_id); - } else if (0x89 == cmd[2]) { /* ATA information */ + arr[3] = inquiry_vpd_88(&arr[4], target_dev_id); + } else if (is_disk && 0x89 == cmd[2]) { /* ATA information */ arr[1] = cmd[2]; /*sanity */ - n = inquiry_evpd_89(&arr[4]); + n = inquiry_vpd_89(&arr[4]); put_unaligned_be16(n, arr + 2); - } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */ + } else if (is_disk && 0xb0 == cmd[2]) { /* Block limits */ arr[1] = cmd[2]; /*sanity */ - arr[3] = inquiry_evpd_b0(&arr[4]); - } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */ + arr[3] = inquiry_vpd_b0(&arr[4]); + } else if (is_disk && 0xb1 == cmd[2]) { /* Block char. */ arr[1] = cmd[2]; /*sanity */ - arr[3] = inquiry_evpd_b1(&arr[4]); - } else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */ + arr[3] = inquiry_vpd_b1(&arr[4]); + } else if (is_disk && 0xb2 == cmd[2]) { /* LB Prov. */ arr[1] = cmd[2]; /*sanity */ - arr[3] = inquiry_evpd_b2(&arr[4]); + arr[3] = inquiry_vpd_b2(&arr[4]); } else { mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1); kfree(arr); @@ -1355,15 +1359,17 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) memcpy(&arr[16], inq_product_id, 16); memcpy(&arr[32], inq_product_rev, 4); /* version descriptors (2 bytes each) follow */ - arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */ - arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */ + put_unaligned_be16(0xc0, arr + 58); /* SAM-6 no version claimed */ + put_unaligned_be16(0x5c0, arr + 60); /* SPC-5 no version claimed */ n = 62; - if (sdebug_ptype == TYPE_DISK) { - arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */ - } else if (sdebug_ptype == TYPE_TAPE) { - arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */ + if (is_disk) { /* SBC-4 no version claimed */ + put_unaligned_be16(0x600, arr + n); + n += 2; + } else if (sdebug_ptype == TYPE_TAPE) { /* SSC-4 rev 3 */ + put_unaligned_be16(0x525, arr + n); + n += 2; } - arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */ + put_unaligned_be16(0x2100, arr + n); /* SPL-4 no version claimed */ ret = fill_from_dev_buffer(scp, arr, min(alloc_len, SDEBUG_LONG_INQ_SZ)); kfree(arr); @@ -1499,13 +1505,17 @@ static int resp_readcap16(struct scsi_cmnd * scp, if (scsi_debug_lbp()) { arr[14] |= 0x80; /* LBPME */ - if (sdebug_lbprz) - arr[14] |= 0x40; /* LBPRZ */ + /* from sbc4r07, this LBPRZ field is 1 bit, but the LBPRZ in + * the LB Provisioning VPD page is 3 bits. Note that lbprz=2 + * in the wider field maps to 0 in this field. + */ + if (sdebug_lbprz & 1) /* precisely what the draft requires */ + arr[14] |= 0x40; } arr[15] = sdebug_lowest_aligned & 0xff; - if (sdebug_dif) { + if (have_dif_prot) { arr[12] = (sdebug_dif - 1) << 1; /* P_TYPE */ arr[12] |= 1; /* PROT_EN */ } @@ -1935,22 +1945,23 @@ static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol) static int resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { - unsigned char dbd, llbaa; int pcontrol, pcode, subpcode, bd_len; unsigned char dev_spec; - int alloc_len, msense_6, offset, len, target_dev_id; + int alloc_len, offset, len, target_dev_id; int target = scp->device->id; unsigned char * ap; unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; unsigned char *cmd = scp->cmnd; + bool dbd, llbaa, msense_6, is_disk, bad_pcode; - dbd = !!(cmd[1] & 0x8); + dbd = !!(cmd[1] & 0x8); /* disable block descriptors */ pcontrol = (cmd[2] & 0xc0) >> 6; pcode = cmd[2] & 0x3f; subpcode = cmd[3]; msense_6 = (MODE_SENSE == cmd[0]); - llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10); - if ((sdebug_ptype == TYPE_DISK) && (dbd == 0)) + llbaa = msense_6 ? false : !!(cmd[1] & 0x10); + is_disk = (sdebug_ptype == TYPE_DISK); + if (is_disk && !dbd) bd_len = llbaa ? 16 : 8; else bd_len = 0; @@ -1963,7 +1974,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + (devip->target * 1000) - 3; /* for disks set DPOFUA bit and clear write protect (WP) bit */ - if (sdebug_ptype == TYPE_DISK) + if (is_disk) dev_spec = 0x10; /* =0x90 if WP=1 implies read-only */ else dev_spec = 0x0; @@ -2002,6 +2013,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp, mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); return check_condition_result; } + bad_pcode = false; + switch (pcode) { case 0x1: /* Read-Write error recovery page, direct access */ len = resp_err_recov_pg(ap, pcontrol, target); @@ -2012,12 +2025,18 @@ static int resp_mode_sense(struct scsi_cmnd *scp, offset += len; break; case 0x3: /* Format device page, direct access */ - len = resp_format_pg(ap, pcontrol, target); - offset += len; + if (is_disk) { + len = resp_format_pg(ap, pcontrol, target); + offset += len; + } else + bad_pcode = true; break; case 0x8: /* Caching page, direct access */ - len = resp_caching_pg(ap, pcontrol, target); - offset += len; + if (is_disk) { + len = resp_caching_pg(ap, pcontrol, target); + offset += len; + } else + bad_pcode = true; break; case 0xa: /* Control Mode page, all devices */ len = resp_ctrl_m_pg(ap, pcontrol, target); @@ -2046,8 +2065,12 @@ static int resp_mode_sense(struct scsi_cmnd *scp, if ((0 == subpcode) || (0xff == subpcode)) { len = resp_err_recov_pg(ap, pcontrol, target); len += resp_disconnect_pg(ap + len, pcontrol, target); - len += resp_format_pg(ap + len, pcontrol, target); - len += resp_caching_pg(ap + len, pcontrol, target); + if (is_disk) { + len += resp_format_pg(ap + len, pcontrol, + target); + len += resp_caching_pg(ap + len, pcontrol, + target); + } len += resp_ctrl_m_pg(ap + len, pcontrol, target); len += resp_sas_sf_m_pg(ap + len, pcontrol, target); if (0xff == subpcode) { @@ -2056,13 +2079,17 @@ static int resp_mode_sense(struct scsi_cmnd *scp, len += resp_sas_sha_m_spg(ap + len, pcontrol); } len += resp_iec_m_pg(ap + len, pcontrol, target); + offset += len; } else { mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); return check_condition_result; } - offset += len; break; default: + bad_pcode = true; + break; + } + if (bad_pcode) { mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5); return check_condition_result; } @@ -2753,9 +2780,10 @@ static void unmap_region(sector_t lba, unsigned int len) lba + sdebug_unmap_granularity <= end && index < map_size) { clear_bit(index, map_storep); - if (sdebug_lbprz) { + if (sdebug_lbprz) { /* for LBPRZ=2 return 0xff_s */ memset(fake_storep + - lba * sdebug_sector_size, 0, + lba * sdebug_sector_size, + (sdebug_lbprz & 1) ? 0 : 0xff, sdebug_sector_size * sdebug_unmap_granularity); } @@ -4098,7 +4126,8 @@ MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)"); MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)"); MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)"); MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)"); -MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)"); +MODULE_PARM_DESC(lbprz, + "on read unmapped LBs return 0 when 1 (def), return 0xff when 2"); MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)"); MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))"); @@ -4112,7 +4141,7 @@ MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)"); MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); MODULE_PARM_DESC(removable, "claim to have removable media (def=0)"); -MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])"); +MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=7[SPC-5])"); MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)"); MODULE_PARM_DESC(statistics, "collect statistics on commands, queues (def=0)"); MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)"); @@ -4125,21 +4154,21 @@ MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)"); -static char sdebug_info[256]; +#define SDEBUG_INFO_LEN 256 +static char sdebug_info[SDEBUG_INFO_LEN]; static const char * scsi_debug_info(struct Scsi_Host * shp) { int k; - k = scnprintf(sdebug_info, sizeof(sdebug_info), - "%s: version %s [%s], dev_size_mb=%d, opts=0x%x\n", - my_name, SDEBUG_VERSION, sdebug_version_date, - sdebug_dev_size_mb, sdebug_opts); - if (k >= (sizeof(sdebug_info) - 1)) + k = scnprintf(sdebug_info, SDEBUG_INFO_LEN, "%s: version %s [%s]\n", + my_name, SDEBUG_VERSION, sdebug_version_date); + if (k >= (SDEBUG_INFO_LEN - 1)) return sdebug_info; - scnprintf(sdebug_info + k, sizeof(sdebug_info) - k, - "%s: submit_queues=%d, statistics=%d\n", my_name, - submit_queues, (int)sdebug_statistics); + scnprintf(sdebug_info + k, SDEBUG_INFO_LEN - k, + " dev_size_mb=%d, opts=0x%x, submit_queues=%d, %s=%d", + sdebug_dev_size_mb, sdebug_opts, submit_queues, + "statistics", (int)sdebug_statistics); return sdebug_info; } From 09ba24c18c7e0c215c39b3d92332b64132dae170 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Fri, 6 May 2016 00:40:28 -0400 Subject: [PATCH 126/138] scsi_debug: uuid for lu name Permit changing of a LU name from a (fake) IEEE registered NAA (5) to a locally assigned UUID. Using a UUID (RFC 4122) for a SCSI designation descriptor (e.g. a LU name) was added in spc5r08.pdf (a draft INCITS standard) on 25 January 2016. Add parameter uuid_ctl to use a separate UUID for each LU (storage device) name. Additional option for all LU names to have the same UUID (since their storage is shared). Previous action of using NAA identifier for LU name remains the default. Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 61 ++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index afbbfaa20a34..efb454906fc7 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -137,6 +138,7 @@ static const char *sdebug_version_date = "20160430"; #define DEF_STRICT 0 #define DEF_STATISTICS false #define DEF_SUBMIT_QUEUES 1 +#define DEF_UUID_CTL 0 #define JDELAY_OVERRIDDEN -9999 #define SDEBUG_LUN_0_VAL 0 @@ -241,6 +243,7 @@ struct sdebug_dev_info { unsigned int channel; unsigned int target; u64 lun; + uuid_be lu_name; struct sdebug_host_info *sdbg_host; unsigned long uas_bm[1]; atomic_t num_in_q; @@ -600,6 +603,7 @@ static unsigned int sdebug_unmap_granularity = DEF_UNMAP_GRANULARITY; static unsigned int sdebug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS; static unsigned int sdebug_unmap_max_desc = DEF_UNMAP_MAX_DESC; static unsigned int sdebug_write_same_length = DEF_WRITESAME_LENGTH; +static int sdebug_uuid_ctl = DEF_UUID_CTL; static bool sdebug_removable = DEF_REMOVABLE; static bool sdebug_clustering; static bool sdebug_host_lock = DEF_HOST_LOCK; @@ -928,8 +932,8 @@ static const u64 naa5_comp_c = 0x5111111000000000ULL; /* Device identification VPD page. Returns number of bytes placed in arr */ static int inquiry_vpd_83(unsigned char *arr, int port_group_id, int target_dev_id, int dev_id_num, - const char *dev_id_str, - int dev_id_str_len) + const char *dev_id_str, int dev_id_str_len, + const uuid_be *lu_name) { int num, port_a; char b[32]; @@ -946,13 +950,25 @@ static int inquiry_vpd_83(unsigned char *arr, int port_group_id, arr[3] = num; num += 4; if (dev_id_num >= 0) { - /* NAA-5, Logical unit identifier (binary) */ - arr[num++] = 0x1; /* binary (not necessarily sas) */ - arr[num++] = 0x3; /* PIV=0, lu, naa */ - arr[num++] = 0x0; - arr[num++] = 0x8; - put_unaligned_be64(naa5_comp_b + dev_id_num, arr + num); - num += 8; + if (sdebug_uuid_ctl) { + /* Locally assigned UUID */ + arr[num++] = 0x1; /* binary (not necessarily sas) */ + arr[num++] = 0xa; /* PIV=0, lu, naa */ + arr[num++] = 0x0; + arr[num++] = 0x12; + arr[num++] = 0x10; /* uuid type=1, locally assigned */ + arr[num++] = 0x0; + memcpy(arr + num, lu_name, 16); + num += 16; + } else { + /* NAA-5, Logical unit identifier (binary) */ + arr[num++] = 0x1; /* binary (not necessarily sas) */ + arr[num++] = 0x3; /* PIV=0, lu, naa */ + arr[num++] = 0x0; + arr[num++] = 0x8; + put_unaligned_be64(naa5_comp_b + dev_id_num, arr + num); + num += 8; + } /* Target relative port number */ arr[num++] = 0x61; /* proto=sas, binary */ arr[num++] = 0x94; /* PIV=1, target port, rel port */ @@ -1293,7 +1309,8 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) arr[1] = cmd[2]; /*sanity */ arr[3] = inquiry_vpd_83(&arr[4], port_group_id, target_dev_id, lu_id_num, - lu_id_str, len); + lu_id_str, len, + &devip->lu_name); } else if (0x84 == cmd[2]) { /* Software interface ident. */ arr[1] = cmd[2]; /*sanity */ arr[3] = inquiry_vpd_84(&arr[4]); @@ -3503,6 +3520,9 @@ static void sdebug_q_cmd_wq_complete(struct work_struct *work) sdebug_q_cmd_complete(sd_dp); } +static bool got_shared_uuid; +static uuid_be shared_uuid; + static struct sdebug_dev_info *sdebug_device_create( struct sdebug_host_info *sdbg_host, gfp_t flags) { @@ -3510,6 +3530,17 @@ static struct sdebug_dev_info *sdebug_device_create( devip = kzalloc(sizeof(*devip), flags); if (devip) { + if (sdebug_uuid_ctl == 1) + uuid_be_gen(&devip->lu_name); + else if (sdebug_uuid_ctl == 2) { + if (got_shared_uuid) + devip->lu_name = shared_uuid; + else { + uuid_be_gen(&shared_uuid); + got_shared_uuid = true; + devip->lu_name = shared_uuid; + } + } devip->sdbg_host = sdbg_host; list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list); } @@ -4101,6 +4132,7 @@ module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO); module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO); module_param_named(unmap_max_desc, sdebug_unmap_max_desc, int, S_IRUGO); module_param_named(virtual_gb, sdebug_virtual_gb, int, S_IRUGO | S_IWUSR); +module_param_named(uuid_ctl, sdebug_uuid_ctl, int, S_IRUGO); module_param_named(vpd_use_hostno, sdebug_vpd_use_hostno, int, S_IRUGO | S_IWUSR); module_param_named(write_same_length, sdebug_write_same_length, int, @@ -4150,6 +4182,8 @@ MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)" MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)"); MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)"); MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)"); +MODULE_PARM_DESC(uuid_ctl, + "1->use uuid for lu name, 0->don't, 2->all use same (def=0)"); MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)"); MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)"); @@ -4787,6 +4821,12 @@ static ssize_t strict_store(struct device_driver *ddp, const char *buf, } static DRIVER_ATTR_RW(strict); +static ssize_t uuid_ctl_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", !!sdebug_uuid_ctl); +} +static DRIVER_ATTR_RO(uuid_ctl); + /* Note: The following array creates attribute files in the /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these @@ -4825,6 +4865,7 @@ static struct attribute *sdebug_drv_attrs[] = { &driver_attr_host_lock.attr, &driver_attr_ndelay.attr, &driver_attr_strict.attr, + &driver_attr_uuid_ctl.attr, NULL, }; ATTRIBUTE_GROUPS(sdebug_drv); From 1b37bd606deef0a787bdbbab6ff51dbebdeb9d3d Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Fri, 6 May 2016 00:40:29 -0400 Subject: [PATCH 127/138] scsi_debug: use locally assigned naa For reported SAS addresses replace fake IEEE registered NAAs (5) with locally assigned NAAs (3). Signed-off-by: Douglas Gilbert Reviewed-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index efb454906fc7..0f9ba41e27d8 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -925,9 +925,10 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, static const char * inq_vendor_id = "Linux "; static const char * inq_product_id = "scsi_debug "; static const char *inq_product_rev = "0186"; /* version less '.' */ -static const u64 naa5_comp_a = 0x5222222000000000ULL; -static const u64 naa5_comp_b = 0x5333333000000000ULL; -static const u64 naa5_comp_c = 0x5111111000000000ULL; +/* Use some locally assigned NAAs for SAS addresses. */ +static const u64 naa3_comp_a = 0x3222222000000000ULL; +static const u64 naa3_comp_b = 0x3333333000000000ULL; +static const u64 naa3_comp_c = 0x3111111000000000ULL; /* Device identification VPD page. Returns number of bytes placed in arr */ static int inquiry_vpd_83(unsigned char *arr, int port_group_id, @@ -961,12 +962,12 @@ static int inquiry_vpd_83(unsigned char *arr, int port_group_id, memcpy(arr + num, lu_name, 16); num += 16; } else { - /* NAA-5, Logical unit identifier (binary) */ + /* NAA-3, Logical unit identifier (binary) */ arr[num++] = 0x1; /* binary (not necessarily sas) */ arr[num++] = 0x3; /* PIV=0, lu, naa */ arr[num++] = 0x0; arr[num++] = 0x8; - put_unaligned_be64(naa5_comp_b + dev_id_num, arr + num); + put_unaligned_be64(naa3_comp_b + dev_id_num, arr + num); num += 8; } /* Target relative port number */ @@ -979,14 +980,14 @@ static int inquiry_vpd_83(unsigned char *arr, int port_group_id, arr[num++] = 0x0; arr[num++] = 0x1; /* relative port A */ } - /* NAA-5, Target port identifier */ + /* NAA-3, Target port identifier */ arr[num++] = 0x61; /* proto=sas, binary */ arr[num++] = 0x93; /* piv=1, target port, naa */ arr[num++] = 0x0; arr[num++] = 0x8; - put_unaligned_be64(naa5_comp_a + port_a, arr + num); + put_unaligned_be64(naa3_comp_a + port_a, arr + num); num += 8; - /* NAA-5, Target port group identifier */ + /* NAA-3, Target port group identifier */ arr[num++] = 0x61; /* proto=sas, binary */ arr[num++] = 0x95; /* piv=1, target port group id */ arr[num++] = 0x0; @@ -995,19 +996,19 @@ static int inquiry_vpd_83(unsigned char *arr, int port_group_id, arr[num++] = 0; put_unaligned_be16(port_group_id, arr + num); num += 2; - /* NAA-5, Target device identifier */ + /* NAA-3, Target device identifier */ arr[num++] = 0x61; /* proto=sas, binary */ arr[num++] = 0xa3; /* piv=1, target device, naa */ arr[num++] = 0x0; arr[num++] = 0x8; - put_unaligned_be64(naa5_comp_a + target_dev_id, arr + num); + put_unaligned_be64(naa3_comp_a + target_dev_id, arr + num); num += 8; /* SCSI name string: Target device identifier */ arr[num++] = 0x63; /* proto=sas, UTF-8 */ arr[num++] = 0xa8; /* piv=1, target device, SCSI name string */ arr[num++] = 0x0; arr[num++] = 24; - memcpy(arr + num, "naa.52222220", 12); + memcpy(arr + num, "naa.32222220", 12); num += 12; snprintf(b, sizeof(b), "%08X", target_dev_id); memcpy(arr + num, b, 8); @@ -1086,7 +1087,7 @@ static int inquiry_vpd_88(unsigned char *arr, int target_dev_id) arr[num++] = 0x93; /* PIV=1, target port, NAA */ arr[num++] = 0x0; /* reserved */ arr[num++] = 0x8; /* length */ - put_unaligned_be64(naa5_comp_a + port_a, arr + num); + put_unaligned_be64(naa3_comp_a + port_a, arr + num); num += 8; arr[num++] = 0x0; /* reserved */ arr[num++] = 0x0; /* reserved */ @@ -1101,7 +1102,7 @@ static int inquiry_vpd_88(unsigned char *arr, int target_dev_id) arr[num++] = 0x93; /* PIV=1, target port, NAA */ arr[num++] = 0x0; /* reserved */ arr[num++] = 0x8; /* length */ - put_unaligned_be64(naa5_comp_a + port_b, arr + num); + put_unaligned_be64(naa3_comp_a + port_b, arr + num); num += 8; return num; @@ -1931,10 +1932,10 @@ static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target, }; int port_a, port_b; - put_unaligned_be64(naa5_comp_a, sas_pcd_m_pg + 16); - put_unaligned_be64(naa5_comp_c + 1, sas_pcd_m_pg + 24); - put_unaligned_be64(naa5_comp_a, sas_pcd_m_pg + 64); - put_unaligned_be64(naa5_comp_c + 1, sas_pcd_m_pg + 72); + put_unaligned_be64(naa3_comp_a, sas_pcd_m_pg + 16); + put_unaligned_be64(naa3_comp_c + 1, sas_pcd_m_pg + 24); + put_unaligned_be64(naa3_comp_a, sas_pcd_m_pg + 64); + put_unaligned_be64(naa3_comp_c + 1, sas_pcd_m_pg + 72); port_a = target_dev_id + 1; port_b = port_a + 1; memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg)); From fe8b9534a0a0356f8a76467e2c561194bdb53c84 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 6 May 2016 10:34:35 +0200 Subject: [PATCH 128/138] scsi_dh_alua: do not fail for unknown VPD identification Not every device will return a useable VPD identification, but still might support ALUA. Rather than disable ALUA support we should be allowing the device identification to be empty and attach individual ALUA device handler to each devices. [mkp: Fixed typo reported by Bart] Reported-by: Paul Mackerras Signed-off-by: Hannes Reinecke Tested-by: Paul Mackerras Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index e034f12c1418..b2244eb90776 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -195,10 +195,13 @@ static struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size, { struct alua_port_group *pg; + if (!id_str || !id_size || !strlen(id_str)) + return NULL; + list_for_each_entry(pg, &port_group_list, node) { if (pg->group_id != group_id) continue; - if (pg->device_id_len != id_size) + if (!pg->device_id_len || pg->device_id_len != id_size) continue; if (strncmp(pg->device_id_str, id_str, id_size)) continue; @@ -232,14 +235,14 @@ static struct alua_port_group *alua_alloc_pg(struct scsi_device *sdev, sizeof(pg->device_id_str)); if (pg->device_id_len <= 0) { /* - * Internal error: TPGS supported but no device - * identifcation found. Disable ALUA support. + * TPGS supported but no device identification found. + * Generate private device identification. */ - kfree(pg); sdev_printk(KERN_INFO, sdev, "%s: No device descriptors found\n", ALUA_DH_NAME); - return ERR_PTR(-ENXIO); + pg->device_id_str[0] = '\0'; + pg->device_id_len = 0; } pg->group_id = group_id; pg->tpgs = tpgs; @@ -354,9 +357,15 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h, return SCSI_DH_NOMEM; return SCSI_DH_DEV_UNSUPP; } - sdev_printk(KERN_INFO, sdev, - "%s: device %s port group %x rel port %x\n", - ALUA_DH_NAME, pg->device_id_str, group_id, rel_port); + if (pg->device_id_len) + sdev_printk(KERN_INFO, sdev, + "%s: device %s port group %x rel port %x\n", + ALUA_DH_NAME, pg->device_id_str, + group_id, rel_port); + else + sdev_printk(KERN_INFO, sdev, + "%s: port group %x rel port %x\n", + ALUA_DH_NAME, group_id, rel_port); /* Check for existing port group references */ spin_lock(&h->pg_lock); From d230823a1c4c3e97afd4c934b86b3975d5e20249 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 9 May 2016 09:14:29 +0200 Subject: [PATCH 129/138] scsi_lib: Decode T10 vendor IDs Some arrays / HBAs will only present T10 vendor IDs, so we should be decoding them, too. [mkp: Fixed T10 spelling] Suggested-by: Paul Mackerras Signed-off-by: Hannes Reinecke Tested-by: Paul Mackerras Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b920c5dabf60..b2e332af0f51 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -3064,6 +3064,7 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) * - EUI-64 based 12-byte * - NAA IEEE Registered * - NAA IEEE Extended + * - T10 Vendor ID * as longer descriptors reduce the likelyhood * of identification clashes. */ @@ -3082,6 +3083,21 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) goto next_desig; switch (d[1] & 0xf) { + case 0x1: + /* T10 Vendor ID */ + if (cur_id_size > d[3]) + break; + /* Prefer anything */ + if (cur_id_type > 0x01 && cur_id_type != 0xff) + break; + cur_id_size = d[3]; + if (cur_id_size + 4 > id_len) + cur_id_size = id_len - 4; + cur_id_str = d + 4; + cur_id_type = d[1] & 0xf; + id_size = snprintf(id, id_len, "t10.%*pE", + cur_id_size, cur_id_str); + break; case 0x2: /* EUI-64 */ if (cur_id_size > d[3]) From ff615f065a48137e48985c78d8b17ce14b22fa90 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Mon, 9 May 2016 13:44:10 -0500 Subject: [PATCH 130/138] hpsa: Fix type ZBC conditional checks The device ID obtained from the inquiry can only be of a single type. The original code places a check for TYPE_ZBC right after the check for TYPE_DISK. Logically, if the first if statement sees a device of a TYPE_DISK and moves on to the second statement checking if not TYPE_ZBC, it will always hit the continue. [mkp: Applied by hand] Signed-off-by: Petros Koutoupis Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ff25d2082139..ff8dcd5b0631 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1665,9 +1665,8 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, for (j = 0; j < ndevices; j++) { if (dev[j] == NULL) continue; - if (dev[j]->devtype != TYPE_DISK) - continue; - if (dev[j]->devtype != TYPE_ZBC) + if (dev[j]->devtype != TYPE_DISK && + dev[j]->devtype != TYPE_ZBC) continue; if (is_logical_device(dev[j])) continue; @@ -1712,9 +1711,8 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, for (i = 0; i < ndevices; i++) { if (dev[i] == NULL) continue; - if (dev[i]->devtype != TYPE_DISK) - continue; - if (dev[i]->devtype != TYPE_ZBC) + if (dev[i]->devtype != TYPE_DISK && + dev[i]->devtype != TYPE_ZBC) continue; if (!is_logical_device(dev[i])) continue; From b324f6392eda4124f25017bd4633c167301ad9e3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 May 2016 09:13:41 +0300 Subject: [PATCH 131/138] eata_pio: missing break statement This missing break statement bug predates git. It's a very minor thing, it means that we print a '?' instead of a 'z' in dmesg. Signed-off-by: Dan Carpenter Signed-off-by: Martin K. Petersen --- drivers/scsi/eata_pio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index ca8003f0d8a3..4299fa485622 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -729,6 +729,7 @@ static int register_pio_HBA(long base, struct get_conf *gc, struct pci_dev *pdev break; case 0x24: SD(sh)->EATA_revision = 'z'; + break; default: SD(sh)->EATA_revision = '?'; } From d65c8fff867a6450c58ce31572e883148a445ddf Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Mon, 9 May 2016 21:39:43 -0400 Subject: [PATCH 132/138] Revert "lpfc: Delete unnecessary checks before the function call mempool_destroy" This reverts commit 9be321819c43417432a8376428b90fe3fe3a3510 which caused a regression on hardware using the SLI3 interface. Reported-by: Dick Kennedy Cc: # 4.6+ Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_mem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 4fb3581d4614..3fa65338d3f5 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -231,13 +231,15 @@ lpfc_mem_free(struct lpfc_hba *phba) if (phba->lpfc_hbq_pool) pci_pool_destroy(phba->lpfc_hbq_pool); phba->lpfc_hbq_pool = NULL; - mempool_destroy(phba->rrq_pool); + + if (phba->rrq_pool) + mempool_destroy(phba->rrq_pool); phba->rrq_pool = NULL; /* Free NLP memory pool */ mempool_destroy(phba->nlp_mem_pool); phba->nlp_mem_pool = NULL; - if (phba->sli_rev == LPFC_SLI_REV4) { + if (phba->sli_rev == LPFC_SLI_REV4 && phba->active_rrq_pool) { mempool_destroy(phba->active_rrq_pool); phba->active_rrq_pool = NULL; } From 4fe6bc97efebdc5083aa749850928fad1740a60d Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Fri, 6 May 2016 14:29:26 +0530 Subject: [PATCH 133/138] mpt3sas: Update MPI header to 2.00.42 Updated MPI version and MPI header files. ChangeList: * Added SATADeviceWaitTime to SAS IO Unit Page 4 * Added EEDPObservedValue added to SCSI IO Reply message * Added MPI2_EVENT_ACTIVE_CABLE_EXCEPTION and MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT Signed-off-by: Chaitra P B Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpi/mpi2.h | 7 +++-- drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h | 18 +++++++++---- drivers/scsi/mpt3sas/mpi/mpi2_init.h | 15 ++++++++--- drivers/scsi/mpt3sas/mpi/mpi2_ioc.h | 40 ++++++++++++++++++++++++---- 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h index dfad5b8c1890..a9a659fc2812 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2.h @@ -8,7 +8,7 @@ * scatter/gather formats. * Creation Date: June 21, 2006 * - * mpi2.h Version: 02.00.39 + * mpi2.h Version: 02.00.42 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -100,6 +100,9 @@ * Added MPI2_DIAG_SBR_RELOAD. * 03-19-15 02.00.38 Bumped MPI2_HEADER_VERSION_UNIT. * 05-25-15 02.00.39 Bumped MPI2_HEADER_VERSION_UNIT. + * 08-25-15 02.00.40 Bumped MPI2_HEADER_VERSION_UNIT. + * 12-15-15 02.00.41 Bumped MPI_HEADER_VERSION_UNIT + * 01-01-16 02.00.42 Bumped MPI_HEADER_VERSION_UNIT * -------------------------------------------------------------------------- */ @@ -139,7 +142,7 @@ #define MPI2_VERSION_02_06 (0x0206) /*Unit and Dev versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x27) +#define MPI2_HEADER_VERSION_UNIT (0x2A) #define MPI2_HEADER_VERSION_DEV (0x00) #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h index 9cf09bf7c4a8..95356a82ee99 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h @@ -6,7 +6,7 @@ * Title: MPI Configuration messages and pages * Creation Date: November 10, 2006 * - * mpi2_cnfg.h Version: 02.00.33 + * mpi2_cnfg.h Version: 02.00.35 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -183,9 +183,12 @@ * Added MPI2_BIOSPAGE1_OPTIONS_ADVANCED_CONFIG. * Added AdapterOrderAux fields to BIOS Page 3. * 03-16-15 02.00.31 Updated for MPI v2.6. + * Added Flags field to IO Unit Page 7. * Added new SAS Phy Event codes * 05-25-15 02.00.33 Added more defines for the BiosOptions field of * MPI2_CONFIG_PAGE_BIOS_1. + * 08-25-15 02.00.34 Bumped Header Version. + * 12-18-15 02.00.35 Added SATADeviceWaitTime to SAS IO Unit Page 4. * -------------------------------------------------------------------------- */ @@ -958,13 +961,16 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { U8 Reserved3; /*0x17 */ U32 BoardPowerRequirement; /*0x18 */ U32 PCISlotPowerAllocation; /*0x1C */ - U32 Reserved6; /* 0x20 */ - U32 Reserved7; /* 0x24 */ +/* reserved prior to MPI v2.6 */ + U8 Flags; /* 0x20 */ + U8 Reserved6; /* 0x21 */ + U16 Reserved7; /* 0x22 */ + U32 Reserved8; /* 0x24 */ } MPI2_CONFIG_PAGE_IO_UNIT_7, *PTR_MPI2_CONFIG_PAGE_IO_UNIT_7, Mpi2IOUnitPage7_t, *pMpi2IOUnitPage7_t; -#define MPI2_IOUNITPAGE7_PAGEVERSION (0x04) +#define MPI2_IOUNITPAGE7_PAGEVERSION (0x05) /*defines for IO Unit Page 7 CurrentPowerMode and PreviousPowerMode fields */ #define MPI25_IOUNITPAGE7_PM_INIT_MASK (0xC0) @@ -1045,6 +1051,8 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { #define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01) #define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02) +/* defines for IO Unit Page 7 Flags field */ +#define MPI2_IOUNITPAGE7_FLAG_CABLE_POWER_EXC (0x01) /*IO Unit Page 8 */ @@ -2271,7 +2279,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 { U8 BootDeviceWaitTime; /*0x24 */ U8 - Reserved4; /*0x25 */ + SATADeviceWaitTime; /*0x25 */ U16 Reserved5; /*0x26 */ U8 diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_init.h b/drivers/scsi/mpt3sas/mpi/mpi2_init.h index c38f624b859d..bba56b61d36c 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_init.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_init.h @@ -6,7 +6,7 @@ * Title: MPI SCSI initiator mode messages and structures * Creation Date: June 23, 2006 * - * mpi2_init.h Version: 02.00.17 + * mpi2_init.h Version: 02.00.20 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -51,6 +51,9 @@ * Added MPI26_SCSIIO_IOFLAGS_ESCAPE_PASSTHROUGH. * Added MPI2_SEP_REQ_SLOTSTATUS_DEV_OFF and * MPI2_SEP_REPLY_SLOTSTATUS_DEV_OFF. + * 08-26-15 02.00.18 Added SCSITASKMGMT_MSGFLAGS for Target Reset. + * 12-18-15 02.00.19 Added EEDPObservedValue added to SCSI IO Reply message. + * 01-04-16 02.00.20 Modified EEDP reported values in SCSI IO Reply message. * -------------------------------------------------------------------------- */ @@ -359,8 +362,14 @@ typedef struct _MPI2_SCSI_IO_REPLY { U16 TaskTag; /*0x20 */ U16 SCSIStatusQualifier; /* 0x22 */ U32 BidirectionalTransferCount; /*0x24 */ - U32 EEDPErrorOffset; /*0x28 *//*MPI 2.5 only; Reserved in MPI 2.0*/ - U32 Reserved6; /*0x2C */ + /* MPI 2.5+ only; Reserved in MPI 2.0 */ + U32 EEDPErrorOffset; /* 0x28 */ + /* MPI 2.5+ only; Reserved in MPI 2.0 */ + U16 EEDPObservedAppTag; /* 0x2C */ + /* MPI 2.5+ only; Reserved in MPI 2.0 */ + U16 EEDPObservedGuard; /* 0x2E */ + /* MPI 2.5+ only; Reserved in MPI 2.0 */ + U32 EEDPObservedRefTag; /* 0x30 */ } MPI2_SCSI_IO_REPLY, *PTR_MPI2_SCSI_IO_REPLY, Mpi2SCSIIOReply_t, *pMpi2SCSIIOReply_t; diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h index cf510ed91924..8bae305bc156 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h @@ -6,7 +6,7 @@ * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: October 11, 2006 * - * mpi2_ioc.h Version: 02.00.26 + * mpi2_ioc.h Version: 02.00.27 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -134,9 +134,13 @@ * Added Encrypted Hash Extended Image. * 12-05-13 02.00.24 Added MPI25_HASH_IMAGE_TYPE_BIOS. * 11-18-14 02.00.25 Updated copyright information. - * 03-16-15 02.00.26 Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS and + * 03-16-15 02.00.26 Updated for MPI v2.6. + * Added MPI2_EVENT_ACTIVE_CABLE_EXCEPTION and + * MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT. + * Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS and * MPI26_FW_HEADER_PID_FAMILY_3516_SAS. * Added MPI26_CTRL_OP_SHUTDOWN. + * 08-25-15 02.00.27 Added IC ARCH Class based signature defines * -------------------------------------------------------------------------- */ @@ -168,7 +172,7 @@ typedef struct _MPI2_IOC_INIT_REQUEST { U16 MsgVersion; /*0x0C */ U16 HeaderVersion; /*0x0E */ U32 Reserved5; /*0x10 */ - U16 Reserved6; /*0x14 */ + U16 ConfigurationFlags; /* 0x14 */ U8 HostPageSize; /*0x16 */ U8 HostMSIxVectors; /*0x17 */ U16 Reserved8; /*0x18 */ @@ -516,6 +520,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY { #define MPI2_EVENT_TEMP_THRESHOLD (0x0027) #define MPI2_EVENT_HOST_MESSAGE (0x0028) #define MPI2_EVENT_POWER_PERFORMANCE_CHANGE (0x0029) +#define MPI2_EVENT_ACTIVE_CABLE_EXCEPTION (0x0034) #define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E) #define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F) @@ -580,7 +585,7 @@ typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE { } MPI2_EVENT_DATA_HOST_MESSAGE, *PTR_MPI2_EVENT_DATA_HOST_MESSAGE, Mpi2EventDataHostMessage_t, *pMpi2EventDataHostMessage_t; -/*Power Performance Change Event */ +/*Power Performance Change Event data */ typedef struct _MPI2_EVENT_DATA_POWER_PERF_CHANGE { U8 CurrentPowerMode; /*0x00 */ @@ -605,6 +610,21 @@ typedef struct _MPI2_EVENT_DATA_POWER_PERF_CHANGE { #define MPI2_EVENT_PM_MODE_REDUCED_POWER (0x05) #define MPI2_EVENT_PM_MODE_STANDBY (0x06) +/* Active Cable Exception Event data */ + +typedef struct _MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT { + U32 ActiveCablePowerRequirement; /* 0x00 */ + U8 ReasonCode; /* 0x04 */ + U8 ReceptacleID; /* 0x05 */ + U16 Reserved1; /* 0x06 */ +} MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT, + *PTR_MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT, + Mpi26EventDataActiveCableExcept_t, + *pMpi26EventDataActiveCableExcept_t; + +/* defines for ReasonCode field */ +#define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00) + /*Hard Reset Received Event data */ typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED { @@ -1366,7 +1386,16 @@ typedef struct _MPI2_FW_IMAGE_HEADER { /*Signature0 field */ #define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04) #define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A) -#define MPI26_FW_HEADER_SIGNATURE0 (0x5AEAA55A) +/* Last byte is defined by architecture */ +#define MPI26_FW_HEADER_SIGNATURE0_BASE (0x5AEAA500) +#define MPI26_FW_HEADER_SIGNATURE0_ARC_0 (0x5A) +#define MPI26_FW_HEADER_SIGNATURE0_ARC_1 (0x00) +#define MPI26_FW_HEADER_SIGNATURE0_ARC_2 (0x01) +/* legacy (0x5AEAA55A) */ +#define MPI26_FW_HEADER_SIGNATURE0 \ + (MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_0) +#define MPI26_FW_HEADER_SIGNATURE0_3516 \ + (MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_1) /*Signature1 field */ #define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08) @@ -1778,6 +1807,7 @@ typedef struct _MPI26_IOUNIT_CONTROL_REQUEST { #define MPI26_CTRL_OP_SAS_PHY_LINK_RESET (0x06) #define MPI26_CTRL_OP_SAS_PHY_HARD_RESET (0x07) #define MPI26_CTRL_OP_PHY_CLEAR_ERROR_LOG (0x08) +#define MPI26_CTRL_OP_LINK_CLEAR_ERROR_LOG (0x09) #define MPI26_CTRL_OP_SAS_SEND_PRIMITIVE (0x0A) #define MPI26_CTRL_OP_FORCE_FULL_DISCOVERY (0x0B) #define MPI26_CTRL_OP_REMOVE_DEVICE (0x0D) From a470a51cd6481373cdf2b5934b1b9f7853688de9 Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Fri, 6 May 2016 14:29:27 +0530 Subject: [PATCH 134/138] mpt3sas: Handle active cable exception event In-order to handle this 'MPI2_EVENT_ACTIVE_CABLE_EXCEPTION' event, driver need to follow below steps, 1. Unmask the 'MPI2_EVENT_ACTIVE_CABLE_EXCEPTION' event, so that FW can notify this event to host driver. 2. After receiving this event, add this event to AEN event queue, for notifying this event to applications. 3. Then Print below message in kernel logs if the event data's reason code is zero, "Currently an active cable with ReceptacleID cannot be powered and devices connected to this active cable will not be seen. This active cable requires of power" This event is only for Intruder/Cutlass HBAs. Signed-off-by: Chaitra P B Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 5 +++++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 93d7c28f8162..b7f4e664f5f3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -655,6 +655,9 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc, case MPI2_EVENT_TEMP_THRESHOLD: desc = "Temperature Threshold"; break; + case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: + desc = "Active cable exception"; + break; } if (!desc) @@ -5424,6 +5427,8 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); _base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD); + if (ioc->hba_mpi_version_belonged == MPI26_VERSION) + _base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION); r = _base_make_ioc_operational(ioc, CAN_SLEEP); if (r) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index f2139e5604a3..4f2500b24c59 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -7848,6 +7848,7 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, Mpi2EventNotificationReply_t *mpi_reply; u16 event; u16 sz; + Mpi26EventDataActiveCableExcept_t *ActiveCableEventData; /* events turned off due to host reset or driver unloading */ if (ioc->remove_host || ioc->pci_error_recovery) @@ -7960,6 +7961,18 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, (Mpi2EventDataTemperature_t *) mpi_reply->EventData); break; + case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: + ActiveCableEventData = + (Mpi26EventDataActiveCableExcept_t *) mpi_reply->EventData; + if (ActiveCableEventData->ReasonCode == + MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) + pr_info(MPT3SAS_FMT "Currently an active cable with ReceptacleID %d", + ioc->name, ActiveCableEventData->ReceptacleID); + pr_info("cannot be powered and devices connected to this active cable"); + pr_info("will not be seen. This active cable"); + pr_info("requires %d mW of power", + ActiveCableEventData->ActiveCablePowerRequirement); + break; default: /* ignore the rest */ return 1; From 648512ccd7d42ccf761f515b7c0cb456a48c477a Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Fri, 6 May 2016 14:29:28 +0530 Subject: [PATCH 135/138] mpt3sas: Fix initial Reference tag field for 4K PI drives. Modified driver code to use scsi_prot_ref_tag() API instead of scsi_get_lba(), while initializing reference tag field in the CDB. Signed-off-by: Chaitra P B Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 4f2500b24c59..d256fc0fcc98 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -3959,7 +3959,7 @@ _scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; mpi_request->CDB.EEDP32.PrimaryReferenceTag = - cpu_to_be32(scsi_get_lba(scmd)); + cpu_to_be32(scsi_prot_ref_tag(scmd)); break; case SCSI_PROT_DIF_TYPE3: From b2500d76a0dbaa8993cd6b43941d23d31a312831 Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Fri, 6 May 2016 14:29:29 +0530 Subject: [PATCH 136/138] mpt3sas: Updating mpt3sas driver version to 13.100.00.00 Bump mpt3sas driver version from 12.100.00.00 to 13.100.00.00 Signed-off-by: Chaitra P B Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 6940c577053f..af2099a5d3f7 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -73,8 +73,8 @@ #define MPT3SAS_DRIVER_NAME "mpt3sas" #define MPT3SAS_AUTHOR "Avago Technologies " #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "12.100.00.00" -#define MPT3SAS_MAJOR_VERSION 12 +#define MPT3SAS_DRIVER_VERSION "13.100.00.00" +#define MPT3SAS_MAJOR_VERSION 13 #define MPT3SAS_MINOR_VERSION 100 #define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION 00 From 6c197093847e8cdec844df39a373bfe1f9a1ac8a Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Fri, 6 May 2016 14:29:30 +0530 Subject: [PATCH 137/138] mpt3sas: Set maximum transfer length per IO to 4MB for VDs Set maximum transfer length per IO on RAID volumes to 4MB by setting VD's queue's max_sector to 8192. Signed-off-by: Chaitra P B Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 ++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index af2099a5d3f7..71b1c58fec3b 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -112,6 +112,8 @@ #define MPT3SAS_SAS_QUEUE_DEPTH 254 #define MPT3SAS_RAID_QUEUE_DEPTH 128 +#define MPT3SAS_RAID_MAX_SECTORS 8192 + #define MPT_NAME_LENGTH 32 /* generic length of strings */ #define MPT_STRING_LENGTH 64 diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index d256fc0fcc98..7217218edbac 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -1909,6 +1909,14 @@ scsih_slave_configure(struct scsi_device *sdev) (unsigned long long)raid_device->wwid, raid_device->num_pds, ds); + if (shost->max_sectors > MPT3SAS_RAID_MAX_SECTORS) { + blk_queue_max_hw_sectors(sdev->request_queue, + MPT3SAS_RAID_MAX_SECTORS); + sdev_printk(KERN_INFO, sdev, + "Set queue's max_sector to: %u\n", + MPT3SAS_RAID_MAX_SECTORS); + } + scsih_change_queue_depth(sdev, qdepth); /* raid transport support */ From 5f0dfb7a9bcc8139958f59ecb9bbd7e738ae702d Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Fri, 6 May 2016 14:29:31 +0530 Subject: [PATCH 138/138] mpt3sas: Used "synchronize_irq()"API to synchronize timed-out IO & TMs Replaced mpt3sas_base_flush_reply_queues() with mpt3sas_base_sync_reply_irqs(),as mpt3sas_base_flush_reply_queues() skips over reply queues that are currently busy (i.e. being handled by interrupt processing in another core). If a reply queue is busy, then call to synchronize_irq()in mpt3sas_base_sync_reply_irqs()make sures the other core has finished flushing the queue and completed any calls to the mid-layer scsi_done() routine. Signed-off-by: Chaitra P B Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 15 +++++++-------- drivers/scsi/mpt3sas/mpt3sas_base.h | 3 ++- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 4 +++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index b7f4e664f5f3..751f13edece0 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -1104,18 +1104,16 @@ _base_is_controller_msix_enabled(struct MPT3SAS_ADAPTER *ioc) } /** - * mpt3sas_base_flush_reply_queues - flushing the MSIX reply queues + * mpt3sas_base_sync_reply_irqs - flush pending MSIX interrupts * @ioc: per adapter object - * Context: ISR conext + * Context: non ISR conext * - * Called when a Task Management request has completed. We want - * to flush the other reply queues so all the outstanding IO has been - * completed back to OS before we process the TM completetion. + * Called when a Task Management request has completed. * * Return nothing. */ void -mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc) +mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc) { struct adapter_reply_queue *reply_q; @@ -1126,12 +1124,13 @@ mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc) return; list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - if (ioc->shost_recovery) + if (ioc->shost_recovery || ioc->remove_host || + ioc->pci_error_recovery) return; /* TMs are on msix_index == 0 */ if (reply_q->msix_index == 0) continue; - _base_interrupt(reply_q->vector, (void *)reply_q); + synchronize_irq(reply_q->vector); } } diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 71b1c58fec3b..892c9be008b5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1236,7 +1236,8 @@ void *mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid); void *mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid); __le32 mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc); + +void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc); /* hi-priority queue */ u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 7217218edbac..6a4df5a315e9 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2124,7 +2124,6 @@ _scsih_tm_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) return 1; if (ioc->tm_cmds.smid != smid) return 1; - mpt3sas_base_flush_reply_queues(ioc); ioc->tm_cmds.status |= MPT3_CMD_COMPLETE; mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); if (mpi_reply) { @@ -2309,6 +2308,9 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, } } + /* sync IRQs in case those were busy during flush. */ + mpt3sas_base_sync_reply_irqs(ioc); + if (ioc->tm_cmds.status & MPT3_CMD_REPLY_VALID) { mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT); mpi_reply = ioc->tm_cmds.reply;