···1+AACRAID Driver for Linux (take two)2+3+Introduction4+-------------------------5+The aacraid driver adds support for Adaptec (http://www.adaptec.com)6+RAID controllers. This is a major rewrite from the original7+Adaptec supplied driver. It has signficantly cleaned up both the code8+and the running binary size (the module is less than half the size of9+the original).10+11+Supported Cards/Chipsets12+-------------------------13+ PCI ID (pci.ids) OEM Product14+ 9005:0285:9005:028a Adaptec 2020ZCR (Skyhawk)15+ 9005:0285:9005:028e Adaptec 2020SA (Skyhawk)16+ 9005:0285:9005:028b Adaptec 2025ZCR (Terminator)17+ 9005:0285:9005:028f Adaptec 2025SA (Terminator)18+ 9005:0285:9005:0286 Adaptec 2120S (Crusader)19+ 9005:0286:9005:028d Adaptec 2130S (Lancer)20+ 9005:0285:9005:0285 Adaptec 2200S (Vulcan)21+ 9005:0285:9005:0287 Adaptec 2200S (Vulcan-2m)22+ 9005:0286:9005:028c Adaptec 2230S (Lancer)23+ 9005:0286:9005:028c Adaptec 2230SLP (Lancer)24+ 9005:0285:9005:0296 Adaptec 2240S (SabreExpress)25+ 9005:0285:9005:0290 Adaptec 2410SA (Jaguar)26+ 9005:0285:9005:0293 Adaptec 21610SA (Corsair-16)27+ 9005:0285:103c:3227 Adaptec 2610SA (Bearcat)28+ 9005:0285:9005:0292 Adaptec 2810SA (Corsair-8)29+ 9005:0285:9005:0294 Adaptec Prowler30+ 9005:0286:9005:029d Adaptec 2420SA (Intruder)31+ 9005:0286:9005:029c Adaptec 2620SA (Intruder)32+ 9005:0286:9005:029b Adaptec 2820SA (Intruder)33+ 9005:0286:9005:02a7 Adaptec 2830SA (Skyray)34+ 9005:0286:9005:02a8 Adaptec 2430SA (Skyray)35+ 9005:0285:9005:0288 Adaptec 3230S (Harrier)36+ 9005:0285:9005:0289 Adaptec 3240S (Tornado)37+ 9005:0285:9005:0298 Adaptec 4000SAS (BlackBird)38+ 9005:0285:9005:0297 Adaptec 4005SAS (AvonPark)39+ 9005:0285:9005:0299 Adaptec 4800SAS (Marauder-X)40+ 9005:0285:9005:029a Adaptec 4805SAS (Marauder-E)41+ 9005:0286:9005:02a2 Adaptec 4810SAS (Hurricane)42+ 1011:0046:9005:0364 Adaptec 5400S (Mustang)43+ 1011:0046:9005:0365 Adaptec 5400S (Mustang)44+ 9005:0283:9005:0283 Adaptec Catapult (3210S with arc firmware)45+ 9005:0284:9005:0284 Adaptec Tomcat (3410S with arc firmware)46+ 9005:0287:9005:0800 Adaptec Themisto (Jupiter)47+ 9005:0200:9005:0200 Adaptec Themisto (Jupiter)48+ 9005:0286:9005:0800 Adaptec Callisto (Jupiter)49+ 1011:0046:9005:1364 Dell PERC 2/QC (Quad Channel, Mustang)50+ 1028:0001:1028:0001 Dell PERC 2/Si (Iguana)51+ 1028:0003:1028:0003 Dell PERC 3/Si (SlimFast)52+ 1028:0002:1028:0002 Dell PERC 3/Di (Opal)53+ 1028:0004:1028:0004 Dell PERC 3/DiF (Iguana)54+ 1028:0002:1028:00d1 Dell PERC 3/DiV (Viper)55+ 1028:0002:1028:00d9 Dell PERC 3/DiL (Lexus)56+ 1028:000a:1028:0106 Dell PERC 3/DiJ (Jaguar)57+ 1028:000a:1028:011b Dell PERC 3/DiD (Dagger)58+ 1028:000a:1028:0121 Dell PERC 3/DiB (Boxster)59+ 9005:0285:1028:0287 Dell PERC 320/DC (Vulcan)60+ 9005:0285:1028:0291 Dell CERC 2 (DellCorsair)61+ 1011:0046:103c:10c2 HP NetRAID-4M (Mustang)62+ 9005:0285:17aa:0286 Legend S220 (Crusader)63+ 9005:0285:17aa:0287 Legend S230 (Vulcan)64+ 9005:0285:9005:0290 IBM ServeRAID 7t (Jaguar)65+ 9005:0285:1014:02F2 IBM ServeRAID 8i (AvonPark)66+ 9005:0285:1014:0312 IBM ServeRAID 8i (AvonParkLite)67+ 9005:0286:1014:9580 IBM ServeRAID 8k/8k-l8 (Aurora)68+ 9005:0286:1014:9540 IBM ServeRAID 8k/8k-l4 (AuroraLite)69+ 9005:0286:9005:029f ICP ICP9014R0 (Lancer)70+ 9005:0286:9005:029e ICP ICP9024R0 (Lancer)71+ 9005:0286:9005:02a0 ICP ICP9047MA (Lancer)72+ 9005:0286:9005:02a1 ICP ICP9087MA (Lancer)73+ 9005:0286:9005:02a4 ICP ICP9085LI (Marauder-X)74+ 9005:0286:9005:02a5 ICP ICP5085BR (Marauder-E)75+ 9005:0286:9005:02a3 ICP ICP5085AU (Hurricane)76+ 9005:0286:9005:02a6 ICP ICP9067MA (Intruder-6)77+ 9005:0286:9005:02a9 ICP ICP5087AU (Skyray)78+ 9005:0286:9005:02aa ICP ICP5047AU (Skyray)79+80+People81+-------------------------82+Alan Cox <alan@redhat.com>83+Christoph Hellwig <hch@infradead.org> (updates for new-style PCI probing and SCSI host registration,84+ small cleanups/fixes)85+Matt Domsch <matt_domsch@dell.com> (revision ioctl, adapter messages)86+Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers87+ added new ioctls, changed scsi interface to use new error handler,88+ increased the number of fibs and outstanding commands to a container)89+90+ (fixed 64bit and 64G memory model, changed confusing naming convention91+ where fibs that go to the hardware are consistently called hw_fibs and92+ not just fibs like the name of the driver tracking structure)93+Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.94+95+Original Driver96+-------------------------97+Adaptec Unix OEM Product Group98+99+Mailing List100+-------------------------101+linux-scsi@vger.kernel.org (Interested parties troll here)102+Also note this is very different to Brian's original driver103+so don't expect him to support it.104+Adaptec does support this driver. Contact Adaptec tech support or105+aacraid@adaptec.com106+107+Original by Brian Boerner February 2001108+Rewritten by Alan Cox, November 2001
+1
drivers/message/fusion/Kconfig
···23 tristate "Fusion MPT ScsiHost drivers for FC"24 depends on PCI && SCSI25 select FUSION026 ---help---27 SCSI HOST support for a Fiber Channel host adapters.28
···23 tristate "Fusion MPT ScsiHost drivers for FC"24 depends on PCI && SCSI25 select FUSION26+ select SCSI_FC_ATTRS27 ---help---28 SCSI HOST support for a Fiber Channel host adapters.29
+7-3
drivers/message/fusion/lsi/mpi.h
···6 * Title: MPI Message independent structures and definitions7 * Creation Date: July 27, 20008 *9- * mpi.h Version: 01.05.0810 *11 * Version History12 * ---------------···74 * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and75 * TargetAssistExtended requests.76 * Added EEDP IOCStatus codes.0077 * --------------------------------------------------------------------------78 */79···106/* Note: The major versions of 0xe0 through 0xff are reserved */107108/* versioning for this MPI header set */109-#define MPI_HEADER_VERSION_UNIT (0x0A)110#define MPI_HEADER_VERSION_DEV (0x00)111#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)112#define MPI_HEADER_VERSION_UNIT_SHIFT (8)···713#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)714#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)715#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)00716717/****************************************************************************/718/* Additional FCP target values (obsolete) */···749#define MPI_IOCSTATUS_LAN_CANCELED (0x0087)750751/****************************************************************************/752-/* Serial Attached SCSI values */753/****************************************************************************/754755#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
···6 * Title: MPI Message independent structures and definitions7 * Creation Date: July 27, 20008 *9+ * mpi.h Version: 01.05.1010 *11 * Version History12 * ---------------···74 * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and75 * TargetAssistExtended requests.76 * Added EEDP IOCStatus codes.77+ * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.78+ * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.79 * --------------------------------------------------------------------------80 */81···104/* Note: The major versions of 0xe0 through 0xff are reserved */105106/* versioning for this MPI header set */107+#define MPI_HEADER_VERSION_UNIT (0x0C)108#define MPI_HEADER_VERSION_DEV (0x00)109#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)110#define MPI_HEADER_VERSION_UNIT_SHIFT (8)···711#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)712#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)713#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)714+#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070)715+#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071)716717/****************************************************************************/718/* Additional FCP target values (obsolete) */···745#define MPI_IOCSTATUS_LAN_CANCELED (0x0087)746747/****************************************************************************/748+/* Serial Attached SCSI values */749/****************************************************************************/750751#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
···1+/*2+ * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.3+ *4+ * NAME: fc_log.h5+ * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips6+ * DESCRIPTION: Contains the enumerated list of values that may be returned7+ * in the IOCLogInfo field of a MPI Default Reply Message.8+ *9+ * CREATION DATE: 6/02/200010+ * ID: $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $11+ */12+13+14+/*15+ * MpiIocLogInfo_t enum16+ *17+ * These 32 bit values are used in the IOCLogInfo field of the MPI reply18+ * messages.19+ * The value is 0xabcccccc where20+ * a = The type of log info as per the MPI spec. Since these codes are21+ * all for Fibre Channel this value will always be 2.22+ * b = Specifies a subclass of the firmware where23+ * 0 = FCP Initiator24+ * 1 = FCP Target25+ * 2 = LAN26+ * 3 = MPI Message Layer27+ * 4 = FC Link28+ * 5 = Context Manager29+ * 6 = Invalid Field Offset30+ * 7 = State Change Info31+ * all others are reserved for future use32+ * c = A specific value within the subclass.33+ *34+ * NOTE: Any new values should be added to the end of each subclass so that the35+ * codes remain consistent across firmware releases.36+ */37+typedef enum _MpiIocLogInfoFc38+{39+ MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000,40+ MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */41+ MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */42+ MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */43+ MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */44+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */45+ MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */46+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */47+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */48+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */49+ MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */50+ MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */51+52+ MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000,53+ MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */54+ MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN = 0x21000002, /* not sent because we are not logged in to the remote node */55+ MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */56+ MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */57+ MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA = 0x21000005, /* Data In, Auto Response, missing data frames */58+ MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP = 0x21000006, /* Data Out, No Response, not sent due to a LIP */59+ MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP = 0x21000007, /* Auto-response after a write not sent due to a LIP */60+ MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP = 0x21000008, /* Data In, No Response, not completed due to a LIP */61+ MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA = 0x21000009, /* Data In, No Response, missing data frames */62+ MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP = 0x2100000a, /* Manual Response not sent due to a LIP */63+ MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3 = 0x2100000b, /* not sent because remote node does not support Class 3 */64+ MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID = 0x2100000c, /* not sent because login to remote node not validated */65+ MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND = 0x2100000e, /* cleared from the outbound queue after a logout */66+ MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN = 0x2100000f, /* cleared waiting for data after a logout */67+68+ MPI_IOCLOGINFO_FC_LAN_BASE = 0x22000000,69+ MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING = 0x22000001, /* Transaction Context Sgl Missing */70+ MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE = 0x22000002, /* Transaction Context found before an EOB */71+ MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET = 0x22000003, /* Transaction Context value has reserved bits set */72+ MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG = 0x22000004, /* Invalid SGL Flags */73+74+ MPI_IOCLOGINFO_FC_MSG_BASE = 0x23000000,75+76+ MPI_IOCLOGINFO_FC_LINK_BASE = 0x24000000,77+ MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */78+ MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */79+ MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */80+ MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */81+82+ MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000,83+84+ MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */85+ MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff,86+87+ MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */88+89+} MpiIocLogInfoFc_t;
···1+2+/***************************************************************************3+ * *4+ * Copyright 2003 LSI Logic Corporation. All rights reserved. *5+ * *6+ * This file is confidential and a trade secret of LSI Logic. The *7+ * receipt of or possession of this file does not convey any rights to *8+ * reproduce or disclose its contents or to manufacture, use, or sell *9+ * anything it may describe, in whole, or in part, without the specific *10+ * written consent of LSI Logic Corporation. *11+ * *12+ ***************************************************************************13+ *14+ * Name: iopiIocLogInfo.h15+ * Title: SAS Firmware IOP Interface IOC Log Info Definitions16+ * Programmer: Guy Kendall17+ * Creation Date: September 24, 200318+ *19+ * Version History20+ * ---------------21+ *22+ * Last Updated23+ * -------------24+ * Version %version: 22 %25+ * Date Updated %date_modified: %26+ * Programmer %created_by: nperucca %27+ *28+ * Date Who Description29+ * -------- --- -------------------------------------------------------30+ * 09/24/03 GWK Initial version31+ *32+ *33+ * Description34+ * ------------35+ * This include file contains SAS firmware interface IOC Log Info codes36+ *37+ *-------------------------------------------------------------------------38+ */39+40+#ifndef IOPI_IOCLOGINFO_H_INCLUDED41+#define IOPI_IOCLOGINFO_H_INCLUDED42+43+44+/****************************************************************************/45+/* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */46+/* Format: */47+/* Bits 31-28: MPI_IOCLOGINFO_TYPE_SAS (3) */48+/* Bits 27-24: IOC_LOGINFO_ORIGINATOR: 0=IOP, 1=PL, 2=IR */49+/* Bits 23-16: LOGINFO_CODE */50+/* Bits 15-0: LOGINFO_CODE Specific */51+/****************************************************************************/52+53+/****************************************************************************/54+/* IOC_LOGINFO_ORIGINATOR defines */55+/****************************************************************************/56+#define IOC_LOGINFO_ORIGINATOR_IOP (0x00000000)57+#define IOC_LOGINFO_ORIGINATOR_PL (0x01000000)58+#define IOC_LOGINFO_ORIGINATOR_IR (0x02000000)59+60+/****************************************************************************/61+/* LOGINFO_CODE defines */62+/****************************************************************************/63+#define IOC_LOGINFO_CODE_MASK (0x00FF0000)64+#define IOC_LOGINFO_CODE_SHIFT (16)65+66+/****************************************************************************/67+/* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP */68+/****************************************************************************/69+#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000)70+#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000)71+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000)72+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */73+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */74+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */75+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */76+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */77+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */78+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */79+#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000)80+81+82+/****************************************************************************/83+/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */84+/****************************************************************************/85+#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000)86+#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000)87+#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000)88+#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000)89+#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000)90+#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000)91+#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000)92+#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000)93+#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000)94+#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000)95+#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000)96+#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000)97+#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000)98+#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000)99+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000)100+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */101+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */102+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */103+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */104+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */105+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */106+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */107+#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000)108+#define PL_LOGINFO_CODE_RESET (0x00110000)109+#define PL_LOGINFO_CODE_ABORT (0x00120000)110+#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000)111+#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000)112+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100)113+#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200)114+#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300)115+#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400)116+#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500)117+#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600)118+#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700)119+#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)120+#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)121+#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00)122+#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00)123+#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00)124+#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00)125+#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00)126+#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000)127+128+129+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */130+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200001) /* Error occured on SMP Read */131+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */132+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */133+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */134+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */135+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */136+137+#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */138+#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */139+#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */140+#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */141+#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */142+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */143+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */144+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */145+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/146+147+148+/****************************************************************************/149+/* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR */150+/****************************************************************************/151+#define IR_LOGINFO_CODE_UNUSED1 (0x00010000)152+#define IR_LOGINFO_CODE_UNUSED2 (0x00020000)153+154+/****************************************************************************/155+/* Defines for convienence */156+/****************************************************************************/157+#define IOC_LOGINFO_PREFIX_IOP ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP)158+#define IOC_LOGINFO_PREFIX_PL ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL)159+#define IOC_LOGINFO_PREFIX_IR ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IR)160+161+#endif /* end of file */162+
+20-10
drivers/message/fusion/lsi/mpi_sas.h
···6 * Title: MPI Serial Attached SCSI structures and definitions7 * Creation Date: August 19, 20048 *9- * mpi_sas.h Version: 01.05.0110 *11 * Version History12 * ---------------···14 * Date Version Description15 * -------- -------- ------------------------------------------------------16 * 08-19-04 01.05.01 Original release.00017 * --------------------------------------------------------------------------18 */19···54 * Values for the SAS DeviceInfo field used in SAS Device Status Change Event55 * data and SAS IO Unit Configuration pages.56 */057#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)58#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)59#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)···216 U8 TargetID; /* 0Ch */217 U8 Bus; /* 0Dh */218 U8 PhyNum; /* 0Eh */219- U8 Reserved4; /* 0Fh */220- U32 Reserved5; /* 10h */221 U64 SASAddress; /* 14h */222- U32 Reserved6; /* 1Ch */223} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,224 SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;225226/* values for the Operation field */227-#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)228-#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)229-#define MPI_SAS_OP_PHY_LINK_RESET (0x06)230-#define MPI_SAS_OP_PHY_HARD_RESET (0x07)231-#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)232-#define MPI_SAS_OP_MAP_CURRENT (0x09)000000233234235/* SAS IO Unit Control Reply */
···6 * Title: MPI Serial Attached SCSI structures and definitions7 * Creation Date: August 19, 20048 *9+ * mpi_sas.h Version: 01.05.0210 *11 * Version History12 * ---------------···14 * Date Version Description15 * -------- -------- ------------------------------------------------------16 * 08-19-04 01.05.01 Original release.17+ * 08-30-05 01.05.02 Added DeviceInfo bit for SEP.18+ * Added PrimFlags and Primitive field to SAS IO Unit19+ * Control request, and added a new operation code.20 * --------------------------------------------------------------------------21 */22···51 * Values for the SAS DeviceInfo field used in SAS Device Status Change Event52 * data and SAS IO Unit Configuration pages.53 */54+#define MPI_SAS_DEVICE_INFO_SEP (0x00004000)55#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)56#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)57#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)···212 U8 TargetID; /* 0Ch */213 U8 Bus; /* 0Dh */214 U8 PhyNum; /* 0Eh */215+ U8 PrimFlags; /* 0Fh */216+ U32 Primitive; /* 10h */217 U64 SASAddress; /* 14h */218+ U32 Reserved4; /* 1Ch */219} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,220 SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;221222/* values for the Operation field */223+#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)224+#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)225+#define MPI_SAS_OP_PHY_LINK_RESET (0x06)226+#define MPI_SAS_OP_PHY_HARD_RESET (0x07)227+#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)228+#define MPI_SAS_OP_MAP_CURRENT (0x09)229+#define MPI_SAS_OP_SEND_PRIMITIVE (0x0A)230+231+/* values for the PrimFlags field */232+#define MPI_SAS_PRIMFLAGS_SINGLE (0x08)233+#define MPI_SAS_PRIMFLAGS_TRIPLE (0x02)234+#define MPI_SAS_PRIMFLAGS_REDUNDANT (0x01)235236237/* SAS IO Unit Control Reply */
+37-11
drivers/message/fusion/mptbase.c
···148static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);149static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);150static int GetLanConfigPages(MPT_ADAPTER *ioc);151-static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);152static int GetIoUnitPage2(MPT_ADAPTER *ioc);153int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);154static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);···1231 dprintk((KERN_INFO MYNAM1232 ": Not using 64 bit consistent mask\n"));12331234- ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);1235 if (ioc == NULL) {1236 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");1237 return -ENOMEM;1238 }1239- memset(ioc, 0, sizeof(MPT_ADAPTER));1240 ioc->alloc_total = sizeof(MPT_ADAPTER);1241 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */1242 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;···1243 ioc->pcidev = pdev;1244 ioc->diagPending = 0;1245 spin_lock_init(&ioc->diagLock);001246 spin_lock_init(&ioc->initializing_hba_lock);12471248 /* Initialize the event logging.···1267 /* Initialize the running configQ head.1268 */1269 INIT_LIST_HEAD(&ioc->configQ);000012701271 /* Find lookup slot. */1272 INIT_LIST_HEAD(&ioc->list);···1377 ioc->prod_name = "LSIFC949X";1378 ioc->bus_type = FC;1379 ioc->errata_flag_1064 = 1;00001380 }1381 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {1382 ioc->prod_name = "LSI53C1030";···1630 pci_enable_device(pdev);16311632 /* enable interrupts */1633- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));1634 ioc->active = 1;16351636 /* F/W not running */···1723 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */1724 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",1725 ioc->alt_ioc->name));1726- CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));1727 ioc->alt_ioc->active = 1;1728 }1729···18391840 if (ret == 0) {1841 /* Enable! (reply interrupt) */1842- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));1843 ioc->active = 1;1844 }1845···1847 /* (re)Enable alt-IOC! (reply interrupt) */1848 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",1849 ioc->alt_ioc->name));1850- CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));1851 ioc->alt_ioc->active = 1;1852 }1853···1888 * (FCPortPage0_t stuff)1889 */1890 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {1891- (void) GetFcPortPage0(ioc, ii);1892 }18931894 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&···42074208/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/4209/*4210- * GetFcPortPage0 - Fetch FCPort config Page0.4211 * @ioc: Pointer to MPT_ADAPTER structure4212 * @portnum: IOC Port number4213 *···4217 * -EAGAIN if no msg frames currently available4218 * -EFAULT for non-successful reply or no reply (timeout)4219 */4220-static int4221-GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)4222{4223 ConfigPageHeader_t hdr;4224 CONFIGPARMS cfg;···4228 int data_sz;4229 int copy_sz;4230 int rc;0042314232 /* Get FCPort Page 0 header */4233 hdr.PageVersion = 0;···4253 rc = -ENOMEM;4254 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);4255 if (ppage0_alloc) {004256 memset((u8 *)ppage0_alloc, 0, data_sz);4257 cfg.physAddr = page0_dma;4258 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;···4286 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);4287 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);428800000000000004289 }42904291 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);···6383EXPORT_SYMBOL(mpt_free_fw_memory);6384EXPORT_SYMBOL(mptbase_sas_persist_operation);6385EXPORT_SYMBOL(mpt_alt_ioc_wait);0638663876388/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
···148static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);149static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);150static int GetLanConfigPages(MPT_ADAPTER *ioc);0151static int GetIoUnitPage2(MPT_ADAPTER *ioc);152int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);153static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);···1232 dprintk((KERN_INFO MYNAM1233 ": Not using 64 bit consistent mask\n"));12341235+ ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);1236 if (ioc == NULL) {1237 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");1238 return -ENOMEM;1239 }01240 ioc->alloc_total = sizeof(MPT_ADAPTER);1241 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */1242 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;···1245 ioc->pcidev = pdev;1246 ioc->diagPending = 0;1247 spin_lock_init(&ioc->diagLock);1248+ spin_lock_init(&ioc->fc_rescan_work_lock);1249+ spin_lock_init(&ioc->fc_rport_lock);1250 spin_lock_init(&ioc->initializing_hba_lock);12511252 /* Initialize the event logging.···1267 /* Initialize the running configQ head.1268 */1269 INIT_LIST_HEAD(&ioc->configQ);1270+1271+ /* Initialize the fc rport list head.1272+ */1273+ INIT_LIST_HEAD(&ioc->fc_rports);12741275 /* Find lookup slot. */1276 INIT_LIST_HEAD(&ioc->list);···1373 ioc->prod_name = "LSIFC949X";1374 ioc->bus_type = FC;1375 ioc->errata_flag_1064 = 1;1376+ }1377+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {1378+ ioc->prod_name = "LSIFC949E";1379+ ioc->bus_type = FC;1380 }1381 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {1382 ioc->prod_name = "LSI53C1030";···1622 pci_enable_device(pdev);16231624 /* enable interrupts */1625+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);1626 ioc->active = 1;16271628 /* F/W not running */···1715 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */1716 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",1717 ioc->alt_ioc->name));1718+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);1719 ioc->alt_ioc->active = 1;1720 }1721···18311832 if (ret == 0) {1833 /* Enable! (reply interrupt) */1834+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);1835 ioc->active = 1;1836 }1837···1839 /* (re)Enable alt-IOC! (reply interrupt) */1840 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",1841 ioc->alt_ioc->name));1842+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);1843 ioc->alt_ioc->active = 1;1844 }1845···1880 * (FCPortPage0_t stuff)1881 */1882 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {1883+ (void) mptbase_GetFcPortPage0(ioc, ii);1884 }18851886 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&···41994200/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/4201/*4202+ * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.4203 * @ioc: Pointer to MPT_ADAPTER structure4204 * @portnum: IOC Port number4205 *···4209 * -EAGAIN if no msg frames currently available4210 * -EFAULT for non-successful reply or no reply (timeout)4211 */4212+int4213+mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)4214{4215 ConfigPageHeader_t hdr;4216 CONFIGPARMS cfg;···4220 int data_sz;4221 int copy_sz;4222 int rc;4223+ int count = 400;4224+42254226 /* Get FCPort Page 0 header */4227 hdr.PageVersion = 0;···4243 rc = -ENOMEM;4244 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);4245 if (ppage0_alloc) {4246+4247+ try_again:4248 memset((u8 *)ppage0_alloc, 0, data_sz);4249 cfg.physAddr = page0_dma;4250 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;···4274 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);4275 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);42764277+ /*4278+ * if still doing discovery,4279+ * hang loose a while until finished4280+ */4281+ if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {4282+ if (count-- > 0) {4283+ msleep_interruptible(100);4284+ goto try_again;4285+ }4286+ printk(MYIOC_s_INFO_FMT "Firmware discovery not"4287+ " complete.\n",4288+ ioc->name);4289+ }4290 }42914292 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);···6358EXPORT_SYMBOL(mpt_free_fw_memory);6359EXPORT_SYMBOL(mptbase_sas_persist_operation);6360EXPORT_SYMBOL(mpt_alt_ioc_wait);6361+EXPORT_SYMBOL(mptbase_GetFcPortPage0);636263636364/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+30-4
drivers/message/fusion/mptbase.h
···76#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR77#endif7879-#define MPT_LINUX_VERSION_COMMON "3.03.05"80-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.05"81#define WHAT_MAGIC_STRING "@" "(" "#" ")"8283#define show_mptmod_ver(s,ver) \···413 u8 status; /* current command status */414 u8 reset; /* 1 if bus reset allowed */415 u8 target; /* target for reset */416- struct semaphore sem_ioc;417} MPT_IOCTL;418419#define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */···421#define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */422423typedef struct _MPT_SAS_MGMT {424- struct semaphore mutex;425 struct completion done;426 u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */427 u8 status; /* current command status */···498 IOCPage3_t *pIocPg3; /* table of physical disks */499 int isRaid; /* bit field, 1 if RAID */500}RaidCfgData;0000000000000000501502/*503 * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS···628 struct list_head list;629 struct net_device *netdev;630 struct list_head sas_topology;0631 MPT_SAS_MGMT sas_mgmt;00000000632} MPT_ADAPTER;633634/*···1024extern int mpt_findImVolumes(MPT_ADAPTER *ioc);1025extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);1026extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);01027extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc);10281029/*
···76#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR77#endif7879+#define MPT_LINUX_VERSION_COMMON "3.03.06"80+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06"81#define WHAT_MAGIC_STRING "@" "(" "#" ")"8283#define show_mptmod_ver(s,ver) \···413 u8 status; /* current command status */414 u8 reset; /* 1 if bus reset allowed */415 u8 target; /* target for reset */416+ struct mutex ioctl_mutex;417} MPT_IOCTL;418419#define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */···421#define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */422423typedef struct _MPT_SAS_MGMT {424+ struct mutex mutex;425 struct completion done;426 u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */427 u8 status; /* current command status */···498 IOCPage3_t *pIocPg3; /* table of physical disks */499 int isRaid; /* bit field, 1 if RAID */500}RaidCfgData;501+502+#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */503+#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */504+#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04 /* target mapped in vdev */505+506+/*507+ * data allocated for each fc rport device508+ */509+struct mptfc_rport_info510+{511+ struct list_head list;512+ struct fc_rport *rport;513+ VirtDevice *vdev;514+ FCDevicePage0_t pg0;515+ u8 flags;516+};517518/*519 * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS···612 struct list_head list;613 struct net_device *netdev;614 struct list_head sas_topology;615+ struct mutex sas_topology_mutex;616 MPT_SAS_MGMT sas_mgmt;617+ int num_ports;618+619+ struct list_head fc_rports;620+ spinlock_t fc_rport_lock; /* list and ri flags */621+ spinlock_t fc_rescan_work_lock;622+ int fc_rescan_work_count;623+ struct work_struct fc_rescan_work;624+625} MPT_ADAPTER;626627/*···999extern int mpt_findImVolumes(MPT_ADAPTER *ioc);1000extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);1001extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);1002+extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);1003extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc);10041005/*
···55#include <linux/reboot.h> /* notifier code */56#include <linux/sched.h>57#include <linux/workqueue.h>05859#include <scsi/scsi.h>60#include <scsi/scsi_cmnd.h>61#include <scsi/scsi_device.h>62#include <scsi/scsi_host.h>63#include <scsi/scsi_tcq.h>06465#include "mptbase.h"66#include "mptscsih.h"···81module_param(mpt_pq_filter, int, 0);82MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");830000000084static int mptfcDoneCtx = -1;85static int mptfcTaskCtx = -1;86static int mptfcInternalCtx = -1; /* Used only for internal commands */00000008788static struct scsi_host_template mptfc_driver_template = {89 .module = THIS_MODULE,···106 .proc_info = mptscsih_proc_info,107 .name = "MPT FC Host",108 .info = mptscsih_info,109- .queuecommand = mptscsih_qcmd,110 .target_alloc = mptscsih_target_alloc,111- .slave_alloc = mptscsih_slave_alloc,112 .slave_configure = mptscsih_slave_configure,113 .target_destroy = mptscsih_target_destroy,114 .slave_destroy = mptscsih_slave_destroy,···145 PCI_ANY_ID, PCI_ANY_ID },146 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,147 PCI_ANY_ID, PCI_ANY_ID },00148 {0} /* Terminating entry */149};150MODULE_DEVICE_TABLE(pci, mptfc_pci_table);151152-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/153-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/154-/*155- * mptfc_probe - Installs scsi devices per bus.156- * @pdev: Pointer to pci_dev structure157- *158- * Returns 0 for success, non-zero for failure.159- *000000000000000160 */0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161static int162mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)163{···624 MPT_SCSI_HOST *hd;625 MPT_ADAPTER *ioc;626 unsigned long flags;627- int sz, ii;628 int numSGE = 0;629 int scale;630 int ioc_cap;631- u8 *mem;632 int error=0;633 int r;634-635 if ((r = mpt_attach(pdev,id)) != 0)636 return r;637-638 ioc = pci_get_drvdata(pdev);639 ioc->DoneCtx = mptfcDoneCtx;640 ioc->TaskCtx = mptfcTaskCtx;···669 printk(MYIOC_s_WARN_FMT670 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",671 ioc->name, ioc);672- return 0;673 }674675 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));···681 error = -1;682 goto out_mptfc_probe;683 }00684685 spin_lock_irqsave(&ioc->FreeQlock, flags);686···745 /* SCSI needs scsi_cmnd lookup table!746 * (with size equal to req_depth*PtrSz!)747 */748- sz = ioc->req_depth * sizeof(void *);749- mem = kmalloc(sz, GFP_ATOMIC);750- if (mem == NULL) {751 error = -ENOMEM;752 goto out_mptfc_probe;753 }754755- memset(mem, 0, sz);756- hd->ScsiLookup = (struct scsi_cmnd **) mem;757-758- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",759- ioc->name, hd->ScsiLookup, sz));760761 /* Allocate memory for the device structures.762 * A non-Null pointer at an offset763 * indicates a device exists.764 * max_id = 1 + maximum id (hosts.h)765 */766- sz = sh->max_id * sizeof(void *);767- mem = kmalloc(sz, GFP_ATOMIC);768- if (mem == NULL) {769 error = -ENOMEM;770 goto out_mptfc_probe;771 }772773- memset(mem, 0, sz);774- hd->Targets = (VirtTarget **) mem;775-776- dprintk((KERN_INFO777- " vdev @ %p, sz=%d\n", hd->Targets, sz));778779 /* Clear the TM flags780 */···800 hd->scandv_wait_done = 0;801 hd->last_queue_full = 0;8020803 error = scsi_add_host (sh, &ioc->pcidev->dev);804 if(error) {805 dprintk((KERN_ERR MYNAM···808 goto out_mptfc_probe;809 }810811- scsi_scan_host(sh);0000812 return 0;813814out_mptfc_probe:···825 .name = "mptfc",826 .id_table = mptfc_pci_table,827 .probe = mptfc_probe,828- .remove = __devexit_p(mptscsih_remove),829 .shutdown = mptscsih_shutdown,830#ifdef CONFIG_PM831 .suspend = mptscsih_suspend,···843static int __init844mptfc_init(void)845{0846847 show_mptmod_ver(my_NAME, my_VERSION);0000000000848849 mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);850 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);···871 ": Registered for IOC reset notifications\n"));872 }873874- return pci_register_driver(&mptfc_driver);00000000000000000000000000875}876877/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/···910mptfc_exit(void)911{912 pci_unregister_driver(&mptfc_driver);913-0914 mpt_reset_deregister(mptfcDoneCtx);915 dprintk((KERN_INFO MYNAM916 ": Deregistered for IOC reset notifications\n"));
···55#include <linux/reboot.h> /* notifier code */56#include <linux/sched.h>57#include <linux/workqueue.h>58+#include <linux/sort.h>5960#include <scsi/scsi.h>61#include <scsi/scsi_cmnd.h>62#include <scsi/scsi_device.h>63#include <scsi/scsi_host.h>64#include <scsi/scsi_tcq.h>65+#include <scsi/scsi_transport_fc.h>6667#include "mptbase.h"68#include "mptscsih.h"···79module_param(mpt_pq_filter, int, 0);80MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");8182+#define MPTFC_DEV_LOSS_TMO (60)83+static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */84+module_param(mptfc_dev_loss_tmo, int, 0);85+MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "86+ " transport to wait for an rport to "87+ " return following a device loss event."88+ " Default=60.");89+90static int mptfcDoneCtx = -1;91static int mptfcTaskCtx = -1;92static int mptfcInternalCtx = -1; /* Used only for internal commands */93+94+int mptfc_slave_alloc(struct scsi_device *device);95+static int mptfc_qcmd(struct scsi_cmnd *SCpnt,96+ void (*done)(struct scsi_cmnd *));97+98+static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);99+static void __devexit mptfc_remove(struct pci_dev *pdev);100101static struct scsi_host_template mptfc_driver_template = {102 .module = THIS_MODULE,···89 .proc_info = mptscsih_proc_info,90 .name = "MPT FC Host",91 .info = mptscsih_info,92+ .queuecommand = mptfc_qcmd,93 .target_alloc = mptscsih_target_alloc,94+ .slave_alloc = mptfc_slave_alloc,95 .slave_configure = mptscsih_slave_configure,96 .target_destroy = mptscsih_target_destroy,97 .slave_destroy = mptscsih_slave_destroy,···128 PCI_ANY_ID, PCI_ANY_ID },129 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,130 PCI_ANY_ID, PCI_ANY_ID },131+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,132+ PCI_ANY_ID, PCI_ANY_ID },133 {0} /* Terminating entry */134};135MODULE_DEVICE_TABLE(pci, mptfc_pci_table);136137+static struct scsi_transport_template *mptfc_transport_template = NULL;138+139+struct fc_function_template mptfc_transport_functions = {140+ .dd_fcrport_size = 8,141+ .show_host_node_name = 1,142+ .show_host_port_name = 1,143+ .show_host_supported_classes = 1,144+ .show_host_port_id = 1,145+ .show_rport_supported_classes = 1,146+ .show_starget_node_name = 1,147+ .show_starget_port_name = 1,148+ .show_starget_port_id = 1,149+ .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,150+ .show_rport_dev_loss_tmo = 1,151+152+};153+154+/* FIXME! values controlling firmware RESCAN event155+ * need to be set low to allow dev_loss_tmo to156+ * work as expected. Currently, firmware doesn't157+ * notify driver of RESCAN event until some number158+ * of seconds elapse. This value can be set via159+ * lsiutil.160 */161+static void162+mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)163+{164+ if (timeout > 0)165+ rport->dev_loss_tmo = timeout;166+ else167+ rport->dev_loss_tmo = mptfc_dev_loss_tmo;168+}169+170+static int171+mptfc_FcDevPage0_cmp_func(const void *a, const void *b)172+{173+ FCDevicePage0_t **aa = (FCDevicePage0_t **)a;174+ FCDevicePage0_t **bb = (FCDevicePage0_t **)b;175+176+ if ((*aa)->CurrentBus == (*bb)->CurrentBus) {177+ if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)178+ return 0;179+ if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)180+ return -1;181+ return 1;182+ }183+ if ((*aa)->CurrentBus < (*bb)->CurrentBus)184+ return -1;185+ return 1;186+}187+188+static int189+mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,190+ void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))191+{192+ ConfigPageHeader_t hdr;193+ CONFIGPARMS cfg;194+ FCDevicePage0_t *ppage0_alloc, *fc;195+ dma_addr_t page0_dma;196+ int data_sz;197+ int ii;198+199+ FCDevicePage0_t *p0_array=NULL, *p_p0;200+ FCDevicePage0_t **pp0_array=NULL, **p_pp0;201+202+ int rc = -ENOMEM;203+ U32 port_id = 0xffffff;204+ int num_targ = 0;205+ int max_bus = ioc->facts.MaxBuses;206+ int max_targ = ioc->facts.MaxDevices;207+208+ if (max_bus == 0 || max_targ == 0)209+ goto out;210+211+ data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;212+ p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);213+ if (!p0_array)214+ goto out;215+216+ data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;217+ p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);218+ if (!pp0_array)219+ goto out;220+221+ do {222+ /* Get FC Device Page 0 header */223+ hdr.PageVersion = 0;224+ hdr.PageLength = 0;225+ hdr.PageNumber = 0;226+ hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;227+ cfg.cfghdr.hdr = &hdr;228+ cfg.physAddr = -1;229+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;230+ cfg.dir = 0;231+ cfg.pageAddr = port_id;232+ cfg.timeout = 0;233+234+ if ((rc = mpt_config(ioc, &cfg)) != 0)235+ break;236+237+ if (hdr.PageLength <= 0)238+ break;239+240+ data_sz = hdr.PageLength * 4;241+ ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,242+ &page0_dma);243+ rc = -ENOMEM;244+ if (!ppage0_alloc)245+ break;246+247+ cfg.physAddr = page0_dma;248+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;249+250+ if ((rc = mpt_config(ioc, &cfg)) == 0) {251+ ppage0_alloc->PortIdentifier =252+ le32_to_cpu(ppage0_alloc->PortIdentifier);253+254+ ppage0_alloc->WWNN.Low =255+ le32_to_cpu(ppage0_alloc->WWNN.Low);256+257+ ppage0_alloc->WWNN.High =258+ le32_to_cpu(ppage0_alloc->WWNN.High);259+260+ ppage0_alloc->WWPN.Low =261+ le32_to_cpu(ppage0_alloc->WWPN.Low);262+263+ ppage0_alloc->WWPN.High =264+ le32_to_cpu(ppage0_alloc->WWPN.High);265+266+ ppage0_alloc->BBCredit =267+ le16_to_cpu(ppage0_alloc->BBCredit);268+269+ ppage0_alloc->MaxRxFrameSize =270+ le16_to_cpu(ppage0_alloc->MaxRxFrameSize);271+272+ port_id = ppage0_alloc->PortIdentifier;273+ num_targ++;274+ *p_p0 = *ppage0_alloc; /* save data */275+ *p_pp0++ = p_p0++; /* save addr */276+ }277+ pci_free_consistent(ioc->pcidev, data_sz,278+ (u8 *) ppage0_alloc, page0_dma);279+ if (rc != 0)280+ break;281+282+ } while (port_id <= 0xff0000);283+284+ if (num_targ) {285+ /* sort array */286+ if (num_targ > 1)287+ sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),288+ mptfc_FcDevPage0_cmp_func, NULL);289+ /* call caller's func for each targ */290+ for (ii = 0; ii < num_targ; ii++) {291+ fc = *(pp0_array+ii);292+ func(ioc, ioc_port, fc);293+ }294+ }295+296+ out:297+ if (pp0_array)298+ kfree(pp0_array);299+ if (p0_array)300+ kfree(p0_array);301+ return rc;302+}303+304+static int305+mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)306+{307+ /* not currently usable */308+ if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |309+ MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))310+ return -1;311+312+ if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))313+ return -1;314+315+ if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))316+ return -1;317+318+ /*319+ * board data structure already normalized to platform endianness320+ * shifted to avoid unaligned access on 64 bit architecture321+ */322+ rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;323+ rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;324+ rid->port_id = pg0->PortIdentifier;325+ rid->roles = FC_RPORT_ROLE_UNKNOWN;326+ rid->roles |= FC_RPORT_ROLE_FCP_TARGET;327+ if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)328+ rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;329+330+ return 0;331+}332+333+static void334+mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)335+{336+ struct fc_rport_identifiers rport_ids;337+ struct fc_rport *rport;338+ struct mptfc_rport_info *ri;339+ int match = 0;340+ u64 port_name;341+ unsigned long flags;342+343+ if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)344+ return;345+346+ /* scan list looking for a match */347+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);348+ list_for_each_entry(ri, &ioc->fc_rports, list) {349+ port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;350+ if (port_name == rport_ids.port_name) { /* match */351+ list_move_tail(&ri->list, &ioc->fc_rports);352+ match = 1;353+ break;354+ }355+ }356+ if (!match) { /* allocate one */357+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);358+ ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);359+ if (!ri)360+ return;361+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);362+ list_add_tail(&ri->list, &ioc->fc_rports);363+ }364+365+ ri->pg0 = *pg0; /* add/update pg0 data */366+ ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;367+368+ if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {369+ ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;370+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);371+ rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);372+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);373+ if (rport) {374+ if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {375+ ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;376+ ri->vdev = NULL;377+ ri->rport = rport;378+ *((struct mptfc_rport_info **)rport->dd_data) = ri;379+ }380+ rport->dev_loss_tmo = mptfc_dev_loss_tmo;381+ /*382+ * if already mapped, remap here. If not mapped,383+ * slave_alloc will allocate vdev and map384+ */385+ if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {386+ ri->vdev->target_id = ri->pg0.CurrentTargetID;387+ ri->vdev->bus_id = ri->pg0.CurrentBus;388+ ri->vdev->vtarget->target_id = ri->vdev->target_id;389+ ri->vdev->vtarget->bus_id = ri->vdev->bus_id;390+ }391+ #ifdef MPT_DEBUG392+ printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "393+ "rport tid %d, tmo %d\n",394+ ioc->sh->host_no,395+ pg0->PortIdentifier,396+ pg0->WWNN,397+ pg0->WWPN,398+ pg0->CurrentTargetID,399+ ri->rport->scsi_target_id,400+ ri->rport->dev_loss_tmo);401+ #endif402+ } else {403+ list_del(&ri->list);404+ kfree(ri);405+ ri = NULL;406+ }407+ }408+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);409+410+}411+412+/*413+ * OS entry point to allow host driver to alloc memory414+ * for each scsi device. Called once per device the bus scan.415+ * Return non-zero if allocation fails.416+ * Init memory once per LUN.417+ */418+int419+mptfc_slave_alloc(struct scsi_device *sdev)420+{421+ MPT_SCSI_HOST *hd;422+ VirtTarget *vtarget;423+ VirtDevice *vdev;424+ struct scsi_target *starget;425+ struct fc_rport *rport;426+ struct mptfc_rport_info *ri;427+ unsigned long flags;428+429+430+ rport = starget_to_rport(scsi_target(sdev));431+432+ if (!rport || fc_remote_port_chkready(rport))433+ return -ENXIO;434+435+ hd = (MPT_SCSI_HOST *)sdev->host->hostdata;436+437+ vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);438+ if (!vdev) {439+ printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",440+ hd->ioc->name, sizeof(VirtDevice));441+ return -ENOMEM;442+ }443+ memset(vdev, 0, sizeof(VirtDevice));444+445+ spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);446+447+ if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {448+ spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);449+ kfree(vdev);450+ return -ENODEV;451+ }452+453+ sdev->hostdata = vdev;454+ starget = scsi_target(sdev);455+ vtarget = starget->hostdata;456+ if (vtarget->num_luns == 0) {457+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |458+ MPT_TARGET_FLAGS_VALID_INQUIRY;459+ hd->Targets[sdev->id] = vtarget;460+ }461+462+ vtarget->target_id = vdev->target_id;463+ vtarget->bus_id = vdev->bus_id;464+465+ vdev->vtarget = vtarget;466+ vdev->ioc_id = hd->ioc->id;467+ vdev->lun = sdev->lun;468+ vdev->target_id = ri->pg0.CurrentTargetID;469+ vdev->bus_id = ri->pg0.CurrentBus;470+471+ ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;472+ ri->vdev = vdev;473+474+ spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);475+476+ vtarget->num_luns++;477+478+#ifdef MPT_DEBUG479+ printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "480+ "CurrentTargetID %d, %x %llx %llx\n",481+ sdev->host->host_no,482+ vtarget->num_luns,483+ sdev->id, ri->pg0.CurrentTargetID,484+ ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);485+#endif486+487+ return 0;488+}489+490+static int491+mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))492+{493+ struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));494+ int err;495+496+ err = fc_remote_port_chkready(rport);497+ if (unlikely(err)) {498+ SCpnt->result = err;499+ done(SCpnt);500+ return 0;501+ }502+ return mptscsih_qcmd(SCpnt,done);503+}504+505+static void506+mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)507+{508+ unsigned class = 0, cos = 0;509+510+ /* don't know what to do as only one scsi (fc) host was allocated */511+ if (portnum != 0)512+ return;513+514+ class = ioc->fc_port_page0[portnum].SupportedServiceClass;515+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)516+ cos |= FC_COS_CLASS1;517+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)518+ cos |= FC_COS_CLASS2;519+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)520+ cos |= FC_COS_CLASS3;521+522+ fc_host_node_name(ioc->sh) =523+ (u64)ioc->fc_port_page0[portnum].WWNN.High << 32524+ | (u64)ioc->fc_port_page0[portnum].WWNN.Low;525+526+ fc_host_port_name(ioc->sh) =527+ (u64)ioc->fc_port_page0[portnum].WWPN.High << 32528+ | (u64)ioc->fc_port_page0[portnum].WWPN.Low;529+530+ fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;531+532+ fc_host_supported_classes(ioc->sh) = cos;533+534+ fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;535+}536+537+static void538+mptfc_rescan_devices(void *arg)539+{540+ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;541+ int ii;542+ int work_to_do;543+ unsigned long flags;544+ struct mptfc_rport_info *ri;545+546+ do {547+ /* start by tagging all ports as missing */548+ spin_lock_irqsave(&ioc->fc_rport_lock,flags);549+ list_for_each_entry(ri, &ioc->fc_rports, list) {550+ if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {551+ ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;552+ }553+ }554+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);555+556+ /*557+ * now rescan devices known to adapter,558+ * will reregister existing rports559+ */560+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {561+ (void) mptbase_GetFcPortPage0(ioc, ii);562+ mptfc_init_host_attr(ioc,ii); /* refresh */563+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);564+ }565+566+ /* delete devices still missing */567+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);568+ list_for_each_entry(ri, &ioc->fc_rports, list) {569+ /* if newly missing, delete it */570+ if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |571+ MPT_RPORT_INFO_FLAGS_MISSING))572+ == (MPT_RPORT_INFO_FLAGS_REGISTERED |573+ MPT_RPORT_INFO_FLAGS_MISSING)) {574+575+ ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|576+ MPT_RPORT_INFO_FLAGS_MISSING);577+ fc_remote_port_delete(ri->rport);578+ /*579+ * remote port not really deleted 'cause580+ * binding is by WWPN and driver only581+ * registers FCP_TARGETs582+ */583+ #ifdef MPT_DEBUG584+ printk ("mptfc_rescan.%d: %llx deleted\n",585+ ioc->sh->host_no, ri->pg0.WWPN);586+ #endif587+ }588+ }589+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);590+591+ /*592+ * allow multiple passes as target state593+ * might have changed during scan594+ */595+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);596+ if (ioc->fc_rescan_work_count > 2) /* only need one more */597+ ioc->fc_rescan_work_count = 2;598+ work_to_do = --ioc->fc_rescan_work_count;599+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);600+ } while (work_to_do);601+}602+603static int604mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)605{···148 MPT_SCSI_HOST *hd;149 MPT_ADAPTER *ioc;150 unsigned long flags;151+ int ii;152 int numSGE = 0;153 int scale;154 int ioc_cap;0155 int error=0;156 int r;157+158 if ((r = mpt_attach(pdev,id)) != 0)159 return r;160+161 ioc = pci_get_drvdata(pdev);162 ioc->DoneCtx = mptfcDoneCtx;163 ioc->TaskCtx = mptfcTaskCtx;···194 printk(MYIOC_s_WARN_FMT195 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",196 ioc->name, ioc);197+ return -ENODEV;198 }199200 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));···206 error = -1;207 goto out_mptfc_probe;208 }209+210+ INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);211212 spin_lock_irqsave(&ioc->FreeQlock, flags);213···268 /* SCSI needs scsi_cmnd lookup table!269 * (with size equal to req_depth*PtrSz!)270 */271+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);272+ if (!hd->ScsiLookup) {0273 error = -ENOMEM;274 goto out_mptfc_probe;275 }276277+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",278+ ioc->name, hd->ScsiLookup));000279280 /* Allocate memory for the device structures.281 * A non-Null pointer at an offset282 * indicates a device exists.283 * max_id = 1 + maximum id (hosts.h)284 */285+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);286+ if (!hd->Targets) {0287 error = -ENOMEM;288 goto out_mptfc_probe;289 }290291+ dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));0000292293 /* Clear the TM flags294 */···332 hd->scandv_wait_done = 0;333 hd->last_queue_full = 0;334335+ sh->transportt = mptfc_transport_template;336 error = scsi_add_host (sh, &ioc->pcidev->dev);337 if(error) {338 dprintk((KERN_ERR MYNAM···339 goto out_mptfc_probe;340 }341342+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {343+ mptfc_init_host_attr(ioc,ii);344+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);345+ }346+347 return 0;348349out_mptfc_probe:···352 .name = "mptfc",353 .id_table = mptfc_pci_table,354 .probe = mptfc_probe,355+ .remove = __devexit_p(mptfc_remove),356 .shutdown = mptscsih_shutdown,357#ifdef CONFIG_PM358 .suspend = mptscsih_suspend,···370static int __init371mptfc_init(void)372{373+ int error;374375 show_mptmod_ver(my_NAME, my_VERSION);376+377+ /* sanity check module parameter */378+ if (mptfc_dev_loss_tmo == 0)379+ mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;380+381+ mptfc_transport_template =382+ fc_attach_transport(&mptfc_transport_functions);383+384+ if (!mptfc_transport_template)385+ return -ENODEV;386387 mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);388 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);···387 ": Registered for IOC reset notifications\n"));388 }389390+ error = pci_register_driver(&mptfc_driver);391+ if (error) {392+ fc_release_transport(mptfc_transport_template);393+ }394+395+ return error;396+}397+398+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/399+/**400+ * mptfc_remove - Removed fc infrastructure for devices401+ * @pdev: Pointer to pci_dev structure402+ *403+ */404+static void __devexit mptfc_remove(struct pci_dev *pdev)405+{406+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);407+ struct mptfc_rport_info *p, *n;408+409+ fc_remove_host(ioc->sh);410+411+ list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {412+ list_del(&p->list);413+ kfree(p);414+ }415+416+ mptscsih_remove(pdev);417}418419/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/···400mptfc_exit(void)401{402 pci_unregister_driver(&mptfc_driver);403+ fc_release_transport(mptfc_transport_template);404+405 mpt_reset_deregister(mptfcDoneCtx);406 dprintk((KERN_INFO MYNAM407 ": Deregistered for IOC reset notifications\n"));
+5-9
drivers/message/fusion/mptlan.c
···411 goto out;412 priv->mpt_txfidx_tail = -1;413414- priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl),415 GFP_KERNEL);416 if (priv->SendCtl == NULL)417 goto out_mpt_txfidx;418- for (i = 0; i < priv->tx_max_out; i++) {419- memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl));420 priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i;421- }422423 dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));424···426 goto out_SendCtl;427 priv->mpt_rxfidx_tail = -1;428429- priv->RcvCtl = kmalloc(priv->max_buckets_out *430- sizeof(struct BufferControl),431 GFP_KERNEL);432 if (priv->RcvCtl == NULL)433 goto out_mpt_rxfidx;434- for (i = 0; i < priv->max_buckets_out; i++) {435- memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl));436 priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;437- }438439/**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - "));440/**/ for (i = 0; i < priv->tx_max_out; i++)
···411 goto out;412 priv->mpt_txfidx_tail = -1;413414+ priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl),415 GFP_KERNEL);416 if (priv->SendCtl == NULL)417 goto out_mpt_txfidx;418+ for (i = 0; i < priv->tx_max_out; i++)0419 priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i;0420421 dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));422···428 goto out_SendCtl;429 priv->mpt_rxfidx_tail = -1;430431+ priv->RcvCtl = kcalloc(priv->max_buckets_out,432+ sizeof(struct BufferControl),433 GFP_KERNEL);434 if (priv->RcvCtl == NULL)435 goto out_mpt_rxfidx;436+ for (i = 0; i < priv->max_buckets_out; i++)0437 priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;0438439/**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - "));440/**/ for (i = 0; i < priv->tx_max_out; i++)
+346-58
drivers/message/fusion/mptsas.c
···5 *6 * Copyright (c) 1999-2005 LSI Logic Corporation7 * (mailto:mpt_linux_developer@lsil.com)8- * Copyright (c) 2005 Dell9 */10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/11/*···86static int mptsasMgmtCtx = -1;878800000000000000000089/*90 * SAS topology structures91 *···117 u8 phy_id; /* phy number of parent device */118 u8 port_id; /* sas physical port this device119 is assoc'd with */120- u8 target; /* logical target id of this device */121- u8 bus; /* logical bus number of this device */122 u64 sas_address; /* WWN of this device,123 SATA is assigned by HBA,expander */124 u32 device_info; /* bitfield detailed info about this device */···132 u8 programmed_link_rate; /* programmed max/min phy link rate */133 struct mptsas_devinfo identify; /* point to phy device info */134 struct mptsas_devinfo attached; /* point to attached device info */0135 struct sas_rphy *rphy;136};137···258 struct scsi_target *starget;259 int i;260261- vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);262 if (!vdev) {263 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",264 hd->ioc->name, sizeof(VirtDevice));265 return -ENOMEM;266 }267- memset(vdev, 0, sizeof(VirtDevice));268 vdev->ioc_id = hd->ioc->id;269 sdev->hostdata = vdev;270 starget = scsi_target(sdev);···274 hd->Targets[sdev->id] = vtarget;275 }2760000000000277 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);0278 list_for_each_entry(p, &hd->ioc->sas_topology, list) {279 for (i = 0; i < p->num_phys; i++) {280 if (p->phy_info[i].attached.sas_address ==281 rphy->identify.sas_address) {282 vdev->target_id =283- p->phy_info[i].attached.target;284- vdev->bus_id = p->phy_info[i].attached.bus;285 vdev->lun = sdev->lun;0286 goto out;287 }288 }289 }0290291 printk("No matching SAS device found!!\n");292 kfree(vdev);···313 return 0;314}315000000000000000000000000000000000000316static struct scsi_host_template mptsas_driver_template = {317 .module = THIS_MODULE,318 .proc_name = "mptsas",···360 .slave_alloc = mptsas_slave_alloc,361 .slave_configure = mptscsih_slave_configure,362 .target_destroy = mptscsih_target_destroy,363- .slave_destroy = mptscsih_slave_destroy,364 .change_queue_depth = mptscsih_change_queue_depth,365 .eh_abort_handler = mptscsih_abort,366 .eh_device_reset_handler = mptscsih_dev_reset,···466 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)467 return -ENXIO;468469- if (down_interruptible(&ioc->sas_mgmt.mutex))470 goto out;471472 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);···517 error = 0;518519 out_unlock:520- up(&ioc->sas_mgmt.mutex);521 out:522 return error;523}···716 device_info->handle = le16_to_cpu(buffer->DevHandle);717 device_info->phy_id = buffer->PhyNum;718 device_info->port_id = buffer->PhysicalPort;719- device_info->target = buffer->TargetID;720- device_info->bus = buffer->Bus;721 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));722 device_info->sas_address = le64_to_cpu(sas_address);723 device_info->device_info =···925static int mptsas_probe_one_phy(struct device *dev,926 struct mptsas_phyinfo *phy_info, int index, int local)927{928- struct sas_phy *port;929 int error;930931- port = sas_phy_alloc(dev, index);932- if (!port)933 return -ENOMEM;934935- port->port_identifier = phy_info->port_id;936- mptsas_parse_device_info(&port->identify, &phy_info->identify);937938 /*939 * Set Negotiated link rate.940 */941 switch (phy_info->negotiated_link_rate) {942 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:943- port->negotiated_linkrate = SAS_PHY_DISABLED;944 break;945 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:946- port->negotiated_linkrate = SAS_LINK_RATE_FAILED;947 break;948 case MPI_SAS_IOUNIT0_RATE_1_5:949- port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;950 break;951 case MPI_SAS_IOUNIT0_RATE_3_0:952- port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;953 break;954 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:955 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:956 default:957- port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;958 break;959 }960···963 */964 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {965 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:966- port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;967 break;968 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:969- port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;970 break;971 default:972 break;···978 switch (phy_info->programmed_link_rate &979 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {980 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:981- port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;982 break;983 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:984- port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;985 break;986 default:987 break;···992 */993 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {994 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:995- port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;996 break;997 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:998- port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;999 break;1000 default:1001 break;···1007 switch (phy_info->programmed_link_rate &1008 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {1009 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:1010- port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;1011 break;1012 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:1013- port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;1014 break;1015 default:1016 break;1017 }10181019 if (local)1020- port->local_attached = 1;10211022- error = sas_phy_add(port);1023 if (error) {1024- sas_phy_free(port);1025 return error;1026 }010271028 if (phy_info->attached.handle) {1029 struct sas_rphy *rphy;10301031- rphy = sas_rphy_alloc(port);1032 if (!rphy)1033 return 0; /* non-fatal: an rphy can be added later */1034···1053 u32 handle = 0xFFFF;1054 int error = -ENOMEM, i;10551056- port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);1057 if (!port_info)1058 goto out;1059- memset(port_info, 0, sizeof(*port_info));10601061 error = mptsas_sas_io_unit_pg0(ioc, port_info);1062 if (error)1063 goto out_free_port_info;1064001065 list_add_tail(&port_info->list, &ioc->sas_topology);001066 for (i = 0; i < port_info->num_phys; i++) {1067 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],1068 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<···1105 struct mptsas_portinfo *port_info, *p;1106 int error = -ENOMEM, i, j;11071108- port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);1109 if (!port_info)1110 goto out;1111- memset(port_info, 0, sizeof(*port_info));11121113 error = mptsas_sas_expander_pg0(ioc, port_info,1114 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<···11171118 *handle = port_info->handle;111901120 list_add_tail(&port_info->list, &ioc->sas_topology);001121 for (i = 0; i < port_info->num_phys; i++) {1122 struct device *parent;1123···1152 * HBA phys.1153 */1154 parent = &ioc->sh->shost_gendev;01155 list_for_each_entry(p, &ioc->sas_topology, list) {1156 for (j = 0; j < p->num_phys; j++) {1157 if (port_info->phy_info[i].identify.handle ==···1160 parent = &p->phy_info[j].rphy->dev;1161 }1162 }011631164 mptsas_probe_one_phy(parent, &port_info->phy_info[i],1165 *index, 0);···1186 ;1187}118800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001189static int1190mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)1191{···1398 MPT_SCSI_HOST *hd;1399 MPT_ADAPTER *ioc;1400 unsigned long flags;1401- int sz, ii;1402 int numSGE = 0;1403 int scale;1404 int ioc_cap;1405- u8 *mem;1406 int error=0;1407 int r;1408···1482 sh->unique_id = ioc->id;14831484 INIT_LIST_HEAD(&ioc->sas_topology);1485- init_MUTEX(&ioc->sas_mgmt.mutex);001486 init_completion(&ioc->sas_mgmt.done);14871488 /* Verify that we won't exceed the maximum···1525 /* SCSI needs scsi_cmnd lookup table!1526 * (with size equal to req_depth*PtrSz!)1527 */1528- sz = ioc->req_depth * sizeof(void *);1529- mem = kmalloc(sz, GFP_ATOMIC);1530- if (mem == NULL) {1531 error = -ENOMEM;1532 goto out_mptsas_probe;1533 }15341535- memset(mem, 0, sz);1536- hd->ScsiLookup = (struct scsi_cmnd **) mem;1537-1538- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",1539- ioc->name, hd->ScsiLookup, sz));15401541 /* Allocate memory for the device structures.1542 * A non-Null pointer at an offset1543 * indicates a device exists.1544 * max_id = 1 + maximum id (hosts.h)1545 */1546- sz = sh->max_id * sizeof(void *);1547- mem = kmalloc(sz, GFP_ATOMIC);1548- if (mem == NULL) {1549 error = -ENOMEM;1550 goto out_mptsas_probe;1551 }15521553- memset(mem, 0, sz);1554- hd->Targets = (VirtTarget **) mem;1555-1556- dprintk((KERN_INFO1557- " vtarget @ %p, sz=%d\n", hd->Targets, sz));15581559 /* Clear the TM flags1560 */···15961597 mptsas_scan_sas_topology(ioc);1598000000000000001599 return 0;16001601out_mptsas_probe:···16251626 sas_remove_host(ioc->sh);162701628 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {1629 list_del(&p->list);1630 kfree(p);1631 }016321633 mptscsih_remove(pdev);1634}···1681 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);1682 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);16831684- if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {1685 devtprintk((KERN_INFO MYNAM1686 ": Registered for IOC event notifications\n"));1687 }
···5 *6 * Copyright (c) 1999-2005 LSI Logic Corporation7 * (mailto:mpt_linux_developer@lsil.com)8+ * Copyright (c) 2005-2006 Dell9 */10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/11/*···86static int mptsasMgmtCtx = -1;878889+enum mptsas_hotplug_action {90+ MPTSAS_ADD_DEVICE,91+ MPTSAS_DEL_DEVICE,92+};93+94+struct mptsas_hotplug_event {95+ struct work_struct work;96+ MPT_ADAPTER *ioc;97+ enum mptsas_hotplug_action event_type;98+ u64 sas_address;99+ u32 channel;100+ u32 id;101+ u32 device_info;102+ u16 handle;103+ u16 parent_handle;104+ u8 phy_id;105+};106+107/*108 * SAS topology structures109 *···99 u8 phy_id; /* phy number of parent device */100 u8 port_id; /* sas physical port this device101 is assoc'd with */102+ u8 id; /* logical target id of this device */103+ u8 channel; /* logical bus number of this device */104 u64 sas_address; /* WWN of this device,105 SATA is assigned by HBA,expander */106 u32 device_info; /* bitfield detailed info about this device */···114 u8 programmed_link_rate; /* programmed max/min phy link rate */115 struct mptsas_devinfo identify; /* point to phy device info */116 struct mptsas_devinfo attached; /* point to attached device info */117+ struct sas_phy *phy;118 struct sas_rphy *rphy;119};120···239 struct scsi_target *starget;240 int i;241242+ vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);243 if (!vdev) {244 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",245 hd->ioc->name, sizeof(VirtDevice));246 return -ENOMEM;247 }0248 vdev->ioc_id = hd->ioc->id;249 sdev->hostdata = vdev;250 starget = scsi_target(sdev);···256 hd->Targets[sdev->id] = vtarget;257 }258259+ /*260+ RAID volumes placed beyond the last expected port.261+ */262+ if (sdev->channel == hd->ioc->num_ports) {263+ vdev->target_id = sdev->id;264+ vdev->bus_id = 0;265+ vdev->lun = 0;266+ goto out;267+ }268+269 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);270+ mutex_lock(&hd->ioc->sas_topology_mutex);271 list_for_each_entry(p, &hd->ioc->sas_topology, list) {272 for (i = 0; i < p->num_phys; i++) {273 if (p->phy_info[i].attached.sas_address ==274 rphy->identify.sas_address) {275 vdev->target_id =276+ p->phy_info[i].attached.id;277+ vdev->bus_id = p->phy_info[i].attached.channel;278 vdev->lun = sdev->lun;279+ mutex_unlock(&hd->ioc->sas_topology_mutex);280 goto out;281 }282 }283 }284+ mutex_unlock(&hd->ioc->sas_topology_mutex);285286 printk("No matching SAS device found!!\n");287 kfree(vdev);···282 return 0;283}284285+static void286+mptsas_slave_destroy(struct scsi_device *sdev)287+{288+ struct Scsi_Host *host = sdev->host;289+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;290+ struct sas_rphy *rphy;291+ struct mptsas_portinfo *p;292+ int i;293+294+ /*295+ * Handle hotplug removal case.296+ * We need to clear out attached data structure.297+ */298+ rphy = dev_to_rphy(sdev->sdev_target->dev.parent);299+300+ mutex_lock(&hd->ioc->sas_topology_mutex);301+ list_for_each_entry(p, &hd->ioc->sas_topology, list) {302+ for (i = 0; i < p->num_phys; i++) {303+ if (p->phy_info[i].attached.sas_address ==304+ rphy->identify.sas_address) {305+ memset(&p->phy_info[i].attached, 0,306+ sizeof(struct mptsas_devinfo));307+ p->phy_info[i].rphy = NULL;308+ goto out;309+ }310+ }311+ }312+313+ out:314+ mutex_unlock(&hd->ioc->sas_topology_mutex);315+ /*316+ * TODO: Issue target reset to flush firmware outstanding commands.317+ */318+ mptscsih_slave_destroy(sdev);319+}320+321static struct scsi_host_template mptsas_driver_template = {322 .module = THIS_MODULE,323 .proc_name = "mptsas",···293 .slave_alloc = mptsas_slave_alloc,294 .slave_configure = mptscsih_slave_configure,295 .target_destroy = mptscsih_target_destroy,296+ .slave_destroy = mptsas_slave_destroy,297 .change_queue_depth = mptscsih_change_queue_depth,298 .eh_abort_handler = mptscsih_abort,299 .eh_device_reset_handler = mptscsih_dev_reset,···399 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)400 return -ENXIO;401402+ if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))403 goto out;404405 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);···450 error = 0;451452 out_unlock:453+ mutex_unlock(&ioc->sas_mgmt.mutex);454 out:455 return error;456}···649 device_info->handle = le16_to_cpu(buffer->DevHandle);650 device_info->phy_id = buffer->PhyNum;651 device_info->port_id = buffer->PhysicalPort;652+ device_info->id = buffer->TargetID;653+ device_info->channel = buffer->Bus;654 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));655 device_info->sas_address = le64_to_cpu(sas_address);656 device_info->device_info =···858static int mptsas_probe_one_phy(struct device *dev,859 struct mptsas_phyinfo *phy_info, int index, int local)860{861+ struct sas_phy *phy;862 int error;863864+ phy = sas_phy_alloc(dev, index);865+ if (!phy)866 return -ENOMEM;867868+ phy->port_identifier = phy_info->port_id;869+ mptsas_parse_device_info(&phy->identify, &phy_info->identify);870871 /*872 * Set Negotiated link rate.873 */874 switch (phy_info->negotiated_link_rate) {875 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:876+ phy->negotiated_linkrate = SAS_PHY_DISABLED;877 break;878 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:879+ phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;880 break;881 case MPI_SAS_IOUNIT0_RATE_1_5:882+ phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;883 break;884 case MPI_SAS_IOUNIT0_RATE_3_0:885+ phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;886 break;887 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:888 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:889 default:890+ phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;891 break;892 }893···896 */897 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {898 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:899+ phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;900 break;901 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:902+ phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;903 break;904 default:905 break;···911 switch (phy_info->programmed_link_rate &912 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {913 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:914+ phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;915 break;916 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:917+ phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;918 break;919 default:920 break;···925 */926 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {927 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:928+ phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;929 break;930 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:931+ phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;932 break;933 default:934 break;···940 switch (phy_info->programmed_link_rate &941 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {942 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:943+ phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;944 break;945 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:946+ phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;947 break;948 default:949 break;950 }951952 if (local)953+ phy->local_attached = 1;954955+ error = sas_phy_add(phy);956 if (error) {957+ sas_phy_free(phy);958 return error;959 }960+ phy_info->phy = phy;961962 if (phy_info->attached.handle) {963 struct sas_rphy *rphy;964965+ rphy = sas_rphy_alloc(phy);966 if (!rphy)967 return 0; /* non-fatal: an rphy can be added later */968···985 u32 handle = 0xFFFF;986 int error = -ENOMEM, i;987988+ port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);989 if (!port_info)990 goto out;0991992 error = mptsas_sas_io_unit_pg0(ioc, port_info);993 if (error)994 goto out_free_port_info;995996+ ioc->num_ports = port_info->num_phys;997+ mutex_lock(&ioc->sas_topology_mutex);998 list_add_tail(&port_info->list, &ioc->sas_topology);999+ mutex_unlock(&ioc->sas_topology_mutex);1000+1001 for (i = 0; i < port_info->num_phys; i++) {1002 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],1003 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<···1034 struct mptsas_portinfo *port_info, *p;1035 int error = -ENOMEM, i, j;10361037+ port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);1038 if (!port_info)1039 goto out;010401041 error = mptsas_sas_expander_pg0(ioc, port_info,1042 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<···10471048 *handle = port_info->handle;10491050+ mutex_lock(&ioc->sas_topology_mutex);1051 list_add_tail(&port_info->list, &ioc->sas_topology);1052+ mutex_unlock(&ioc->sas_topology_mutex);1053+1054 for (i = 0; i < port_info->num_phys; i++) {1055 struct device *parent;1056···1079 * HBA phys.1080 */1081 parent = &ioc->sh->shost_gendev;1082+ mutex_lock(&ioc->sas_topology_mutex);1083 list_for_each_entry(p, &ioc->sas_topology, list) {1084 for (j = 0; j < p->num_phys; j++) {1085 if (port_info->phy_info[i].identify.handle ==···1086 parent = &p->phy_info[j].rphy->dev;1087 }1088 }1089+ mutex_unlock(&ioc->sas_topology_mutex);10901091 mptsas_probe_one_phy(parent, &port_info->phy_info[i],1092 *index, 0);···1111 ;1112}11131114+static struct mptsas_phyinfo *1115+mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)1116+{1117+ struct mptsas_portinfo *port_info;1118+ struct mptsas_devinfo device_info;1119+ struct mptsas_phyinfo *phy_info = NULL;1120+ int i, error;1121+1122+ /*1123+ * Retrieve the parent sas_address1124+ */1125+ error = mptsas_sas_device_pg0(ioc, &device_info,1126+ (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<1127+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),1128+ parent_handle);1129+ if (error) {1130+ printk("mptsas: failed to retrieve device page\n");1131+ return NULL;1132+ }1133+1134+ /*1135+ * The phy_info structures are never deallocated during lifetime of1136+ * a host, so the code below is safe without additional refcounting.1137+ */1138+ mutex_lock(&ioc->sas_topology_mutex);1139+ list_for_each_entry(port_info, &ioc->sas_topology, list) {1140+ for (i = 0; i < port_info->num_phys; i++) {1141+ if (port_info->phy_info[i].identify.sas_address ==1142+ device_info.sas_address &&1143+ port_info->phy_info[i].phy_id == phy_id) {1144+ phy_info = &port_info->phy_info[i];1145+ break;1146+ }1147+ }1148+ }1149+ mutex_unlock(&ioc->sas_topology_mutex);1150+1151+ return phy_info;1152+}1153+1154+static struct mptsas_phyinfo *1155+mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)1156+{1157+ struct mptsas_portinfo *port_info;1158+ struct mptsas_phyinfo *phy_info = NULL;1159+ int i;1160+1161+ /*1162+ * The phy_info structures are never deallocated during lifetime of1163+ * a host, so the code below is safe without additional refcounting.1164+ */1165+ mutex_lock(&ioc->sas_topology_mutex);1166+ list_for_each_entry(port_info, &ioc->sas_topology, list) {1167+ for (i = 0; i < port_info->num_phys; i++) {1168+ if (port_info->phy_info[i].attached.handle == handle) {1169+ phy_info = &port_info->phy_info[i];1170+ break;1171+ }1172+ }1173+ }1174+ mutex_unlock(&ioc->sas_topology_mutex);1175+1176+ return phy_info;1177+}1178+1179+static void1180+mptsas_hotplug_work(void *arg)1181+{1182+ struct mptsas_hotplug_event *ev = arg;1183+ MPT_ADAPTER *ioc = ev->ioc;1184+ struct mptsas_phyinfo *phy_info;1185+ struct sas_rphy *rphy;1186+ char *ds = NULL;1187+1188+ if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)1189+ ds = "ssp";1190+ if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)1191+ ds = "stp";1192+ if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)1193+ ds = "sata";1194+1195+ switch (ev->event_type) {1196+ case MPTSAS_DEL_DEVICE:1197+ printk(MYIOC_s_INFO_FMT1198+ "removing %s device, channel %d, id %d, phy %d\n",1199+ ioc->name, ds, ev->channel, ev->id, ev->phy_id);1200+1201+ phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);1202+ if (!phy_info) {1203+ printk("mptsas: remove event for non-existant PHY.\n");1204+ break;1205+ }1206+1207+ if (phy_info->rphy) {1208+ sas_rphy_delete(phy_info->rphy);1209+ phy_info->rphy = NULL;1210+ }1211+ break;1212+ case MPTSAS_ADD_DEVICE:1213+ printk(MYIOC_s_INFO_FMT1214+ "attaching %s device, channel %d, id %d, phy %d\n",1215+ ioc->name, ds, ev->channel, ev->id, ev->phy_id);1216+1217+ phy_info = mptsas_find_phyinfo_by_parent(ioc,1218+ ev->parent_handle, ev->phy_id);1219+ if (!phy_info) {1220+ printk("mptsas: add event for non-existant PHY.\n");1221+ break;1222+ }1223+1224+ if (phy_info->rphy) {1225+ printk("mptsas: trying to add existing device.\n");1226+ break;1227+ }1228+1229+ /* fill attached info */1230+ phy_info->attached.handle = ev->handle;1231+ phy_info->attached.phy_id = ev->phy_id;1232+ phy_info->attached.port_id = phy_info->identify.port_id;1233+ phy_info->attached.id = ev->id;1234+ phy_info->attached.channel = ev->channel;1235+ phy_info->attached.sas_address = ev->sas_address;1236+ phy_info->attached.device_info = ev->device_info;1237+1238+ rphy = sas_rphy_alloc(phy_info->phy);1239+ if (!rphy)1240+ break; /* non-fatal: an rphy can be added later */1241+1242+ mptsas_parse_device_info(&rphy->identify, &phy_info->attached);1243+ if (sas_rphy_add(rphy)) {1244+ sas_rphy_free(rphy);1245+ break;1246+ }1247+1248+ phy_info->rphy = rphy;1249+ break;1250+ }1251+1252+ kfree(ev);1253+}1254+1255+static void1256+mptscsih_send_sas_event(MPT_ADAPTER *ioc,1257+ EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)1258+{1259+ struct mptsas_hotplug_event *ev;1260+ u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);1261+ __le64 sas_address;1262+1263+ if ((device_info &1264+ (MPI_SAS_DEVICE_INFO_SSP_TARGET |1265+ MPI_SAS_DEVICE_INFO_STP_TARGET |1266+ MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)1267+ return;1268+1269+ if ((sas_event_data->ReasonCode &1270+ (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |1271+ MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)1272+ return;1273+1274+ ev = kmalloc(sizeof(*ev), GFP_ATOMIC);1275+ if (!ev) {1276+ printk(KERN_WARNING "mptsas: lost hotplug event\n");1277+ return;1278+ }1279+1280+1281+ INIT_WORK(&ev->work, mptsas_hotplug_work, ev);1282+ ev->ioc = ioc;1283+ ev->handle = le16_to_cpu(sas_event_data->DevHandle);1284+ ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);1285+ ev->channel = sas_event_data->Bus;1286+ ev->id = sas_event_data->TargetID;1287+ ev->phy_id = sas_event_data->PhyNum;1288+ memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));1289+ ev->sas_address = le64_to_cpu(sas_address);1290+ ev->device_info = device_info;1291+1292+ if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)1293+ ev->event_type = MPTSAS_ADD_DEVICE;1294+ else1295+ ev->event_type = MPTSAS_DEL_DEVICE;1296+1297+ schedule_work(&ev->work);1298+}1299+1300+static int1301+mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)1302+{1303+ u8 event = le32_to_cpu(reply->Event) & 0xFF;1304+1305+ if (!ioc->sh)1306+ return 1;1307+1308+ switch (event) {1309+ case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:1310+ mptscsih_send_sas_event(ioc,1311+ (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);1312+ return 1; /* currently means nothing really */1313+1314+ default:1315+ return mptscsih_event_process(ioc, reply);1316+ }1317+}1318+1319static int1320mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)1321{···1118 MPT_SCSI_HOST *hd;1119 MPT_ADAPTER *ioc;1120 unsigned long flags;1121+ int ii;1122 int numSGE = 0;1123 int scale;1124 int ioc_cap;01125 int error=0;1126 int r;1127···1203 sh->unique_id = ioc->id;12041205 INIT_LIST_HEAD(&ioc->sas_topology);1206+ mutex_init(&ioc->sas_topology_mutex);1207+1208+ mutex_init(&ioc->sas_mgmt.mutex);1209 init_completion(&ioc->sas_mgmt.done);12101211 /* Verify that we won't exceed the maximum···1244 /* SCSI needs scsi_cmnd lookup table!1245 * (with size equal to req_depth*PtrSz!)1246 */1247+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);1248+ if (!hd->ScsiLookup) {01249 error = -ENOMEM;1250 goto out_mptsas_probe;1251 }12521253+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",1254+ ioc->name, hd->ScsiLookup));00012551256 /* Allocate memory for the device structures.1257 * A non-Null pointer at an offset1258 * indicates a device exists.1259 * max_id = 1 + maximum id (hosts.h)1260 */1261+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);1262+ if (!hd->Targets) {01263 error = -ENOMEM;1264 goto out_mptsas_probe;1265 }12661267+ dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));000012681269 /* Clear the TM flags1270 */···13241325 mptsas_scan_sas_topology(ioc);13261327+ /*1328+ Reporting RAID volumes.1329+ */1330+ if (!ioc->raid_data.pIocPg2)1331+ return 0;1332+ if (!ioc->raid_data.pIocPg2->NumActiveVolumes)1333+ return 0;1334+ for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {1335+ scsi_add_device(sh,1336+ ioc->num_ports,1337+ ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,1338+ 0);1339+ }1340+1341 return 0;13421343out_mptsas_probe:···13391340 sas_remove_host(ioc->sh);13411342+ mutex_lock(&ioc->sas_topology_mutex);1343 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {1344 list_del(&p->list);1345 kfree(p);1346 }1347+ mutex_unlock(&ioc->sas_topology_mutex);13481349 mptscsih_remove(pdev);1350}···1393 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);1394 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);13951396+ if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {1397 devtprintk((KERN_INFO MYNAM1398 ": Registered for IOC event notifications\n"));1399 }
+26-8
drivers/message/fusion/mptscsih.c
···893 * when a lun is disable by mid-layer.894 * Do NOT access the referenced scsi_cmnd structure or895 * members. Will cause either a paging or NULL ptr error.0896 * @hd: Pointer to a SCSI HOST structure897 * @vdevice: per device private data898 *···2163{2164 VirtTarget *vtarget;21652166- vtarget = kmalloc(sizeof(VirtTarget), GFP_KERNEL);2167 if (!vtarget)2168 return -ENOMEM;2169- memset(vtarget, 0, sizeof(VirtTarget));2170 starget->hostdata = vtarget;2171 return 0;2172}···2185 VirtDevice *vdev;2186 struct scsi_target *starget;21872188- vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);2189 if (!vdev) {2190 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",2191 hd->ioc->name, sizeof(VirtDevice));2192 return -ENOMEM;2193 }21942195- memset(vdev, 0, sizeof(VirtDevice));2196 vdev->ioc_id = hd->ioc->id;2197 vdev->target_id = sdev->id;2198 vdev->bus_id = sdev->channel;···2558 hd->cmdPtr = NULL;2559 }25602561- /* 7. Set flag to force DV and re-read IOC Page 32562 */2563 if (ioc->bus_type == SPI) {2564 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;2565 ddvtprintk(("Set reload IOC Pg3 Flag\n"));2566 }25670000000000002568 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));25692570 }···2600{2601 MPT_SCSI_HOST *hd;2602 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;0026032604 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",2605 ioc->name, event));···2623 /* FIXME! */2624 break;2625000000002626 /*2627 * CHECKME! Don't think we need to do2628 * anything for these, but...2629 */2630- case MPI_EVENT_RESCAN: /* 06 */2631 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */2632 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */2633 /*···3972 mptscsih_do_cmd(hd, &iocmd);3973}39743975-/* Search IOC page 3 to determine if this is hidden physical disk3976- */3977/* Search IOC page 3 to determine if this is hidden physical disk3978 */3979static int
···893 * when a lun is disable by mid-layer.894 * Do NOT access the referenced scsi_cmnd structure or895 * members. Will cause either a paging or NULL ptr error.896+ * (BUT, BUT, BUT, the code does reference it! - mdr)897 * @hd: Pointer to a SCSI HOST structure898 * @vdevice: per device private data899 *···2162{2163 VirtTarget *vtarget;21642165+ vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);2166 if (!vtarget)2167 return -ENOMEM;02168 starget->hostdata = vtarget;2169 return 0;2170}···2185 VirtDevice *vdev;2186 struct scsi_target *starget;21872188+ vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);2189 if (!vdev) {2190 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",2191 hd->ioc->name, sizeof(VirtDevice));2192 return -ENOMEM;2193 }219402195 vdev->ioc_id = hd->ioc->id;2196 vdev->target_id = sdev->id;2197 vdev->bus_id = sdev->channel;···2559 hd->cmdPtr = NULL;2560 }25612562+ /* 7. SPI: Set flag to force DV and re-read IOC Page 32563 */2564 if (ioc->bus_type == SPI) {2565 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;2566 ddvtprintk(("Set reload IOC Pg3 Flag\n"));2567 }25682569+ /* 7. FC: Rescan for blocked rports which might have returned.2570+ */2571+ else if (ioc->bus_type == FC) {2572+ int work_count;2573+ unsigned long flags;2574+2575+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);2576+ work_count = ++ioc->fc_rescan_work_count;2577+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);2578+ if (work_count == 1)2579+ schedule_work(&ioc->fc_rescan_work);2580+ }2581 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));25822583 }···2589{2590 MPT_SCSI_HOST *hd;2591 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;2592+ int work_count;2593+ unsigned long flags;25942595 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",2596 ioc->name, event));···2610 /* FIXME! */2611 break;26122613+ case MPI_EVENT_RESCAN: /* 06 */2614+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);2615+ work_count = ++ioc->fc_rescan_work_count;2616+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);2617+ if (work_count == 1)2618+ schedule_work(&ioc->fc_rescan_work);2619+ break;2620+2621 /*2622 * CHECKME! Don't think we need to do2623 * anything for these, but...2624 */02625 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */2626 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */2627 /*···3952 mptscsih_do_cmd(hd, &iocmd);3953}3954003955/* Search IOC page 3 to determine if this is hidden physical disk3956 */3957static int
+8-18
drivers/message/fusion/mptspi.c
···158 MPT_SCSI_HOST *hd;159 MPT_ADAPTER *ioc;160 unsigned long flags;161- int sz, ii;162 int numSGE = 0;163 int scale;164 int ioc_cap;165- u8 *mem;166 int error=0;167 int r;168···287 /* SCSI needs scsi_cmnd lookup table!288 * (with size equal to req_depth*PtrSz!)289 */290- sz = ioc->req_depth * sizeof(void *);291- mem = kmalloc(sz, GFP_ATOMIC);292- if (mem == NULL) {293 error = -ENOMEM;294 goto out_mptspi_probe;295 }296297- memset(mem, 0, sz);298- hd->ScsiLookup = (struct scsi_cmnd **) mem;299-300- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",301- ioc->name, hd->ScsiLookup, sz));302303 /* Allocate memory for the device structures.304 * A non-Null pointer at an offset305 * indicates a device exists.306 * max_id = 1 + maximum id (hosts.h)307 */308- sz = sh->max_id * sizeof(void *);309- mem = kmalloc(sz, GFP_ATOMIC);310- if (mem == NULL) {311 error = -ENOMEM;312 goto out_mptspi_probe;313 }314315- memset(mem, 0, sz);316- hd->Targets = (VirtTarget **) mem;317-318- dprintk((KERN_INFO319- " vdev @ %p, sz=%d\n", hd->Targets, sz));320321 /* Clear the TM flags322 */
···158 MPT_SCSI_HOST *hd;159 MPT_ADAPTER *ioc;160 unsigned long flags;161+ int ii;162 int numSGE = 0;163 int scale;164 int ioc_cap;0165 int error=0;166 int r;167···288 /* SCSI needs scsi_cmnd lookup table!289 * (with size equal to req_depth*PtrSz!)290 */291+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);292+ if (!hd->ScsiLookup) {0293 error = -ENOMEM;294 goto out_mptspi_probe;295 }296297+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",298+ ioc->name, hd->ScsiLookup));000299300 /* Allocate memory for the device structures.301 * A non-Null pointer at an offset302 * indicates a device exists.303 * max_id = 1 + maximum id (hosts.h)304 */305+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);306+ if (!hd->Targets) {0307 error = -ENOMEM;308 goto out_mptspi_probe;309 }310311+ dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));0000312313 /* Clear the TM flags314 */
+5-5
drivers/message/i2o/pci.c
···88 struct device *dev = &pdev->dev;89 int i;9091- if (pci_request_regions(pdev, OSM_DESCRIPTION)) {92- printk(KERN_ERR "%s: device already claimed\n", c->name);93- return -ENODEV;94- }95-96 for (i = 0; i < 6; i++) {97 /* Skip I/O spaces */98 if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {···312 printk(KERN_WARNING "i2o: couldn't enable device %s\n",313 pci_name(pdev));314 return rc;00000315 }316317 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
···88 struct device *dev = &pdev->dev;89 int i;900000091 for (i = 0; i < 6; i++) {92 /* Skip I/O spaces */93 if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {···317 printk(KERN_WARNING "i2o: couldn't enable device %s\n",318 pci_name(pdev));319 return rc;320+ }321+322+ if (pci_request_regions(pdev, OSM_DESCRIPTION)) {323+ printk(KERN_ERR "i2o: device already claimed\n");324+ return -ENODEV;325 }326327 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+2
drivers/s390/scsi/zfcp_aux.c
···1125 zfcp_free_low_mem_buffers(adapter);1126 /* free memory of adapter data structure and queues */1127 zfcp_qdio_free_queues(adapter);001128 ZFCP_LOG_TRACE("freeing adapter structure\n");1129 kfree(adapter);1130 out:
···1125 zfcp_free_low_mem_buffers(adapter);1126 /* free memory of adapter data structure and queues */1127 zfcp_qdio_free_queues(adapter);1128+ kfree(adapter->fc_stats);1129+ kfree(adapter->stats_reset_data);1130 ZFCP_LOG_TRACE("freeing adapter structure\n");1131 kfree(adapter);1132 out:
+3-1
drivers/s390/scsi/zfcp_def.h
···921 u32 physical_s_id; /* local FC port ID */922 struct ccw_device *ccw_device; /* S/390 ccw device */923 u8 fc_service_class;924- u32 fc_topology; /* FC topology */925 u32 hydra_version; /* Hydra version */926 u32 fsf_lic_version;927 u32 adapter_features; /* FCP channel features */···977 struct zfcp_adapter_mempool pool; /* Adapter memory pools */978 struct qdio_initialize qdio_init_data; /* for qdio_establish */979 struct device generic_services; /* directory for WKA ports */000980};981982/*
···921 u32 physical_s_id; /* local FC port ID */922 struct ccw_device *ccw_device; /* S/390 ccw device */923 u8 fc_service_class;0924 u32 hydra_version; /* Hydra version */925 u32 fsf_lic_version;926 u32 adapter_features; /* FCP channel features */···978 struct zfcp_adapter_mempool pool; /* Adapter memory pools */979 struct qdio_initialize qdio_init_data; /* for qdio_establish */980 struct device generic_services; /* directory for WKA ports */981+ struct fc_host_statistics *fc_stats;982+ struct fsf_qtcb_bottom_port *stats_reset_data;983+ unsigned long stats_reset;984};985986/*
+1-1
drivers/s390/scsi/zfcp_erp.c
···2613 case ZFCP_ERP_STEP_UNINITIALIZED:2614 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:2615 case ZFCP_ERP_STEP_PORT_CLOSING:2616- if (adapter->fc_topology == FSF_TOPO_P2P) {2617 if (port->wwpn != adapter->peer_wwpn) {2618 ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx "2619 "on adapter %s.\nPeer WWPN "
···2613 case ZFCP_ERP_STEP_UNINITIALIZED:2614 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:2615 case ZFCP_ERP_STEP_PORT_CLOSING:2616+ if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) {2617 if (port->wwpn != adapter->peer_wwpn) {2618 ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx "2619 "on adapter %s.\nPeer WWPN "
+60-24
drivers/s390/scsi/zfcp_fsf.c
···964 | ZFCP_STATUS_COMMON_ERP_FAILED);965 break;9660000000000000000000000000000000000967 case FSF_STATUS_READ_CFDC_UPDATED:968 ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",969 zfcp_get_busid_by_adapter(adapter));···1988 erp_action->fsf_req->qtcb->bottom.config.feature_selection =1989 FSF_FEATURE_CFDC |1990 FSF_FEATURE_LUN_SHARING |01991 FSF_FEATURE_UPDATE_ALERT;19921993 /* start QDIO request for this FSF request */···2043 fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;2044 fc_host_speed(shost) = bottom->fc_link_speed;2045 fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;2046- adapter->fc_topology = bottom->fc_topology;2047 adapter->hydra_version = bottom->adapter_type;2048- if (adapter->physical_wwpn == 0)2049- adapter->physical_wwpn = fc_host_port_name(shost);2050- if (adapter->physical_s_id == 0)2051- adapter->physical_s_id = fc_host_port_id(shost);00000000002052 } else {2053 fc_host_node_name(shost) = 0;2054 fc_host_port_name(shost) = 0;2055 fc_host_port_id(shost) = 0;2056 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;2057- adapter->fc_topology = 0;2058 adapter->hydra_version = 0;2059- }2060-2061- if (adapter->fc_topology == FSF_TOPO_P2P) {2062- adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;2063- adapter->peer_wwpn = bottom->plogi_payload.wwpn;2064- adapter->peer_wwnn = bottom->plogi_payload.wwnn;2065 }20662067 if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {···2135 if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))2136 return -EIO;21372138- switch (adapter->fc_topology) {2139- case FSF_TOPO_P2P:2140 ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "2141 "configuration detected at adapter %s\n"2142 "Peer WWNN 0x%016llx, "···2149 debug_text_event(fsf_req->adapter->erp_dbf, 0,2150 "top-p-to-p");2151 break;2152- case FSF_TOPO_AL:2153 ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "2154 "topology detected at adapter %s "2155 "unsupported, shutting down adapter\n",···2158 "top-al");2159 zfcp_erp_adapter_shutdown(adapter, 0);2160 return -EIO;2161- case FSF_TOPO_FABRIC:2162 ZFCP_LOG_NORMAL("Switched fabric fibrechannel "2163 "network detected at adapter %s.\n",2164 zfcp_get_busid_by_adapter(adapter));···2171 "of a type known to the zfcp "2172 "driver, shutting down adapter\n",2173 zfcp_get_busid_by_adapter(adapter));2174- adapter->fc_topology = FSF_TOPO_ERROR;2175 debug_text_exception(fsf_req->adapter->erp_dbf, 0,2176 "unknown-topo");2177 zfcp_erp_adapter_shutdown(adapter, 0);···2330 data = (struct fsf_qtcb_bottom_port*) fsf_req->data;2331 if (data)2332 memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));2333- if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {2334- adapter->physical_wwpn = bottom->wwpn;2335- adapter->physical_s_id = bottom->fc_port_id;2336- } else {2337- adapter->physical_wwpn = fc_host_port_name(shost);2338- adapter->physical_s_id = fc_host_port_id(shost);2339- }2340 fc_host_maxframe_size(shost) = bottom->maximum_frame_size;02341 break;23422343 case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
···964 | ZFCP_STATUS_COMMON_ERP_FAILED);965 break;966967+ case FSF_STATUS_READ_NOTIFICATION_LOST:968+ ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: "969+ "adapter %s%s%s%s%s%s%s%s%s\n",970+ zfcp_get_busid_by_adapter(adapter),971+ (status_buffer->status_subtype &972+ FSF_STATUS_READ_SUB_INCOMING_ELS) ?973+ ", incoming ELS" : "",974+ (status_buffer->status_subtype &975+ FSF_STATUS_READ_SUB_SENSE_DATA) ?976+ ", sense data" : "",977+ (status_buffer->status_subtype &978+ FSF_STATUS_READ_SUB_LINK_STATUS) ?979+ ", link status change" : "",980+ (status_buffer->status_subtype &981+ FSF_STATUS_READ_SUB_PORT_CLOSED) ?982+ ", port close" : "",983+ (status_buffer->status_subtype &984+ FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ?985+ ", bit error exception" : "",986+ (status_buffer->status_subtype &987+ FSF_STATUS_READ_SUB_ACT_UPDATED) ?988+ ", ACT update" : "",989+ (status_buffer->status_subtype &990+ FSF_STATUS_READ_SUB_ACT_HARDENED) ?991+ ", ACT hardening" : "",992+ (status_buffer->status_subtype &993+ FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ?994+ ", adapter feature change" : "");995+996+ if (status_buffer->status_subtype &997+ FSF_STATUS_READ_SUB_ACT_UPDATED)998+ zfcp_erp_adapter_access_changed(adapter);999+ break;1000+1001 case FSF_STATUS_READ_CFDC_UPDATED:1002 ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",1003 zfcp_get_busid_by_adapter(adapter));···1954 erp_action->fsf_req->qtcb->bottom.config.feature_selection =1955 FSF_FEATURE_CFDC |1956 FSF_FEATURE_LUN_SHARING |1957+ FSF_FEATURE_NOTIFICATION_LOST |1958 FSF_FEATURE_UPDATE_ALERT;19591960 /* start QDIO request for this FSF request */···2008 fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;2009 fc_host_speed(shost) = bottom->fc_link_speed;2010 fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;02011 adapter->hydra_version = bottom->adapter_type;2012+ if (fc_host_permanent_port_name(shost) == -1)2013+ fc_host_permanent_port_name(shost) =2014+ fc_host_port_name(shost);2015+ if (bottom->fc_topology == FSF_TOPO_P2P) {2016+ adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;2017+ adapter->peer_wwpn = bottom->plogi_payload.wwpn;2018+ adapter->peer_wwnn = bottom->plogi_payload.wwnn;2019+ fc_host_port_type(shost) = FC_PORTTYPE_PTP;2020+ } else if (bottom->fc_topology == FSF_TOPO_FABRIC)2021+ fc_host_port_type(shost) = FC_PORTTYPE_NPORT;2022+ else if (bottom->fc_topology == FSF_TOPO_AL)2023+ fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;2024+ else2025+ fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;2026 } else {2027 fc_host_node_name(shost) = 0;2028 fc_host_port_name(shost) = 0;2029 fc_host_port_id(shost) = 0;2030 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;2031+ fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;2032 adapter->hydra_version = 0;0000002033 }20342035 if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {···2097 if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))2098 return -EIO;20992100+ switch (fc_host_port_type(adapter->scsi_host)) {2101+ case FC_PORTTYPE_PTP:2102 ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "2103 "configuration detected at adapter %s\n"2104 "Peer WWNN 0x%016llx, "···2111 debug_text_event(fsf_req->adapter->erp_dbf, 0,2112 "top-p-to-p");2113 break;2114+ case FC_PORTTYPE_NLPORT:2115 ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "2116 "topology detected at adapter %s "2117 "unsupported, shutting down adapter\n",···2120 "top-al");2121 zfcp_erp_adapter_shutdown(adapter, 0);2122 return -EIO;2123+ case FC_PORTTYPE_NPORT:2124 ZFCP_LOG_NORMAL("Switched fabric fibrechannel "2125 "network detected at adapter %s.\n",2126 zfcp_get_busid_by_adapter(adapter));···2133 "of a type known to the zfcp "2134 "driver, shutting down adapter\n",2135 zfcp_get_busid_by_adapter(adapter));02136 debug_text_exception(fsf_req->adapter->erp_dbf, 0,2137 "unknown-topo");2138 zfcp_erp_adapter_shutdown(adapter, 0);···2293 data = (struct fsf_qtcb_bottom_port*) fsf_req->data;2294 if (data)2295 memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));2296+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)2297+ fc_host_permanent_port_name(shost) = bottom->wwpn;2298+ else2299+ fc_host_permanent_port_name(shost) =2300+ fc_host_port_name(shost);002301 fc_host_maxframe_size(shost) = bottom->maximum_frame_size;2302+ fc_host_supported_speeds(shost) = bottom->supported_speed;2303 break;23042305 case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+12-1
drivers/s390/scsi/zfcp_fsf.h
···166#define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004167#define FSF_STATUS_READ_LINK_DOWN 0x00000005168#define FSF_STATUS_READ_LINK_UP 0x000000060169#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A170#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B171#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C···180#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001181#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x000000021820000000000183/* status subtypes for CFDC */184#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002185#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F···199#define FSF_TOPO_P2P 0x00000001200#define FSF_TOPO_FABRIC 0x00000002201#define FSF_TOPO_AL 0x00000003202-#define FSF_TOPO_FABRIC_VIRT 0x00000004203204/* data direction for FCP commands */205#define FSF_DATADIR_WRITE 0x00000001···221/* channel features */222#define FSF_FEATURE_CFDC 0x00000002223#define FSF_FEATURE_LUN_SHARING 0x000000040224#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010225#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020226#define FSF_FEATURE_UPDATE_ALERT 0x00000100
···166#define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004167#define FSF_STATUS_READ_LINK_DOWN 0x00000005168#define FSF_STATUS_READ_LINK_UP 0x00000006169+#define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009170#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A171#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B172#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C···179#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001180#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002181182+/* status subtypes for unsolicited status notification lost */183+#define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001184+#define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002185+#define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004186+#define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008187+#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010188+#define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020189+#define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040190+#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080191+192/* status subtypes for CFDC */193#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002194#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F···188#define FSF_TOPO_P2P 0x00000001189#define FSF_TOPO_FABRIC 0x00000002190#define FSF_TOPO_AL 0x000000030191192/* data direction for FCP commands */193#define FSF_DATADIR_WRITE 0x00000001···211/* channel features */212#define FSF_FEATURE_CFDC 0x00000002213#define FSF_FEATURE_LUN_SHARING 0x00000004214+#define FSF_FEATURE_NOTIFICATION_LOST 0x00000008215#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010216#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020217#define FSF_FEATURE_UPDATE_ALERT 0x00000100
···73#include <linux/delay.h>74#include <linux/pci.h>75#include <linux/time.h>076#include <asm/io.h>77#include <asm/irq.h>78#include <asm/uaccess.h>···616 void __user *argp = (void __user *)arg;617618 /* Only let one of these through at a time */619- if (down_interruptible(&tw_dev->ioctl_sem)) {620 retval = TW_IOCTL_ERROR_OS_EINTR;621 goto out;622 }···853 /* Now free ioctl buf memory */854 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);855out2:856- up(&tw_dev->ioctl_sem);857out:858 return retval;859} /* End twa_chrdev_ioctl() */···1183 tw_dev->error_sequence_id = 1;1184 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;11851186- init_MUTEX(&tw_dev->ioctl_sem);1187 init_waitqueue_head(&tw_dev->ioctl_wqueue);11881189 retval = 0;
···73#include <linux/delay.h>74#include <linux/pci.h>75#include <linux/time.h>76+#include <linux/mutex.h>77#include <asm/io.h>78#include <asm/irq.h>79#include <asm/uaccess.h>···615 void __user *argp = (void __user *)arg;616617 /* Only let one of these through at a time */618+ if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {619 retval = TW_IOCTL_ERROR_OS_EINTR;620 goto out;621 }···852 /* Now free ioctl buf memory */853 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);854out2:855+ mutex_unlock(&tw_dev->ioctl_lock);856out:857 return retval;858} /* End twa_chrdev_ioctl() */···1182 tw_dev->error_sequence_id = 1;1183 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;11841185+ mutex_init(&tw_dev->ioctl_lock);1186 init_waitqueue_head(&tw_dev->ioctl_wqueue);11871188 retval = 0;
+1-1
drivers/scsi/3w-9xxx.h
···672 u32 ioctl_msec;673 int chrdev_request_id;674 wait_queue_head_t ioctl_wqueue;675- struct semaphore ioctl_sem;676 char aen_clobber;677 unsigned short working_srl;678 unsigned short working_branch;
···672 u32 ioctl_msec;673 int chrdev_request_id;674 wait_queue_head_t ioctl_wqueue;675+ struct mutex ioctl_lock;676 char aen_clobber;677 unsigned short working_srl;678 unsigned short working_branch;
+4-3
drivers/scsi/3w-xxxx.c
···203#include <linux/delay.h>204#include <linux/pci.h>205#include <linux/time.h>0206#include <asm/io.h>207#include <asm/irq.h>208#include <asm/uaccess.h>···889 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");890891 /* Only let one of these through at a time */892- if (down_interruptible(&tw_dev->ioctl_sem))893 return -EINTR;894895 /* First copy down the buffer length */···1030 /* Now free ioctl buf memory */1031 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);1032out:1033- up(&tw_dev->ioctl_sem);1034 return retval;1035} /* End tw_chrdev_ioctl() */1036···1271 tw_dev->pending_tail = TW_Q_START;1272 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;12731274- init_MUTEX(&tw_dev->ioctl_sem);1275 init_waitqueue_head(&tw_dev->ioctl_wqueue);12761277 return 0;
···203#include <linux/delay.h>204#include <linux/pci.h>205#include <linux/time.h>206+#include <linux/mutex.h>207#include <asm/io.h>208#include <asm/irq.h>209#include <asm/uaccess.h>···888 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");889890 /* Only let one of these through at a time */891+ if (mutex_lock_interruptible(&tw_dev->ioctl_lock))892 return -EINTR;893894 /* First copy down the buffer length */···1029 /* Now free ioctl buf memory */1030 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);1031out:1032+ mutex_unlock(&tw_dev->ioctl_lock);1033 return retval;1034} /* End tw_chrdev_ioctl() */1035···1270 tw_dev->pending_tail = TW_Q_START;1271 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;12721273+ mutex_init(&tw_dev->ioctl_lock);1274 init_waitqueue_head(&tw_dev->ioctl_wqueue);12751276 return 0;
···1-AACRAID Driver for Linux (take two)2-3-Introduction4--------------------------5-The aacraid driver adds support for Adaptec (http://www.adaptec.com)6-RAID controllers. This is a major rewrite from the original 7-Adaptec supplied driver. It has signficantly cleaned up both the code8-and the running binary size (the module is less than half the size of9-the original).10-11-Supported Cards/Chipsets12--------------------------13- Adaptec 2020S14- Adaptec 2025S15- Adaptec 2120S16- Adaptec 2130S17- Adaptec 2200S18- Adaptec 2230S19- Adaptec 2240S20- Adaptec 2410SA21- Adaptec 2610SA22- Adaptec 2810SA23- Adaptec 21610SA24- Adaptec 3230S25- Adaptec 3240S26- Adaptec 4000SAS27- Adaptec 4005SAS28- Adaptec 4800SAS29- Adaptec 4805SAS30- Adaptec 5400S31- Dell PERC 2 Quad Channel32- Dell PERC 2/Si33- Dell PERC 3/Si34- Dell PERC 3/Di35- Dell CERC 236- HP NetRAID-4M37- Legend S22038- Legend S23039- IBM ServeRAID 8i40- ICP 9014R041- ICP 9024R042- ICP 9047MA43- ICP 9087MA44- ICP 9085LI45- ICP 5085AU46-47-People48--------------------------49-Alan Cox <alan@redhat.com>50-Christoph Hellwig <hch@infradead.org> (updates for new-style PCI probing and SCSI host registration,51- small cleanups/fixes)52-Matt Domsch <matt_domsch@dell.com> (revision ioctl, adapter messages)53-Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers54- added new ioctls, changed scsi interface to use new error handler,55- increased the number of fibs and outstanding commands to a container)56-57- (fixed 64bit and 64G memory model, changed confusing naming convention58- where fibs that go to the hardware are consistently called hw_fibs and59- not just fibs like the name of the driver tracking structure)60-Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.61-62-Original Driver63--------------------------64-Adaptec Unix OEM Product Group65-66-Mailing List67--------------------------68-linux-scsi@vger.kernel.org (Interested parties troll here)69-Also note this is very different to Brian's original driver70-so don't expect him to support it.71-Adaptec does support this driver. Contact either tech support or Mark Salyzyn.72-73-Original by Brian Boerner February 200174-Rewritten by Alan Cox, November 2001
···532#define AAC_QUIRK_MASTER 0x0008533534/*0000000535 * The adapter interface specs all queues to be located in the same536 * physically contigous block. The host structure that defines the537 * commuication queues will assume they are each a separate physically
···532#define AAC_QUIRK_MASTER 0x0008533534/*535+ * Some adapter firmware perform poorly when it must split up scatter gathers536+ * in order to deal with the limits of the underlying CHIM. This limit in this537+ * class of adapters is 17 scatter gather elements.538+ */539+#define AAC_QUIRK_17SG 0x0010540+541+/*542 * The adapter interface specs all queues to be located in the same543 * physically contigous block. The host structure that defines the544 * commuication queues will assume they are each a separate physically
+4
drivers/scsi/aacraid/commctrl.c
···85 if (size < le16_to_cpu(kfib->header.SenderSize))86 size = le16_to_cpu(kfib->header.SenderSize);87 if (size > dev->max_fib_size) {000088 /* Highjack the hw_fib */89 hw_fib = fibptr->hw_fib;90 hw_fib_pa = fibptr->hw_fib_pa;
···85 if (size < le16_to_cpu(kfib->header.SenderSize))86 size = le16_to_cpu(kfib->header.SenderSize);87 if (size > dev->max_fib_size) {88+ if (size > 2048) {89+ retval = -EINVAL;90+ goto cleanup;91+ }92 /* Highjack the hw_fib */93 hw_fib = fibptr->hw_fib;94 hw_fib_pa = fibptr->hw_fib_pa;
···42config AIC7XXX_RESET_DELAY_MS43 int "Initial bus reset delay in milli-seconds"44 depends on SCSI_AIC7XXX45- default "15000"46 ---help---47 The number of milliseconds to delay after an initial bus reset.48 The bus settle delay following all error recovery actions is49 dictated by the SCSI layer and is not affected by this value.5051- Default: 15000 (15 seconds)5253config AIC7XXX_PROBE_EISA_VL54 bool "Probe for EISA and VL AIC7XXX Adapters"
···42config AIC7XXX_RESET_DELAY_MS43 int "Initial bus reset delay in milli-seconds"44 depends on SCSI_AIC7XXX45+ default "5000"46 ---help---47 The number of milliseconds to delay after an initial bus reset.48 The bus settle delay following all error recovery actions is49 dictated by the SCSI layer and is not affected by this value.5051+ Default: 5000 (5 seconds)5253config AIC7XXX_PROBE_EISA_VL54 bool "Probe for EISA and VL AIC7XXX Adapters"
+26-13
drivers/scsi/aic7xxx/aic79xx.h
···37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE38 * POSSIBILITY OF SUCH DAMAGES.39 *40- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#95 $41 *42 * $FreeBSD$43 */···75#define INITIATOR_WILDCARD (~0)76#define SCB_LIST_NULL 0xFF0077#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL))78-#define QOUTFIFO_ENTRY_VALID 0x800079-#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000))80#define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)8182#define SCSIID_TARGET(ahd, scsiid) \···10521053typedef void ahd_callback_t (void *);105400000001055struct ahd_softc {1056 bus_space_tag_t tags[2];1057 bus_space_handle_t bshs[2];···1068 struct scb_data scb_data;10691070 struct hardware_scb *next_queued_hscb;010711072 /*1073 * SCBs that have been sent to the controller···1147 ahd_flag flags;1148 struct seeprom_config *seep_config;11491150- /* Values to store in the SEQCTL register for pause and unpause */1151- uint8_t unpause;1152- uint8_t pause;1153-1154 /* Command Queues */01155 uint16_t qoutfifonext;1156 uint16_t qoutfifonext_valid_tag;1157 uint16_t qinfifonext;1158 uint16_t qinfifo[AHD_SCB_MAX];1159- uint16_t *qoutfifo;000000000011601161 /* Critical Section Data */1162 struct cs *critical_sections;···1211 */1212 bus_dma_tag_t parent_dmat;1213 bus_dma_tag_t shared_data_dmat;1214- bus_dmamap_t shared_data_dmamap;1215- dma_addr_t shared_data_busaddr;12161217 /* Information saved through suspend/resume cycles */1218 struct ahd_suspend_state suspend_state;···1309};13101311/****************************** PCI Structures ********************************/1312-#define AHD_PCI_IOADDR0 PCIR_MAPS /* I/O BAR*/1313-#define AHD_PCI_MEMADDR (PCIR_MAPS + 4) /* Memory BAR */1314-#define AHD_PCI_IOADDR1 (PCIR_MAPS + 12)/* Second I/O BAR */13151316typedef int (ahd_device_setup_t)(struct ahd_softc *);1317
···37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE38 * POSSIBILITY OF SUCH DAMAGES.39 *40+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $41 *42 * $FreeBSD$43 */···75#define INITIATOR_WILDCARD (~0)76#define SCB_LIST_NULL 0xFF0077#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL))78+#define QOUTFIFO_ENTRY_VALID 0x80079#define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)8081#define SCSIID_TARGET(ahd, scsiid) \···10531054typedef void ahd_callback_t (void *);10551056+struct ahd_completion1057+{1058+ uint16_t tag;1059+ uint8_t sg_status;1060+ uint8_t valid_tag;1061+};1062+1063struct ahd_softc {1064 bus_space_tag_t tags[2];1065 bus_space_handle_t bshs[2];···1062 struct scb_data scb_data;10631064 struct hardware_scb *next_queued_hscb;1065+ struct map_node *next_queued_hscb_map;10661067 /*1068 * SCBs that have been sent to the controller···1140 ahd_flag flags;1141 struct seeprom_config *seep_config;114200001143 /* Command Queues */1144+ struct ahd_completion *qoutfifo;1145 uint16_t qoutfifonext;1146 uint16_t qoutfifonext_valid_tag;1147 uint16_t qinfifonext;1148 uint16_t qinfifo[AHD_SCB_MAX];1149+1150+ /*1151+ * Our qfreeze count. The sequencer compares1152+ * this value with its own counter to determine1153+ * whether to allow selections to occur.1154+ */1155+ uint16_t qfreeze_cnt;1156+1157+ /* Values to store in the SEQCTL register for pause and unpause */1158+ uint8_t unpause;1159+ uint8_t pause;11601161 /* Critical Section Data */1162 struct cs *critical_sections;···1197 */1198 bus_dma_tag_t parent_dmat;1199 bus_dma_tag_t shared_data_dmat;1200+ struct map_node shared_data_map;012011202 /* Information saved through suspend/resume cycles */1203 struct ahd_suspend_state suspend_state;···1296};12971298/****************************** PCI Structures ********************************/1299+#define AHD_PCI_IOADDR0 PCIR_BAR(0) /* I/O BAR*/1300+#define AHD_PCI_MEMADDR PCIR_BAR(1) /* Memory BAR */1301+#define AHD_PCI_IOADDR1 PCIR_BAR(3) /* Second I/O BAR */13021303typedef int (ahd_device_setup_t)(struct ahd_softc *);1304
+39-21
drivers/scsi/aic7xxx/aic79xx.reg
···39 *40 * $FreeBSD$41 */42-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"4344/*45 * This file is processed by the aic7xxx_asm utility for use in assembling···65 mvi MODE_PTR, MK_MODE(src, dst); \66 }6768-#define TOGGLE_DFF_MODE \69- if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \70- call toggle_dff_mode_work_around; \71- } else { \72- xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \73- }74-75#define RESTORE_MODE(mode) \76 if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \77 mov mode call set_mode_work_around; \···11921193/*1194 * LQ Packet In1195- * The last LQ Packet received1196 */1197register LQIN {1198 address 0x020···3535 COMPLETE_DMA_SCB_HEAD {3536 size 23537 }3538- /* Counting semaphore to prevent new select-outs */0000000000000000000003539 QFREEZE_COUNT {0003540 size 23541 }3542 /*···3642 size 13643 }3644 /*000000000003645 * Base address of our shared data with the kernel driver in host3646 * memory. This includes the qoutfifo and target mode3647 * incoming command queue.···3666 */3667 QOUTFIFO_NEXT_ADDR {3668 size 43669- }3670- /*3671- * Kernel and sequencer offsets into the queue of3672- * incoming target mode command descriptors. The3673- * queue is full when the KERNEL_TQINPOS == TQINPOS.3674- */3675- KERNEL_TQINPOS {3676- size 13677- }3678- TQINPOS { 3679- size 13680 }3681 ARG_1 {3682 size 1···3968const SG_SIZEOF download3969const PKT_OVERRUN_BUFOFFSET download3970const SCB_TRANSFER_SIZE download039713972/*3973 * BIOS SCB offsets
···39 *40 * $FreeBSD$41 */42+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"4344/*45 * This file is processed by the aic7xxx_asm utility for use in assembling···65 mvi MODE_PTR, MK_MODE(src, dst); \66 }67000000068#define RESTORE_MODE(mode) \69 if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \70 mov mode call set_mode_work_around; \···11991200/*1201 * LQ Packet In1202+ * The last LQ Packet recieved1203 */1204register LQIN {1205 address 0x020···3542 COMPLETE_DMA_SCB_HEAD {3543 size 23544 }3545+ /*3546+ * tail of list of SCBs that have3547+ * completed but need to be uploaded3548+ * to the host prior to being completed.3549+ */3550+ COMPLETE_DMA_SCB_TAIL {3551+ size 23552+ }3553+ /*3554+ * head of list of SCBs that have3555+ * been uploaded to the host, but cannot3556+ * be completed until the QFREEZE is in3557+ * full effect (i.e. no selections pending).3558+ */3559+ COMPLETE_ON_QFREEZE_HEAD {3560+ size 23561+ }3562+ /*3563+ * Counting semaphore to prevent new select-outs3564+ * The queue is frozen so long as the sequencer3565+ * and kernel freeze counts differ.3566+ */3567 QFREEZE_COUNT {3568+ size 23569+ }3570+ KERNEL_QFREEZE_COUNT {3571 size 23572 }3573 /*···3625 size 13626 }3627 /*3628+ * Kernel and sequencer offsets into the queue of3629+ * incoming target mode command descriptors. The3630+ * queue is full when the KERNEL_TQINPOS == TQINPOS.3631+ */3632+ KERNEL_TQINPOS {3633+ size 13634+ }3635+ TQINPOS { 3636+ size 13637+ }3638+ /*3639 * Base address of our shared data with the kernel driver in host3640 * memory. This includes the qoutfifo and target mode3641 * incoming command queue.···3638 */3639 QOUTFIFO_NEXT_ADDR {3640 size 4000000000003641 }3642 ARG_1 {3643 size 1···3951const SG_SIZEOF download3952const PKT_OVERRUN_BUFOFFSET download3953const SCB_TRANSFER_SIZE download3954+const CACHELINE_MASK download39553956/*3957 * BIOS SCB offsets
+188-53
drivers/scsi/aic7xxx/aic79xx.seq
···40 * $FreeBSD$41 */4243-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $"44PATCH_ARG_LIST = "struct ahd_softc *ahd"45PREFIX = "ahd_"46···68 }69 SET_MODE(M_SCSI, M_SCSI)70 test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;71- test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus;0000000000000000000000000000000000072 cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;73 /*74 * ENSELO is cleared by a SELDO, so we must test for SELDO75 * one last time.76 */77-BEGIN_CRITICAL;78 test SSTAT0, SELDO jnz select_out;79END_CRITICAL;80 call start_selection;···124 test SSTAT2, NONPACKREQ jz . + 2;125 call unexpected_nonpkt_phase_find_ctxt;126 if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {0000000127 and A, FIFO0FREE|FIFO1FREE, DFFSTAT;128 cmp A, FIFO0FREE|FIFO1FREE jne . + 3;129 and SBLKCTL, ~DIAGLEDEN|DIAGLEDON;···142 call idle_loop_cchan;143 jmp idle_loop;144145-BEGIN_CRITICAL;146idle_loop_gsfifo:147 SET_MODE(M_SCSI, M_SCSI)0148idle_loop_gsfifo_in_scsi_mode:149 test LQISTAT2, LQIGSAVAIL jz return;150 /*···193194idle_loop_service_fifos:195 SET_MODE(M_DFF0, M_DFF0)0196 test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;197 call longjmp;0198idle_loop_next_fifo:199 SET_MODE(M_DFF1, M_DFF1)0200 test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;0201return:202 ret;203···215 test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;216 test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;217 test CCSCBCTL, CCSCBDONE jz return;218-END_CRITICAL;219 /* FALLTHROUGH */220scbdma_tohost_done:221 test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;···224 * bad SCSI status (currently only for underruns), we225 * queue the SCB for normal completion. Otherwise, we226 * wait until any select-out activity has halted, and227- * then notify the host so that the transaction can be228- * dealt with.229 */230- test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host;231 and CCSCBCTL, ~(CCARREN|CCSCBEN);232 bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;000000233 bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;234 bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;235-scbdma_notify_host:236- SET_MODE(M_SCSI, M_SCSI)237- test SCSISEQ0, ENSELO jnz return;238- test SSTAT0, (SELDO|SELINGO) jnz return;239- SET_MODE(M_CCHAN, M_CCHAN)240- /*241- * Remove SCB and notify host.242- */243- and CCSCBCTL, ~(CCARREN|CCSCBEN);244- bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;245- SET_SEQINTCODE(BAD_SCB_STATUS)246- ret;247fill_qoutfifo_dmadone:248 and CCSCBCTL, ~(CCARREN|CCSCBEN);249 call qoutfifo_updated;···244 test QOFF_CTLSTA, SDSCB_ROLLOVR jz return;245 bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;246 xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;0247248qoutfifo_updated:249 /*···361 * Keep track of the SCBs we are dmaing just362 * in case the DMA fails or is aborted.363 */364- mov A, QOUTFIFO_ENTRY_VALID_TAG;365 bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2;366 mvi CCSCBCTL, CCSCBRESET;367 bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4;0368 bmov SCBPTR, COMPLETE_SCB_HEAD, 2;369fill_qoutfifo_loop:370- mov CCSCBRAM, SCBPTR;371- or CCSCBRAM, A, SCBPTR[1];0372 mov NONE, SDSCB_QOFF;373 inc INT_COALESCING_CMDCOUNT;374 add CMDS_PENDING, -1;···377 cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done;378 cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done;379 test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done;000000000000380 bmov SCBPTR, SCB_NEXT_COMPLETE, 2;381 jmp fill_qoutfifo_loop;382fill_qoutfifo_done:···404 bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;405 bmov SCBHADDR, SCB_BUSADDR, 4;406 mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb;407-END_CRITICAL;408409/*410 * Either post or fetch an SCB from host memory. The caller···420 mvi SCBHCNT, SCB_TRANSFER_SIZE;421 mov CCSCBCTL, SINDEX ret;422423-BEGIN_CRITICAL;424setjmp:425- bmov LONGJMP_ADDR, STACK, 2 ret;00000000000426setjmp_inline:427 bmov LONGJMP_ADDR, STACK, 2;428longjmp:···450set_mode_work_around:451 mvi SEQINTCTL, INTVEC1DSL;452 mov MODE_PTR, SINDEX;453- clr SEQINTCTL ret;454-455-toggle_dff_mode_work_around:456- mvi SEQINTCTL, INTVEC1DSL;457- xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);458 clr SEQINTCTL ret;459}460···544SET_SRC_MODE M_SCSI;545SET_DST_MODE M_SCSI;546select_in:000000000000000547 if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {548 /*549 * Test to ensure that the bus has not···597SET_DST_MODE M_SCSI;598select_out:599BEGIN_CRITICAL;000000000000000600 /* Clear out all SCBs that have been successfully sent. */601 if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {602 /*···1084/*1085 * We received a "command complete" message. Put the SCB on the complete1086 * queue and trigger a completion interrupt via the idle loop. Before doing1087- * so, check to see if there1088- * is a residual or the status byte is something other than STATUS_GOOD (0).1089- * In either of these conditions, we upload the SCB back to the host so it can1090- * process this information. In the case of a non zero status byte, we 1091- * additionally interrupt the kernel driver synchronously, allowing it to1092- * decide if sense should be retrieved. If the kernel driver wishes to request1093- * sense, it will fill the kernel SCB with a request sense command, requeue1094- * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting 1095- * RETURN_1 to SEND_SENSE.1096 */1097mesgin_complete:1098···1131 call queue_scb_completion;1132 jmp await_busfree;113301134freeze_queue:1135 /* Cancel any pending select-out. */1136 test SSTAT0, SELDO|SELINGO jnz . + 2;···1142 adc QFREEZE_COUNT[1], A;1143 or SEQ_FLAGS2, SELECTOUT_QFROZEN;1144 mov A, ACCUM_SAVE ret;011451146/*1147 * Complete the current FIFO's SCB if data for this same···1165 test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */1166 test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;1167complete:01168 bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;1169 bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;01170bad_status:1171 cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;1172 call freeze_queue;···1179 * it on the host.1180 */1181 bmov SCB_TAG, SCBPTR, 2;1182- bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2;0001183 bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;1184- or SCB_SGPTR, SG_STATUS_VALID ret;00000011851186/*1187 * Is it a disconnect message? Set a flag in the SCB to remind us···1237await_busfree_clrchn:1238 mvi DFFSXFRCTL, CLRCHN;1239await_busfree_not_m_dff:1240- call clear_target_state;01241 test SSTAT1,REQINIT|BUSFREE jz .;0000000001242 test SSTAT1, BUSFREE jnz idle_loop;1243 SET_SEQINTCODE(MISSED_BUSFREE)1244···1302msgin_rdptrs_get_fifo:1303 call allocate_fifo;1304 jmp mesgin_done;1305-1306-clear_target_state:1307- mvi LASTPHASE, P_BUSFREE;1308- /* clear target specific flags */1309- mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;13101311phase_lock: 1312 if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {···1394 test CCSGCTL, CCSGENACK jnz return;13951396 /*000000000000000000000000000000000000000001397 * We fetch a "cacheline aligned" and sized amount of data1398 * so we don't end up referencing a non-existant page.1399 * Cacheline aligned is in quotes because the kernel will···1445 mvi SGHCNT, SG_PREFETCH_CNT;1446 if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {1447 /*1448- * Need two instruction between "touches" of SGHADDR.1449 */1450 nop;1451 }···1795 * savepointer in the current FIFO. We do this so that1796 * a pending CTXTDONE or SAVEPTR is visible in the active1797 * FIFO. This status is the only way we can detect if we1798- * have lost the race (e.g. host paused us) and our attepts1799 * to disable the channel occurred after all REQs were1800 * already seen and acked (REQINIT never comes true).1801 */···1804 test DFCNTRL, DIRECTION jz interrupt_return;1805 and DFCNTRL, ~SCSIEN;1806snapshot_wait_data_valid:1807- test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid;1808 test SSTAT1, REQINIT jz snapshot_wait_data_valid;1809snapshot_data_valid:1810 or DFCNTRL, SCSIEN;···1971 dec SCB_FIFO_USE_COUNT;1972 test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;1973 mvi DFFSXFRCTL, CLRCHN ret;1974-END_CRITICAL;19751976/*1977 * LAST_SEG_DONE status has been seen in the current FIFO.···1979 * Check for overrun and see if we can complete this command.1980 */1981pkt_last_seg_done:1982-BEGIN_CRITICAL;1983 /*1984 * Mark transfer as completed.1985 */
···40 * $FreeBSD$41 */4243+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $"44PATCH_ARG_LIST = "struct ahd_softc *ahd"45PREFIX = "ahd_"46···68 }69 SET_MODE(M_SCSI, M_SCSI)70 test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;71+ test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list;72+ /*73+ * If the kernel has caught up with us, thaw the queue.74+ */75+ mov A, KERNEL_QFREEZE_COUNT;76+ cmp QFREEZE_COUNT, A jne check_frozen_completions;77+ mov A, KERNEL_QFREEZE_COUNT[1];78+ cmp QFREEZE_COUNT[1], A jne check_frozen_completions;79+ and SEQ_FLAGS2, ~SELECTOUT_QFROZEN;80+ jmp check_waiting_list;81+check_frozen_completions:82+ test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus;83+BEGIN_CRITICAL;84+ /*85+ * If we have completions stalled waiting for the qfreeze86+ * to take effect, move them over to the complete_scb list87+ * now that no selections are pending.88+ */89+ cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus;90+ /*91+ * Find the end of the qfreeze list. The first element has92+ * to be treated specially.93+ */94+ bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2;95+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists;96+ /*97+ * Now the normal loop.98+ */99+ bmov SCBPTR, SCB_NEXT_COMPLETE, 2;100+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1;101+join_lists:102+ bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;103+ bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2;104+ mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL;105+ jmp idle_loop_checkbus;106+check_waiting_list:107 cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;108 /*109 * ENSELO is cleared by a SELDO, so we must test for SELDO110 * one last time.111 */0112 test SSTAT0, SELDO jnz select_out;113END_CRITICAL;114 call start_selection;···90 test SSTAT2, NONPACKREQ jz . + 2;91 call unexpected_nonpkt_phase_find_ctxt;92 if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {93+ /*94+ * On Rev A. hardware, the busy LED is only95+ * turned on automaically during selections96+ * and re-selections. Make the LED status97+ * more useful by forcing it to be on so98+ * long as one of our data FIFOs is active.99+ */100 and A, FIFO0FREE|FIFO1FREE, DFFSTAT;101 cmp A, FIFO0FREE|FIFO1FREE jne . + 3;102 and SBLKCTL, ~DIAGLEDEN|DIAGLEDON;···101 call idle_loop_cchan;102 jmp idle_loop;1030104idle_loop_gsfifo:105 SET_MODE(M_SCSI, M_SCSI)106+BEGIN_CRITICAL;107idle_loop_gsfifo_in_scsi_mode:108 test LQISTAT2, LQIGSAVAIL jz return;109 /*···152153idle_loop_service_fifos:154 SET_MODE(M_DFF0, M_DFF0)155+BEGIN_CRITICAL;156 test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;157 call longjmp;158+END_CRITICAL;159idle_loop_next_fifo:160 SET_MODE(M_DFF1, M_DFF1)161+BEGIN_CRITICAL;162 test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;163+END_CRITICAL;164return:165 ret;166···170 test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;171 test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;172 test CCSCBCTL, CCSCBDONE jz return;0173 /* FALLTHROUGH */174scbdma_tohost_done:175 test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;···180 * bad SCSI status (currently only for underruns), we181 * queue the SCB for normal completion. Otherwise, we182 * wait until any select-out activity has halted, and183+ * then queue the completion.0184 */0185 and CCSCBCTL, ~(CCARREN|CCSCBEN);186 bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;187+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2;188+ mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL;189+ test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion;190+ bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2;191+ bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret;192+scbdma_queue_completion:193 bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;194 bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;000000000000195fill_qoutfifo_dmadone:196 and CCSCBCTL, ~(CCARREN|CCSCBEN);197 call qoutfifo_updated;···208 test QOFF_CTLSTA, SDSCB_ROLLOVR jz return;209 bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;210 xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;211+END_CRITICAL;212213qoutfifo_updated:214 /*···324 * Keep track of the SCBs we are dmaing just325 * in case the DMA fails or is aborted.326 */0327 bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2;328 mvi CCSCBCTL, CCSCBRESET;329 bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4;330+ mov A, QOUTFIFO_NEXT_ADDR;331 bmov SCBPTR, COMPLETE_SCB_HEAD, 2;332fill_qoutfifo_loop:333+ bmov CCSCBRAM, SCBPTR, 2;334+ mov CCSCBRAM, SCB_SGPTR[0];335+ mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG;336 mov NONE, SDSCB_QOFF;337 inc INT_COALESCING_CMDCOUNT;338 add CMDS_PENDING, -1;···339 cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done;340 cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done;341 test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done;342+ /*343+ * Don't cross an ADB or Cachline boundary when DMA'ing344+ * completion entries. In PCI mode, at least in 32/33345+ * configurations, the SCB DMA engine may lose its place346+ * in the data-stream should the target force a retry on347+ * something other than an 8byte aligned boundary. In348+ * PCI-X mode, we do this to avoid split transactions since349+ * many chipsets seem to be unable to format proper split350+ * completions to continue the data transfer.351+ */352+ add SINDEX, A, CCSCBADDR;353+ test SINDEX, CACHELINE_MASK jz fill_qoutfifo_done;354 bmov SCBPTR, SCB_NEXT_COMPLETE, 2;355 jmp fill_qoutfifo_loop;356fill_qoutfifo_done:···354 bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;355 bmov SCBHADDR, SCB_BUSADDR, 4;356 mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb;0357358/*359 * Either post or fetch an SCB from host memory. The caller···371 mvi SCBHCNT, SCB_TRANSFER_SIZE;372 mov CCSCBCTL, SINDEX ret;3730374setjmp:375+ /*376+ * At least on the A, a return in the same377+ * instruction as the bmov results in a return378+ * to the caller, not to the new address at the379+ * top of the stack. Since we want the latter380+ * (we use setjmp to register a handler from an381+ * interrupt context but not invoke that handler382+ * until we return to our idle loop), use a383+ * separate ret instruction.384+ */385+ bmov LONGJMP_ADDR, STACK, 2;386+ ret;387setjmp_inline:388 bmov LONGJMP_ADDR, STACK, 2;389longjmp:···391set_mode_work_around:392 mvi SEQINTCTL, INTVEC1DSL;393 mov MODE_PTR, SINDEX;00000394 clr SEQINTCTL ret;395}396···490SET_SRC_MODE M_SCSI;491SET_DST_MODE M_SCSI;492select_in:493+ if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {494+ /*495+ * On Rev A. hardware, the busy LED is only496+ * turned on automaically during selections497+ * and re-selections. Make the LED status498+ * more useful by forcing it to be on from499+ * the point of selection until our idle500+ * loop determines that neither of our FIFOs501+ * are busy. This handles the non-packetized502+ * case nicely as we will not return to the503+ * idle loop until the busfree at the end of504+ * each transaction.505+ */506+ or SBLKCTL, DIAGLEDEN|DIAGLEDON;507+ }508 if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {509 /*510 * Test to ensure that the bus has not···528SET_DST_MODE M_SCSI;529select_out:530BEGIN_CRITICAL;531+ if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {532+ /*533+ * On Rev A. hardware, the busy LED is only534+ * turned on automaically during selections535+ * and re-selections. Make the LED status536+ * more useful by forcing it to be on from537+ * the point of re-selection until our idle538+ * loop determines that neither of our FIFOs539+ * are busy. This handles the non-packetized540+ * case nicely as we will not return to the541+ * idle loop until the busfree at the end of542+ * each transaction.543+ */544+ or SBLKCTL, DIAGLEDEN|DIAGLEDON;545+ }546 /* Clear out all SCBs that have been successfully sent. */547 if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {548 /*···1000/*1001 * We received a "command complete" message. Put the SCB on the complete1002 * queue and trigger a completion interrupt via the idle loop. Before doing1003+ * so, check to see if there is a residual or the status byte is something1004+ * other than STATUS_GOOD (0). In either of these conditions, we upload the1005+ * SCB back to the host so it can process this information.0000001006 */1007mesgin_complete:1008···1053 call queue_scb_completion;1054 jmp await_busfree;10551056+BEGIN_CRITICAL;1057freeze_queue:1058 /* Cancel any pending select-out. */1059 test SSTAT0, SELDO|SELINGO jnz . + 2;···1063 adc QFREEZE_COUNT[1], A;1064 or SEQ_FLAGS2, SELECTOUT_QFROZEN;1065 mov A, ACCUM_SAVE ret;1066+END_CRITICAL;10671068/*1069 * Complete the current FIFO's SCB if data for this same···1085 test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */1086 test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;1087complete:1088+BEGIN_CRITICAL;1089 bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;1090 bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;1091+END_CRITICAL;1092bad_status:1093 cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;1094 call freeze_queue;···1097 * it on the host.1098 */1099 bmov SCB_TAG, SCBPTR, 2;1100+BEGIN_CRITICAL;1101+ or SCB_SGPTR, SG_STATUS_VALID;1102+ mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL;1103+ cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail;1104 bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;1105+ bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret;1106+add_dma_scb_tail:1107+ bmov REG0, SCBPTR, 2;1108+ bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2;1109+ bmov SCB_NEXT_COMPLETE, REG0, 2;1110+ bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret;1111+END_CRITICAL;11121113/*1114 * Is it a disconnect message? Set a flag in the SCB to remind us···1146await_busfree_clrchn:1147 mvi DFFSXFRCTL, CLRCHN;1148await_busfree_not_m_dff:1149+ /* clear target specific flags */1150+ mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;1151 test SSTAT1,REQINIT|BUSFREE jz .;1152+ /*1153+ * We only set BUSFREE status once either a new1154+ * phase has been detected or we are really1155+ * BUSFREE. This allows the driver to know1156+ * that we are active on the bus even though1157+ * no identified transaction exists should a1158+ * timeout occur while awaiting busfree.1159+ */1160+ mvi LASTPHASE, P_BUSFREE;1161 test SSTAT1, BUSFREE jnz idle_loop;1162 SET_SEQINTCODE(MISSED_BUSFREE)1163···1201msgin_rdptrs_get_fifo:1202 call allocate_fifo;1203 jmp mesgin_done;0000012041205phase_lock: 1206 if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {···1298 test CCSGCTL, CCSGENACK jnz return;12991300 /*1301+ * Should the other FIFO get the S/G cache first? If1302+ * both FIFOs have been allocated since we last checked1303+ * any FIFO, it is important that we service a FIFO1304+ * that is not actively on the bus first. This guarantees1305+ * that a FIFO will be freed to handle snapshot requests for1306+ * any FIFO that is still on the bus. Chips with RTI do not1307+ * perform snapshots, so don't bother with this test there.1308+ */1309+ if ((ahd->features & AHD_RTI) == 0) {1310+ /*1311+ * If we're not still receiving SCSI data,1312+ * it is safe to allocate the S/G cache to1313+ * this FIFO.1314+ */1315+ test DFCNTRL, SCSIEN jz idle_sgfetch_start;1316+1317+ /*1318+ * Switch to the other FIFO. Non-RTI chips1319+ * also have the "set mode" bug, so we must1320+ * disable interrupts during the switch.1321+ */1322+ mvi SEQINTCTL, INTVEC1DSL;1323+ xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);1324+1325+ /*1326+ * If the other FIFO needs loading, then it1327+ * must not have claimed the S/G cache yet1328+ * (SG_CACHE_AVAIL would have been cleared in1329+ * the orginal FIFO mode and we test this above).1330+ * Return to the idle loop so we can process the1331+ * FIFO not currently on the bus first.1332+ */1333+ test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay;1334+ clr SEQINTCTL ret;1335+idle_sgfetch_okay:1336+ xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);1337+ clr SEQINTCTL;1338+ }1339+1340+idle_sgfetch_start:1341+ /*1342 * We fetch a "cacheline aligned" and sized amount of data1343 * so we don't end up referencing a non-existant page.1344 * Cacheline aligned is in quotes because the kernel will···1308 mvi SGHCNT, SG_PREFETCH_CNT;1309 if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {1310 /*1311+ * Need two instructions between "touches" of SGHADDR.1312 */1313 nop;1314 }···1658 * savepointer in the current FIFO. We do this so that1659 * a pending CTXTDONE or SAVEPTR is visible in the active1660 * FIFO. This status is the only way we can detect if we1661+ * have lost the race (e.g. host paused us) and our attempts1662 * to disable the channel occurred after all REQs were1663 * already seen and acked (REQINIT never comes true).1664 */···1667 test DFCNTRL, DIRECTION jz interrupt_return;1668 and DFCNTRL, ~SCSIEN;1669snapshot_wait_data_valid:1670+ test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return;1671 test SSTAT1, REQINIT jz snapshot_wait_data_valid;1672snapshot_data_valid:1673 or DFCNTRL, SCSIEN;···1834 dec SCB_FIFO_USE_COUNT;1835 test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;1836 mvi DFFSXFRCTL, CLRCHN ret;018371838/*1839 * LAST_SEG_DONE status has been seen in the current FIFO.···1843 * Check for overrun and see if we can complete this command.1844 */1845pkt_last_seg_done:01846 /*1847 * Mark transfer as completed.1848 */
+418-365
drivers/scsi/aic7xxx/aic79xx_core.c
···37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE38 * POSSIBILITY OF SUCH DAMAGES.39 *40- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $41- *42- * $FreeBSD$43 */4445#ifdef __linux__···330 ahd_outb(ahd, SCSISEQ1,331 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));332 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);00000000333 ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);334 ahd_unpause(ahd);335}···379 saved_modes = ahd_save_modes(ahd);380381 /*382- * Complete any SCBs that just finished being383- * DMA'ed into the qoutfifo.384- */385- ahd_run_qoutfifo(ahd);386-387- /*388- * Flush the good status FIFO for compelted packetized commands.389 */390 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);391 saved_scbptr = ahd_get_scbptr(ahd);···387 u_int fifo_mode;388 u_int i;389390- scbid = (ahd_inb(ahd, GSFIFO+1) << 8)391- | ahd_inb(ahd, GSFIFO);392 scb = ahd_lookup_scb(ahd, scbid);393 if (scb == NULL) {394 printf("%s: Warning - GSFIFO SCB %d invalid\n",···400 * the host before completing the command.401 */402 fifo_mode = 0;0403 for (i = 0; i < 2; i++) {404 /* Toggle to the other mode. */405 fifo_mode ^= 1;406 ahd_set_modes(ahd, fifo_mode, fifo_mode);0407 if (ahd_scb_active_in_fifo(ahd, scb) == 0)408 continue;409410 ahd_run_data_fifo(ahd, scb);411412 /*413- * Clearing this transaction in this FIFO may414- * cause a CFG4DATA for this same transaction415- * to assert in the other FIFO. Make sure we416- * loop one more time and check the other FIFO.00000000417 */418- i = 0;0419 }420 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);421 ahd_set_scbptr(ahd, scbid);···439 /*440 * The transfer completed with a residual.441 * Place this SCB on the complete DMA list442- * so that we Update our in-core copy of the443 * SCB before completing the command.444 */445 ahd_outb(ahd, SCB_SCSI_STATUS, 0);446 ahd_outb(ahd, SCB_SGPTR,447 ahd_inb_scbram(ahd, SCB_SGPTR)448 | SG_STATUS_VALID);449- ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb));0450 comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);451- ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head);452- if (SCBID_IS_NULL(comp_head))453- ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD,454- SCB_GET_TAG(scb));00000000455 } else456 ahd_complete_scb(ahd, scb);457 }···484 break;485 ahd_delay(200);486 }487- if ((ccscbctl & CCSCBDIR) != 0)0000000488 ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));000000489490 saved_scbptr = ahd_get_scbptr(ahd);491 /*···526 scbid = next_scbid;527 }528 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);000000000000000000529530 scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);531 while (!SCBID_IS_NULL(scbid)) {···608{609 u_int seqintsrc;610611- while (1) {612- seqintsrc = ahd_inb(ahd, SEQINTSRC);613- if ((seqintsrc & CFG4DATA) != 0) {614- uint32_t datacnt;615- uint32_t sgptr;616617- /*618- * Clear full residual flag.619- */620- sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;621- ahd_outb(ahd, SCB_SGPTR, sgptr);622623- /*624- * Load datacnt and address.625- */626- datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);627- if ((datacnt & AHD_DMA_LAST_SEG) != 0) {628- sgptr |= LAST_SEG;629- ahd_outb(ahd, SG_STATE, 0);630- } else631- ahd_outb(ahd, SG_STATE, LOADING_NEEDED);632- ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));633- ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);634- ahd_outb(ahd, SG_CACHE_PRE, sgptr);635- ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);636-637- /*638- * Initialize Residual Fields.639- */640- ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);641- ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);642-643- /*644- * Mark the SCB as having a FIFO in use.645- */646- ahd_outb(ahd, SCB_FIFO_USE_COUNT,647- ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);648-649- /*650- * Install a "fake" handler for this FIFO.651- */652- ahd_outw(ahd, LONGJMP_ADDR, 0);653-654- /*655- * Notify the hardware that we have satisfied656- * this sequencer interrupt.657- */658- ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);659- } else if ((seqintsrc & SAVEPTRS) != 0) {660- uint32_t sgptr;661- uint32_t resid;662-663- if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {664- /*665- * Snapshot Save Pointers. Clear666- * the snapshot and continue.667- */668- ahd_outb(ahd, DFFSXFRCTL, CLRCHN);669- continue;670- }671-672- /*673- * Disable S/G fetch so the DMA engine674- * is available to future users.675- */676- if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)677- ahd_outb(ahd, CCSGCTL, 0);678 ahd_outb(ahd, SG_STATE, 0);000000679680- /*681- * Flush the data FIFO. Strickly only682- * necessary for Rev A parts.683- */684- ahd_outb(ahd, DFCNTRL,685- ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);686687- /*688- * Calculate residual.689- */690- sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);691- resid = ahd_inl(ahd, SHCNT);692- resid |=693- ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;694- ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);695- if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {696- /*697- * Must back up to the correct S/G element.698- * Typically this just means resetting our699- * low byte to the offset in the SG_CACHE,700- * but if we wrapped, we have to correct701- * the other bytes of the sgptr too.702- */703- if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0704- && (sgptr & 0x80) == 0)705- sgptr -= 0x100;706- sgptr &= ~0xFF;707- sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)708- & SG_ADDR_MASK;709- ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);710- ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);711- } else if ((resid & AHD_SG_LEN_MASK) == 0) {712- ahd_outb(ahd, SCB_RESIDUAL_SGPTR,713- sgptr | SG_LIST_NULL);714- }715- /*716- * Save Pointers.717- */718- ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));719- ahd_outl(ahd, SCB_DATACNT, resid);720- ahd_outl(ahd, SCB_SGPTR, sgptr);721- ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);722- ahd_outb(ahd, SEQIMODE,723- ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);724- /*725- * If the data is to the SCSI bus, we are726- * done, otherwise wait for FIFOEMP.727- */728- if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)729- break;730- } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {731- uint32_t sgptr;732- uint64_t data_addr;733- uint32_t data_len;734- u_int dfcntrl;735736- /*737- * Disable S/G fetch so the DMA engine738- * is available to future users.739- */740- if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {741- ahd_outb(ahd, CCSGCTL, 0);742- ahd_outb(ahd, SG_STATE, LOADING_NEEDED);743- }7440000000000745 /*746- * Wait for the DMA engine to notice that the747- * host transfer is enabled and that there is748- * space in the S/G FIFO for new segments before749- * loading more segments.750 */751- if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0)752- continue;753- if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0)754- continue;0000000000000000000000000000000000000000000000000000000000000000000000000000000755756 /*757 * Determine the offset of the next S/G···794 * Advertise the segment to the hardware.795 */796 dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;797- if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) {798 /*799 * Use SCSIENWRDIS so that SCSIEN800 * is never modified by this···803 dfcntrl |= SCSIENWRDIS;804 }805 ahd_outb(ahd, DFCNTRL, dfcntrl);806- } else if ((ahd_inb(ahd, SG_CACHE_SHADOW)807- & LAST_SEG_DONE) != 0) {808-809- /*810- * Transfer completed to the end of SG list811- * and has flushed to the host.812- */813- ahd_outb(ahd, SCB_SGPTR,814- ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);815- break;816- } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {817- break;818 }819- ahd_delay(200);0000000000000000000820 }821- /*822- * Clear any handler for this FIFO, decrement823- * the FIFO use count for the SCB, and release824- * the FIFO.825- */826- ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);827- ahd_outb(ahd, SCB_FIFO_USE_COUNT,828- ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);829- ahd_outb(ahd, DFFSXFRCTL, CLRCHN);830}8310000000000832void833ahd_run_qoutfifo(struct ahd_softc *ahd)834{0835 struct scb *scb;836 u_int scb_index;837···848 panic("ahd_run_qoutfifo recursion");849 ahd->flags |= AHD_RUNNING_QOUTFIFO;850 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);851- while ((ahd->qoutfifo[ahd->qoutfifonext]852- & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) {853854- scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext]855- & ~QOUTFIFO_ENTRY_VALID_LE);00856 scb = ahd_lookup_scb(ahd, scb_index);857 if (scb == NULL) {858 printf("%s: WARNING no command for scb %d "···862 ahd_name(ahd), scb_index,863 ahd->qoutfifonext);864 ahd_dump_card_state(ahd);865- } else866- ahd_complete_scb(ahd, scb);000867868 ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);869 if (ahd->qoutfifonext == 0)870- ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE;871 }872 ahd->flags &= ~AHD_RUNNING_QOUTFIFO;873}···936 ahd_name(ahd), seqintcode);937#endif938 switch (seqintcode) {939- case BAD_SCB_STATUS:940- {941- struct scb *scb;942- u_int scbid;943- int cmds_pending;944-945- scbid = ahd_get_scbptr(ahd);946- scb = ahd_lookup_scb(ahd, scbid);947- if (scb != NULL) {948- ahd_complete_scb(ahd, scb);949- } else {950- printf("%s: WARNING no command for scb %d "951- "(bad status)\n", ahd_name(ahd), scbid);952- ahd_dump_card_state(ahd);953- }954- cmds_pending = ahd_inw(ahd, CMDS_PENDING);955- if (cmds_pending > 0)956- ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);957- break;958- }959 case ENTERING_NONPACK:960 {961 struct scb *scb;···1100 ahd_outb(ahd, SAVED_LUN, 0);1101 ahd_outb(ahd, SEQ_FLAGS, 0);1102 ahd_assert_atn(ahd);1103- scb->flags &= ~(SCB_PACKETIZED);1104 scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;1105 ahd_freeze_devq(ahd, scb);1106 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);···1543 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)1544 scb = NULL;15451546- /* Make sure the sequencer is in a safe location. */1547- ahd_clear_critical_section(ahd);1548-1549 if ((status0 & IOERR) != 0) {1550 u_int now_lvd;1551···1558 ahd_setup_iocell_workaround(ahd);1559 ahd_unpause(ahd);1560 } else if ((status0 & OVERRUN) != 0) {01561 printf("%s: SCSI offset overrun detected. Resetting bus.\n",1562 ahd_name(ahd));1563 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);1564 } else if ((status & SCSIRSTI) != 0) {01565 printf("%s: Someone reset channel A\n", ahd_name(ahd));1566 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);1567 } else if ((status & SCSIPERR) != 0) {00001568 ahd_handle_transmission_error(ahd);1569 } else if (lqostat0 != 0) {01570 printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);1571 ahd_outb(ahd, CLRLQOINT0, lqostat0);1572- if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {1573 ahd_outb(ahd, CLRLQOINT1, 0);1574- }1575 } else if ((status & SELTO) != 0) {1576 u_int scbid;15771578 /* Stop the selection */1579 ahd_outb(ahd, SCSISEQ0, 0);00015801581 /* No more pending messages */1582 ahd_clear_msg_state(ahd);···1619 scbid);1620 }1621#endif1622- /*1623- * Force a renegotiation with this target just in1624- * case the cable was pulled and will later be1625- * re-attached. The target may forget its negotiation1626- * settings with us should it attempt to reselect1627- * during the interruption. The target will not issue1628- * a unit attention in this case, so we must always1629- * renegotiate.1630- */1631 ahd_scb_devinfo(ahd, &devinfo, scb);1632- ahd_force_renegotiation(ahd, &devinfo);1633 ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);1634 ahd_freeze_devq(ahd, scb);0000000000001635 }1636 ahd_outb(ahd, CLRINT, CLRSCSIINT);1637 ahd_iocell_first_selection(ahd);1638 ahd_unpause(ahd);1639 } else if ((status0 & (SELDI|SELDO)) != 0) {01640 ahd_iocell_first_selection(ahd);1641 ahd_unpause(ahd);1642 } else if (status3 != 0) {···1647 ahd_name(ahd), status3);1648 ahd_outb(ahd, CLRSINT3, status3);1649 } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {00001650 ahd_handle_lqiphase_error(ahd, lqistat1);1651 } else if ((lqistat1 & LQICRCI_NLQ) != 0) {1652 /*···1674 * go about selecting the target while we handle the event.1675 */1676 ahd_outb(ahd, SCSISEQ0, 0);00016771678 /*1679 * Determine what we were up to at the time of···1715 clear_fifo = 0;1716 packetized = (lqostat1 & LQOBUSFREE) != 0;1717 if (!packetized1718- && ahd_inb(ahd, LASTPHASE) == P_BUSFREE)0000000001719 packetized = 1;1720 break;1721 }···2375 "PRGMCNT == 0x%x\n",2376 ahd_lookup_phase_entry(lastphase)->phasemsg,2377 aborted,2378- ahd_inb(ahd, PRGMCNT)2379- | (ahd_inb(ahd, PRGMCNT+1) << 8));2380 ahd_dump_card_state(ahd);2381 }2382 /* Always restart the sequencer. */···2538 u_int i;25392540 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);2541- seqaddr = ahd_inb(ahd, CURADDR)2542- | (ahd_inb(ahd, CURADDR+1) << 8);25432544 cs = ahd->critical_sections;2545 for (i = 0; i < ahd->num_critical_sections; i++, cs++) {···3259 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;32603261 if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 03262- && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) {03263 /*3264 * Slow down our CRC interval to be3265- * compatible with devices that can't3266- * handle a CRC at full speed.03267 */3268 con_opts |= ENSLOWCRC;0000000003269 }3270 }3271···3366 * Force the sequencer to reinitialize the selection for3367 * the command at the head of the execution queue if it3368 * has already been setup. The negotiation changes may3369- * effect whether we select-out with ATN.003370 */3371 saved_modes = ahd_save_modes(ahd);3372 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);3373- ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);003374 saved_scbptr = ahd_get_scbptr(ahd);3375 /* Ensure that the hscbs down on the card match the new information */3376 for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {···4987 * Determine initial values for data_addr and data_cnt4988 * for resuming the data phase.4989 */4990- sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24)4991- | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16)4992- | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8)4993- | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);4994 sgptr &= SG_PTR_MASK;49954996 resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)···5005 dataptr = ahd_le64toh(sg->addr)5006 + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)5007 - resid;5008- ahd_outb(ahd, HADDR + 7, dataptr >> 56);5009- ahd_outb(ahd, HADDR + 6, dataptr >> 48);5010- ahd_outb(ahd, HADDR + 5, dataptr >> 40);5011- ahd_outb(ahd, HADDR + 4, dataptr >> 32);5012 } else {5013 struct ahd_dma_seg *sg;5014···5020 ahd_outb(ahd, HADDR + 4,5021 (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);5022 }5023- ahd_outb(ahd, HADDR + 3, dataptr >> 24);5024- ahd_outb(ahd, HADDR + 2, dataptr >> 16);5025- ahd_outb(ahd, HADDR + 1, dataptr >> 8);5026- ahd_outb(ahd, HADDR, dataptr);5027 ahd_outb(ahd, HCNT + 2, resid >> 16);5028 ahd_outb(ahd, HCNT + 1, resid >> 8);5029 ahd_outb(ahd, HCNT, resid);···5080 ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,5081 AHD_TRANS_CUR, /*paused*/TRUE);5082 ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,5083- /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE);050845085- ahd_send_async(ahd, devinfo->channel, devinfo->target,5086- lun, AC_SENT_BDR, NULL);050875088- if (message != NULL5089- && (verbose_level <= bootverbose))5090 printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),5091 message, devinfo->channel, devinfo->target, found);5092}···5273 /* FALLTHROUGH */5274 case 4:5275 ahd_dmamap_unload(ahd, ahd->shared_data_dmat,5276- ahd->shared_data_dmamap);5277 /* FALLTHROUGH */5278 case 3:5279 ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,5280- ahd->shared_data_dmamap);5281 ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,5282- ahd->shared_data_dmamap);5283 /* FALLTHROUGH */5284 case 2:5285 ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);···6045 newcount = MIN(scb_data->sense_left, scb_data->scbs_left);6046 newcount = MIN(newcount, scb_data->sgs_left);6047 newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));6048- scb_data->sense_left -= newcount;6049- scb_data->scbs_left -= newcount;6050- scb_data->sgs_left -= newcount;6051 for (i = 0; i < newcount; i++) {6052- u_int col_tag;6053-6054 struct scb_platform_data *pdata;06055#ifndef __linux__6056 int error;6057#endif06058 next_scb = (struct scb *)malloc(sizeof(*next_scb),6059 M_DEVBUF, M_NOWAIT);6060 if (next_scb == NULL)···6108 sense_data += AHD_SENSE_BUFSIZE;6109 sense_busaddr += AHD_SENSE_BUFSIZE;6110 scb_data->numscbs++;0006111 }6112}6113···6158int6159ahd_init(struct ahd_softc *ahd)6160{6161- uint8_t *base_vaddr;6162 uint8_t *next_vaddr;6163 dma_addr_t next_baddr;6164 size_t driver_data_size;···6225 * for the target mode role, we must additionally provide space for6226 * the incoming target command fifo.6227 */6228- driver_data_size = AHD_SCB_MAX * sizeof(uint16_t)6229 + sizeof(struct hardware_scb);6230 if ((ahd->features & AHD_TARGETMODE) != 0)6231 driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);···62476248 /* Allocation of driver data */6249 if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,6250- (void **)&base_vaddr,6251- BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) {06252 return (ENOMEM);6253 }62546255 ahd->init_level++;62566257 /* And permanently map it in */6258- ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,6259- base_vaddr, driver_data_size, ahd_dmamap_cb,6260- &ahd->shared_data_busaddr, /*flags*/0);6261- ahd->qoutfifo = (uint16_t *)base_vaddr;06262 next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];6263- next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t);06264 if ((ahd->features & AHD_TARGETMODE) != 0) {6265 ahd->targetcmds = (struct target_cmd *)next_vaddr;6266 next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);···6284 * specially from the DMA safe memory chunk used for the QOUTFIFO.6285 */6286 ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;06287 ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);62886289 ahd->init_level++;···65906591 /* All of our queues are empty */6592 ahd->qoutfifonext = 0;6593- ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE;6594- ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8);6595 for (i = 0; i < AHD_QOUT_SIZE; i++)6596- ahd->qoutfifo[i] = 0;6597 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);65986599 ahd->qinfifonext = 0;···6626 ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);6627 ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);6628 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);0066296630 /*6631 * The Freeze Count is 0.6632 */06633 ahd_outw(ahd, QFREEZE_COUNT, 0);066346635 /*6636 * Tell the sequencer where it can find our arrays in memory.6637 */6638- busaddr = ahd->shared_data_busaddr;6639- ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF);6640- ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF);6641- ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF);6642- ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF);6643- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF);6644- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF);6645- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF);6646- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF);66476648 /*6649 * Setup the allowed SCSI Sequences based on operational mode.···6690 * Tell the sequencer which SCB will be the next one it receives.6691 */6692 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);6693- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);6694- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);6695- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);6696- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);66976698 /*6699 * Default to coalescing disabled.···6994{6995 u_int intstat;6996 u_int maxloops;6997- u_int qfreeze_cnt;69986999 maxloops = 1000;7000 ahd->flags |= AHD_ALL_INTERRUPTS;7001 ahd_pause(ahd);7002 /*7003- * Increment the QFreeze Count so that the sequencer7004- * will not start new selections. We do this only7005 * until we are safely paused without further selections7006 * pending.7007 */7008- ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1);07009 ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);7010 do {7011- struct scb *waiting_scb;70127013 ahd_unpause(ahd);0000007014 ahd_intr(ahd);7015 ahd_pause(ahd);7016- ahd_clear_critical_section(ahd);7017 intstat = ahd_inb(ahd, INTSTAT);7018- ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);7019- if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)7020- ahd_outb(ahd, SCSISEQ0,7021- ahd_inb(ahd, SCSISEQ0) & ~ENSELO);7022- /*7023- * In the non-packetized case, the sequencer (for Rev A),7024- * relies on ENSELO remaining set after SELDO. The hardware7025- * auto-clears ENSELO in the packetized case.7026- */7027- waiting_scb = ahd_lookup_scb(ahd,7028- ahd_inw(ahd, WAITING_TID_HEAD));7029- if (waiting_scb != NULL7030- && (waiting_scb->flags & SCB_PACKETIZED) == 07031- && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)7032- ahd_outb(ahd, SCSISEQ0,7033- ahd_inb(ahd, SCSISEQ0) | ENSELO);7034 } while (--maxloops7035 && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)7036 && ((intstat & INT_PEND) != 0···7032 printf("Infinite interrupt loop, INTSTAT = %x",7033 ahd_inb(ahd, INTSTAT));7034 }7035- qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);7036- if (qfreeze_cnt == 0) {7037- printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n",7038- ahd_name(ahd));7039- } else {7040- qfreeze_cnt--;7041- }7042- ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);7043- if (qfreeze_cnt == 0)7044- ahd_outb(ahd, SEQ_FLAGS2,7045- ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);70467047 ahd_flush_qoutfifo(ahd);7048···7205 uint32_t busaddr;72067207 busaddr = ahd_le32toh(scb->hscb->hscb_busaddr);7208- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);7209- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);7210- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);7211- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);7212 } else {7213 prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;7214 ahd_sync_scb(ahd, prev_scb, ···7312 */7313 ahd->qinfifonext = qinstart;7314 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);7315- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);7316- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);7317- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);7318- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);73197320 while (qinpos != qintail) {7321 scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);···7374 * appropriate, traverse the SCBs of each "their id"7375 * looking for matches.7376 */07377 savedscbptr = ahd_get_scbptr(ahd);7378 tid_next = ahd_inw(ahd, WAITING_TID_HEAD);7379 tid_prev = SCB_LIST_NULL;···7444 u_int prev;7445 int found;74467447- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);7448 found = 0;7449 prev = SCB_LIST_NULL;7450 next = *list_head;···7511ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,7512 u_int tid_cur, u_int tid_next)7513{7514- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);75157516 if (SCBID_IS_NULL(tid_cur)) {7517···7551{7552 u_int tail_offset;75537554- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);7555 if (!SCBID_IS_NULL(prev)) {7556 ahd_set_scbptr(ahd, prev);7557 ahd_outw(ahd, SCB_NEXT, next);···7784 */7785 ahd_clear_msg_state(ahd);7786 ahd_outb(ahd, SIMODE1,7787- ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE));77887789 if (initiate_reset)7790 ahd_reset_current_bus(ahd);···7955void7956ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)7957{7958- struct hardware_scb *hscb;7959- u_int qfreeze_cnt;79607961 /*7962 * The sequencer freezes its select-out queue7963 * anytime a SCSI status error occurs. We must7964- * handle the error and decrement the QFREEZE count7965- * to allow the sequencer to continue.0007966 */7967 hscb = scb->hscb; 000000079687969 /* Freeze the queue until the client sees the error. */7970 ahd_freeze_devq(ahd, scb);7971 ahd_freeze_scb(scb);7972- qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);7973- if (qfreeze_cnt == 0) {7974- printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd));7975- } else {7976- qfreeze_cnt--;7977- ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);7978- }7979- if (qfreeze_cnt == 0)7980- ahd_outb(ahd, SEQ_FLAGS2,7981- ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);79827983 /* Don't want to clobber the original sense code */7984 if ((scb->flags & SCB_SENSE) != 0) {···8367 max_prog = 2048;83688369 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);8370- ahd_outb(ahd, PRGMCNT, 0);8371- ahd_outb(ahd, PRGMCNT+1, 0);8372 for (i = 0; i < max_prog; i++) {8373 uint8_t ins_bytes[4];8374···8396 u_int sg_prefetch_cnt_limit;8397 u_int sg_prefetch_align;8398 u_int sg_size;08399 uint8_t download_consts[DOWNLOAD_CONST_COUNT];84008401 if (bootverbose)8402 printf("%s: Downloading Sequencer Program...",8403 ahd_name(ahd));84048405-#if DOWNLOAD_CONST_COUNT != 78406#error "Download Const Mismatch"8407#endif8408 /*···8439 /* Round down to the nearest power of 2. */8440 while (powerof2(sg_prefetch_align) == 0)8441 sg_prefetch_align--;0008442 /*8443 * If the cacheline boundary is greater than half our prefetch RAM8444 * we risk not being able to fetch even a single complete S/G···8482 download_consts[PKT_OVERRUN_BUFOFFSET] =8483 (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;8484 download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;08485 cur_patch = patches;8486 downloaded = 0;8487 skip_addr = 0;8488 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);8489- ahd_outb(ahd, PRGMCNT, 0);8490- ahd_outb(ahd, PRGMCNT+1, 0);84918492 for (i = 0; i < sizeof(seqprog)/4; i++) {8493 if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {···8780 printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"8781 "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",8782 ahd_name(ahd), 8783- ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8),8784 ahd_build_mode_state(ahd, ahd->saved_src_mode,8785 ahd->saved_dst_mode));8786 if (paused)···88898890 printf("Sequencer DMA-Up and Complete list: ");8891 scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);0000000008892 i = 0;8893 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {8894 ahd_set_scbptr(ahd, scb_index);···9139{9140 int cnt;91419142- cnt = 20;9143 while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)9144 ahd_delay(5);9145···9485 if ((ahd->features & AHD_MULTI_TID) != 0) {9486 u_int targid_mask;94879488- targid_mask = ahd_inb(ahd, TARGID)9489- | (ahd_inb(ahd, TARGID + 1) << 8);9490-9491 targid_mask |= target_mask;9492- ahd_outb(ahd, TARGID, targid_mask);9493- ahd_outb(ahd, TARGID+1, (targid_mask >> 8));9494-9495 ahd_update_scsiid(ahd, targid_mask);9496 } else {9497 u_int our_id;···9601 if (ahd->features & AHD_MULTI_TID) {9602 u_int targid_mask;96039604- targid_mask = ahd_inb(ahd, TARGID)9605- | (ahd_inb(ahd, TARGID + 1)9606- << 8);9607-9608 targid_mask &= ~target_mask;9609- ahd_outb(ahd, TARGID, targid_mask);9610- ahd_outb(ahd, TARGID+1,9611- (targid_mask >> 8));9612 ahd_update_scsiid(ahd, targid_mask);9613 }9614 }···97049705 cmd->cmd_valid = 0;9706 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,9707- ahd->shared_data_dmamap,9708 ahd_targetcmd_offset(ahd, ahd->tqinfifonext),9709 sizeof(struct target_cmd),9710 BUS_DMASYNC_PREREAD);
···37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE38 * POSSIBILITY OF SUCH DAMAGES.39 *40+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $0041 */4243#ifdef __linux__···332 ahd_outb(ahd, SCSISEQ1,333 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));334 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);335+336+ /*337+ * Clear any pending sequencer interrupt. It is no338+ * longer relevant since we're resetting the Program339+ * Counter.340+ */341+ ahd_outb(ahd, CLRINT, CLRSEQINT);342+343 ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);344 ahd_unpause(ahd);345}···373 saved_modes = ahd_save_modes(ahd);374375 /*376+ * Flush the good status FIFO for completed packetized commands.000000377 */378 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);379 saved_scbptr = ahd_get_scbptr(ahd);···387 u_int fifo_mode;388 u_int i;389390+ scbid = ahd_inw(ahd, GSFIFO);0391 scb = ahd_lookup_scb(ahd, scbid);392 if (scb == NULL) {393 printf("%s: Warning - GSFIFO SCB %d invalid\n",···401 * the host before completing the command.402 */403 fifo_mode = 0;404+rescan_fifos:405 for (i = 0; i < 2; i++) {406 /* Toggle to the other mode. */407 fifo_mode ^= 1;408 ahd_set_modes(ahd, fifo_mode, fifo_mode);409+410 if (ahd_scb_active_in_fifo(ahd, scb) == 0)411 continue;412413 ahd_run_data_fifo(ahd, scb);414415 /*416+ * Running this FIFO may cause a CFG4DATA for417+ * this same transaction to assert in the other418+ * FIFO or a new snapshot SAVEPTRS interrupt419+ * in this FIFO. Even running a FIFO may not420+ * clear the transaction if we are still waiting421+ * for data to drain to the host. We must loop422+ * until the transaction is not active in either423+ * FIFO just to be sure. Reset our loop counter424+ * so we will visit both FIFOs again before425+ * declaring this transaction finished. We426+ * also delay a bit so that status has a chance427+ * to change before we look at this FIFO again.428 */429+ ahd_delay(200);430+ goto rescan_fifos;431 }432 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);433 ahd_set_scbptr(ahd, scbid);···429 /*430 * The transfer completed with a residual.431 * Place this SCB on the complete DMA list432+ * so that we update our in-core copy of the433 * SCB before completing the command.434 */435 ahd_outb(ahd, SCB_SCSI_STATUS, 0);436 ahd_outb(ahd, SCB_SGPTR,437 ahd_inb_scbram(ahd, SCB_SGPTR)438 | SG_STATUS_VALID);439+ ahd_outw(ahd, SCB_TAG, scbid);440+ ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);441 comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);442+ if (SCBID_IS_NULL(comp_head)) {443+ ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);444+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);445+ } else {446+ u_int tail;447+448+ tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);449+ ahd_set_scbptr(ahd, tail);450+ ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);451+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);452+ ahd_set_scbptr(ahd, scbid);453+ }454 } else455 ahd_complete_scb(ahd, scb);456 }···465 break;466 ahd_delay(200);467 }468+ /*469+ * We leave the sequencer to cleanup in the case of DMA's to470+ * update the qoutfifo. In all other cases (DMA's to the471+ * chip or a push of an SCB from the COMPLETE_DMA_SCB list),472+ * we disable the DMA engine so that the sequencer will not473+ * attempt to handle the DMA completion.474+ */475+ if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)476 ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));477+478+ /*479+ * Complete any SCBs that just finished480+ * being DMA'ed into the qoutfifo.481+ */482+ ahd_run_qoutfifo(ahd);483484 saved_scbptr = ahd_get_scbptr(ahd);485 /*···494 scbid = next_scbid;495 }496 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);497+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);498+499+ scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);500+ while (!SCBID_IS_NULL(scbid)) {501+502+ ahd_set_scbptr(ahd, scbid);503+ next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);504+ scb = ahd_lookup_scb(ahd, scbid);505+ if (scb == NULL) {506+ printf("%s: Warning - Complete Qfrz SCB %d invalid\n",507+ ahd_name(ahd), scbid);508+ continue;509+ }510+511+ ahd_complete_scb(ahd, scb);512+ scbid = next_scbid;513+ }514+ ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);515516 scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);517 while (!SCBID_IS_NULL(scbid)) {···558{559 u_int seqintsrc;560561+ seqintsrc = ahd_inb(ahd, SEQINTSRC);562+ if ((seqintsrc & CFG4DATA) != 0) {563+ uint32_t datacnt;564+ uint32_t sgptr;0565566+ /*567+ * Clear full residual flag.568+ */569+ sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;570+ ahd_outb(ahd, SCB_SGPTR, sgptr);571572+ /*573+ * Load datacnt and address.574+ */575+ datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);576+ if ((datacnt & AHD_DMA_LAST_SEG) != 0) {577+ sgptr |= LAST_SEG;0000000000000000000000000000000000000000000000000578 ahd_outb(ahd, SG_STATE, 0);579+ } else580+ ahd_outb(ahd, SG_STATE, LOADING_NEEDED);581+ ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));582+ ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);583+ ahd_outb(ahd, SG_CACHE_PRE, sgptr);584+ ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);585586+ /*587+ * Initialize Residual Fields.588+ */589+ ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);590+ ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);0591592+ /*593+ * Mark the SCB as having a FIFO in use.594+ */595+ ahd_outb(ahd, SCB_FIFO_USE_COUNT,596+ ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);0000000000000000000000000000000000000000000597598+ /*599+ * Install a "fake" handler for this FIFO.600+ */601+ ahd_outw(ahd, LONGJMP_ADDR, 0);0000602603+ /*604+ * Notify the hardware that we have satisfied605+ * this sequencer interrupt.606+ */607+ ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);608+ } else if ((seqintsrc & SAVEPTRS) != 0) {609+ uint32_t sgptr;610+ uint32_t resid;611+612+ if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {613 /*614+ * Snapshot Save Pointers. All that615+ * is necessary to clear the snapshot616+ * is a CLRCHN.0617 */618+ goto clrchn;619+ }620+621+ /*622+ * Disable S/G fetch so the DMA engine623+ * is available to future users.624+ */625+ if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)626+ ahd_outb(ahd, CCSGCTL, 0);627+ ahd_outb(ahd, SG_STATE, 0);628+629+ /*630+ * Flush the data FIFO. Strickly only631+ * necessary for Rev A parts.632+ */633+ ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);634+635+ /*636+ * Calculate residual.637+ */638+ sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);639+ resid = ahd_inl(ahd, SHCNT);640+ resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;641+ ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);642+ if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {643+ /*644+ * Must back up to the correct S/G element.645+ * Typically this just means resetting our646+ * low byte to the offset in the SG_CACHE,647+ * but if we wrapped, we have to correct648+ * the other bytes of the sgptr too.649+ */650+ if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0651+ && (sgptr & 0x80) == 0)652+ sgptr -= 0x100;653+ sgptr &= ~0xFF;654+ sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)655+ & SG_ADDR_MASK;656+ ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);657+ ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);658+ } else if ((resid & AHD_SG_LEN_MASK) == 0) {659+ ahd_outb(ahd, SCB_RESIDUAL_SGPTR,660+ sgptr | SG_LIST_NULL);661+ }662+ /*663+ * Save Pointers.664+ */665+ ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));666+ ahd_outl(ahd, SCB_DATACNT, resid);667+ ahd_outl(ahd, SCB_SGPTR, sgptr);668+ ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);669+ ahd_outb(ahd, SEQIMODE,670+ ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);671+ /*672+ * If the data is to the SCSI bus, we are673+ * done, otherwise wait for FIFOEMP.674+ */675+ if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)676+ goto clrchn;677+ } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {678+ uint32_t sgptr;679+ uint64_t data_addr;680+ uint32_t data_len;681+ u_int dfcntrl;682+683+ /*684+ * Disable S/G fetch so the DMA engine685+ * is available to future users. We won't686+ * be using the DMA engine to load segments.687+ */688+ if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {689+ ahd_outb(ahd, CCSGCTL, 0);690+ ahd_outb(ahd, SG_STATE, LOADING_NEEDED);691+ }692+693+ /*694+ * Wait for the DMA engine to notice that the695+ * host transfer is enabled and that there is696+ * space in the S/G FIFO for new segments before697+ * loading more segments.698+ */699+ if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0700+ && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {701702 /*703 * Determine the offset of the next S/G···748 * Advertise the segment to the hardware.749 */750 dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;751+ if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {752 /*753 * Use SCSIENWRDIS so that SCSIEN754 * is never modified by this···757 dfcntrl |= SCSIENWRDIS;758 }759 ahd_outb(ahd, DFCNTRL, dfcntrl);000000000000760 }761+ } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {762+763+ /*764+ * Transfer completed to the end of SG list765+ * and has flushed to the host.766+ */767+ ahd_outb(ahd, SCB_SGPTR,768+ ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);769+ goto clrchn;770+ } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {771+clrchn:772+ /*773+ * Clear any handler for this FIFO, decrement774+ * the FIFO use count for the SCB, and release775+ * the FIFO.776+ */777+ ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);778+ ahd_outb(ahd, SCB_FIFO_USE_COUNT,779+ ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);780+ ahd_outb(ahd, DFFSXFRCTL, CLRCHN);781 }000000000782}783784+/*785+ * Look for entries in the QoutFIFO that have completed.786+ * The valid_tag completion field indicates the validity787+ * of the entry - the valid value toggles each time through788+ * the queue. We use the sg_status field in the completion789+ * entry to avoid referencing the hscb if the completion790+ * occurred with no errors and no residual. sg_status is791+ * a copy of the first byte (little endian) of the sgptr792+ * hscb field.793+ */794void795ahd_run_qoutfifo(struct ahd_softc *ahd)796{797+ struct ahd_completion *completion;798 struct scb *scb;799 u_int scb_index;800···793 panic("ahd_run_qoutfifo recursion");794 ahd->flags |= AHD_RUNNING_QOUTFIFO;795 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);796+ for (;;) {797+ completion = &ahd->qoutfifo[ahd->qoutfifonext];798799+ if (completion->valid_tag != ahd->qoutfifonext_valid_tag)800+ break;801+802+ scb_index = ahd_le16toh(completion->tag);803 scb = ahd_lookup_scb(ahd, scb_index);804 if (scb == NULL) {805 printf("%s: WARNING no command for scb %d "···805 ahd_name(ahd), scb_index,806 ahd->qoutfifonext);807 ahd_dump_card_state(ahd);808+ } else if ((completion->sg_status & SG_STATUS_VALID) != 0) {809+ ahd_handle_scb_status(ahd, scb);810+ } else {811+ ahd_done(ahd, scb);812+ }813814 ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);815 if (ahd->qoutfifonext == 0)816+ ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;817 }818 ahd->flags &= ~AHD_RUNNING_QOUTFIFO;819}···876 ahd_name(ahd), seqintcode);877#endif878 switch (seqintcode) {00000000000000000000879 case ENTERING_NONPACK:880 {881 struct scb *scb;···1060 ahd_outb(ahd, SAVED_LUN, 0);1061 ahd_outb(ahd, SEQ_FLAGS, 0);1062 ahd_assert_atn(ahd);1063+ scb->flags &= ~SCB_PACKETIZED;1064 scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;1065 ahd_freeze_devq(ahd, scb);1066 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);···1503 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)1504 scb = NULL;15050001506 if ((status0 & IOERR) != 0) {1507 u_int now_lvd;1508···1521 ahd_setup_iocell_workaround(ahd);1522 ahd_unpause(ahd);1523 } else if ((status0 & OVERRUN) != 0) {1524+1525 printf("%s: SCSI offset overrun detected. Resetting bus.\n",1526 ahd_name(ahd));1527 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);1528 } else if ((status & SCSIRSTI) != 0) {1529+1530 printf("%s: Someone reset channel A\n", ahd_name(ahd));1531 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);1532 } else if ((status & SCSIPERR) != 0) {1533+1534+ /* Make sure the sequencer is in a safe location. */1535+ ahd_clear_critical_section(ahd);1536+1537 ahd_handle_transmission_error(ahd);1538 } else if (lqostat0 != 0) {1539+1540 printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);1541 ahd_outb(ahd, CLRLQOINT0, lqostat0);1542+ if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)1543 ahd_outb(ahd, CLRLQOINT1, 0);01544 } else if ((status & SELTO) != 0) {1545 u_int scbid;15461547 /* Stop the selection */1548 ahd_outb(ahd, SCSISEQ0, 0);1549+1550+ /* Make sure the sequencer is in a safe location. */1551+ ahd_clear_critical_section(ahd);15521553 /* No more pending messages */1554 ahd_clear_msg_state(ahd);···1573 scbid);1574 }1575#endif0000000001576 ahd_scb_devinfo(ahd, &devinfo, scb);01577 ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);1578 ahd_freeze_devq(ahd, scb);1579+1580+ /*1581+ * Cancel any pending transactions on the device1582+ * now that it seems to be missing. This will1583+ * also revert us to async/narrow transfers until1584+ * we can renegotiate with the device.1585+ */1586+ ahd_handle_devreset(ahd, &devinfo,1587+ CAM_LUN_WILDCARD,1588+ CAM_SEL_TIMEOUT,1589+ "Selection Timeout",1590+ /*verbose_level*/1);1591 }1592 ahd_outb(ahd, CLRINT, CLRSCSIINT);1593 ahd_iocell_first_selection(ahd);1594 ahd_unpause(ahd);1595 } else if ((status0 & (SELDI|SELDO)) != 0) {1596+1597 ahd_iocell_first_selection(ahd);1598 ahd_unpause(ahd);1599 } else if (status3 != 0) {···1598 ahd_name(ahd), status3);1599 ahd_outb(ahd, CLRSINT3, status3);1600 } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {1601+1602+ /* Make sure the sequencer is in a safe location. */1603+ ahd_clear_critical_section(ahd);1604+1605 ahd_handle_lqiphase_error(ahd, lqistat1);1606 } else if ((lqistat1 & LQICRCI_NLQ) != 0) {1607 /*···1621 * go about selecting the target while we handle the event.1622 */1623 ahd_outb(ahd, SCSISEQ0, 0);1624+1625+ /* Make sure the sequencer is in a safe location. */1626+ ahd_clear_critical_section(ahd);16271628 /*1629 * Determine what we were up to at the time of···1659 clear_fifo = 0;1660 packetized = (lqostat1 & LQOBUSFREE) != 0;1661 if (!packetized1662+ && ahd_inb(ahd, LASTPHASE) == P_BUSFREE1663+ && (ahd_inb(ahd, SSTAT0) & SELDI) == 01664+ && ((ahd_inb(ahd, SSTAT0) & SELDO) == 01665+ || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))1666+ /*1667+ * Assume packetized if we are not1668+ * on the bus in a non-packetized1669+ * capacity and any pending selection1670+ * was a packetized selection.1671+ */1672 packetized = 1;1673 break;1674 }···2310 "PRGMCNT == 0x%x\n",2311 ahd_lookup_phase_entry(lastphase)->phasemsg,2312 aborted,2313+ ahd_inw(ahd, PRGMCNT));02314 ahd_dump_card_state(ahd);2315 }2316 /* Always restart the sequencer. */···2474 u_int i;24752476 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);2477+ seqaddr = ahd_inw(ahd, CURADDR);024782479 cs = ahd->critical_sections;2480 for (i = 0; i < ahd->num_critical_sections; i++, cs++) {···3196 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;31973198 if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 03199+ && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 03200+ && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {3201 /*3202 * Slow down our CRC interval to be3203+ * compatible with non-packetized3204+ * U160 devices that can't handle a3205+ * CRC at full speed.3206 */3207 con_opts |= ENSLOWCRC;3208+ }3209+3210+ if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {3211+ /*3212+ * On H2A4, revert to a slower slewrate3213+ * on non-paced transfers.3214+ */3215+ iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=3216+ ~AHD_SLEWRATE_MASK;3217 }3218 }3219···3292 * Force the sequencer to reinitialize the selection for3293 * the command at the head of the execution queue if it3294 * has already been setup. The negotiation changes may3295+ * effect whether we select-out with ATN. It is only3296+ * safe to clear ENSELO when the bus is not free and no3297+ * selection is in progres or completed.3298 */3299 saved_modes = ahd_save_modes(ahd);3300 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);3301+ if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 03302+ && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)3303+ ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);3304 saved_scbptr = ahd_get_scbptr(ahd);3305 /* Ensure that the hscbs down on the card match the new information */3306 for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {···4909 * Determine initial values for data_addr and data_cnt4910 * for resuming the data phase.4911 */4912+ sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);0004913 sgptr &= SG_PTR_MASK;49144915 resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)···4930 dataptr = ahd_le64toh(sg->addr)4931 + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)4932 - resid;4933+ ahd_outl(ahd, HADDR + 4, dataptr >> 32);0004934 } else {4935 struct ahd_dma_seg *sg;4936···4948 ahd_outb(ahd, HADDR + 4,4949 (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);4950 }4951+ ahd_outl(ahd, HADDR, dataptr);0004952 ahd_outb(ahd, HCNT + 2, resid >> 16);4953 ahd_outb(ahd, HCNT + 1, resid >> 8);4954 ahd_outb(ahd, HCNT, resid);···5011 ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,5012 AHD_TRANS_CUR, /*paused*/TRUE);5013 ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,5014+ /*ppr_options*/0, AHD_TRANS_CUR,5015+ /*paused*/TRUE);50165017+ if (status != CAM_SEL_TIMEOUT)5018+ ahd_send_async(ahd, devinfo->channel, devinfo->target,5019+ CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);50205021+ if (message != NULL && bootverbose)05022 printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),5023 message, devinfo->channel, devinfo->target, found);5024}···5203 /* FALLTHROUGH */5204 case 4:5205 ahd_dmamap_unload(ahd, ahd->shared_data_dmat,5206+ ahd->shared_data_map.dmamap);5207 /* FALLTHROUGH */5208 case 3:5209 ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,5210+ ahd->shared_data_map.dmamap);5211 ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,5212+ ahd->shared_data_map.dmamap);5213 /* FALLTHROUGH */5214 case 2:5215 ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);···5975 newcount = MIN(scb_data->sense_left, scb_data->scbs_left);5976 newcount = MIN(newcount, scb_data->sgs_left);5977 newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));0005978 for (i = 0; i < newcount; i++) {005979 struct scb_platform_data *pdata;5980+ u_int col_tag;5981#ifndef __linux__5982 int error;5983#endif5984+5985 next_scb = (struct scb *)malloc(sizeof(*next_scb),5986 M_DEVBUF, M_NOWAIT);5987 if (next_scb == NULL)···6041 sense_data += AHD_SENSE_BUFSIZE;6042 sense_busaddr += AHD_SENSE_BUFSIZE;6043 scb_data->numscbs++;6044+ scb_data->sense_left--;6045+ scb_data->scbs_left--;6046+ scb_data->sgs_left--;6047 }6048}6049···6088int6089ahd_init(struct ahd_softc *ahd)6090{06091 uint8_t *next_vaddr;6092 dma_addr_t next_baddr;6093 size_t driver_data_size;···6156 * for the target mode role, we must additionally provide space for6157 * the incoming target command fifo.6158 */6159+ driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)6160 + sizeof(struct hardware_scb);6161 if ((ahd->features & AHD_TARGETMODE) != 0)6162 driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);···61786179 /* Allocation of driver data */6180 if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,6181+ (void **)&ahd->shared_data_map.vaddr,6182+ BUS_DMA_NOWAIT,6183+ &ahd->shared_data_map.dmamap) != 0) {6184 return (ENOMEM);6185 }61866187 ahd->init_level++;61886189 /* And permanently map it in */6190+ ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,6191+ ahd->shared_data_map.vaddr, driver_data_size,6192+ ahd_dmamap_cb, &ahd->shared_data_map.physaddr,6193+ /*flags*/0);6194+ ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;6195 next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];6196+ next_baddr = ahd->shared_data_map.physaddr6197+ + AHD_QOUT_SIZE*sizeof(struct ahd_completion);6198 if ((ahd->features & AHD_TARGETMODE) != 0) {6199 ahd->targetcmds = (struct target_cmd *)next_vaddr;6200 next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);···6212 * specially from the DMA safe memory chunk used for the QOUTFIFO.6213 */6214 ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;6215+ ahd->next_queued_hscb_map = &ahd->shared_data_map;6216 ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);62176218 ahd->init_level++;···65176518 /* All of our queues are empty */6519 ahd->qoutfifonext = 0;6520+ ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;6521+ ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);6522 for (i = 0; i < AHD_QOUT_SIZE; i++)6523+ ahd->qoutfifo[i].valid_tag = 0;6524 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);65256526 ahd->qinfifonext = 0;···6553 ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);6554 ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);6555 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);6556+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);6557+ ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);65586559 /*6560 * The Freeze Count is 0.6561 */6562+ ahd->qfreeze_cnt = 0;6563 ahd_outw(ahd, QFREEZE_COUNT, 0);6564+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);65656566 /*6567 * Tell the sequencer where it can find our arrays in memory.6568 */6569+ busaddr = ahd->shared_data_map.physaddr;6570+ ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);6571+ ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);00000065726573 /*6574 * Setup the allowed SCSI Sequences based on operational mode.···6619 * Tell the sequencer which SCB will be the next one it receives.6620 */6621 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);6622+ ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);00066236624 /*6625 * Default to coalescing disabled.···6926{6927 u_int intstat;6928 u_int maxloops;069296930 maxloops = 1000;6931 ahd->flags |= AHD_ALL_INTERRUPTS;6932 ahd_pause(ahd);6933 /*6934+ * Freeze the outgoing selections. We do this only06935 * until we are safely paused without further selections6936 * pending.6937 */6938+ ahd->qfreeze_cnt--;6939+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);6940 ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);6941 do {069426943 ahd_unpause(ahd);6944+ /*6945+ * Give the sequencer some time to service6946+ * any active selections.6947+ */6948+ ahd_delay(500);6949+6950 ahd_intr(ahd);6951 ahd_pause(ahd);06952 intstat = ahd_inb(ahd, INTSTAT);6953+ if ((intstat & INT_PEND) == 0) {6954+ ahd_clear_critical_section(ahd);6955+ intstat = ahd_inb(ahd, INTSTAT);6956+ }0000000000006957 } while (--maxloops6958 && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)6959 && ((intstat & INT_PEND) != 0···6973 printf("Infinite interrupt loop, INTSTAT = %x",6974 ahd_inb(ahd, INTSTAT));6975 }6976+ ahd->qfreeze_cnt++;6977+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);00000000069786979 ahd_flush_qoutfifo(ahd);6980···7155 uint32_t busaddr;71567157 busaddr = ahd_le32toh(scb->hscb->hscb_busaddr);7158+ ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);0007159 } else {7160 prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;7161 ahd_sync_scb(ahd, prev_scb, ···7265 */7266 ahd->qinfifonext = qinstart;7267 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);7268+ ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);00072697270 while (qinpos != qintail) {7271 scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);···7330 * appropriate, traverse the SCBs of each "their id"7331 * looking for matches.7332 */7333+ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);7334 savedscbptr = ahd_get_scbptr(ahd);7335 tid_next = ahd_inw(ahd, WAITING_TID_HEAD);7336 tid_prev = SCB_LIST_NULL;···7399 u_int prev;7400 int found;74017402+ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);7403 found = 0;7404 prev = SCB_LIST_NULL;7405 next = *list_head;···7466ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,7467 u_int tid_cur, u_int tid_next)7468{7469+ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);74707471 if (SCBID_IS_NULL(tid_cur)) {7472···7506{7507 u_int tail_offset;75087509+ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);7510 if (!SCBID_IS_NULL(prev)) {7511 ahd_set_scbptr(ahd, prev);7512 ahd_outw(ahd, SCB_NEXT, next);···7739 */7740 ahd_clear_msg_state(ahd);7741 ahd_outb(ahd, SIMODE1,7742+ ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));77437744 if (initiate_reset)7745 ahd_reset_current_bus(ahd);···7910void7911ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)7912{7913+ struct hardware_scb *hscb;7914+ int paused;79157916 /*7917 * The sequencer freezes its select-out queue7918 * anytime a SCSI status error occurs. We must7919+ * handle the error and increment our qfreeze count7920+ * to allow the sequencer to continue. We don't7921+ * bother clearing critical sections here since all7922+ * operations are on data structures that the sequencer7923+ * is not touching once the queue is frozen.7924 */7925 hscb = scb->hscb; 7926+7927+ if (ahd_is_paused(ahd)) {7928+ paused = 1;7929+ } else {7930+ paused = 0;7931+ ahd_pause(ahd);7932+ }79337934 /* Freeze the queue until the client sees the error. */7935 ahd_freeze_devq(ahd, scb);7936 ahd_freeze_scb(scb);7937+ ahd->qfreeze_cnt++;7938+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);7939+7940+ if (paused == 0)7941+ ahd_unpause(ahd);0000079427943 /* Don't want to clobber the original sense code */7944 if ((scb->flags & SCB_SENSE) != 0) {···8317 max_prog = 2048;83188319 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);8320+ ahd_outw(ahd, PRGMCNT, 0);08321 for (i = 0; i < max_prog; i++) {8322 uint8_t ins_bytes[4];8323···8347 u_int sg_prefetch_cnt_limit;8348 u_int sg_prefetch_align;8349 u_int sg_size;8350+ u_int cacheline_mask;8351 uint8_t download_consts[DOWNLOAD_CONST_COUNT];83528353 if (bootverbose)8354 printf("%s: Downloading Sequencer Program...",8355 ahd_name(ahd));83568357+#if DOWNLOAD_CONST_COUNT != 88358#error "Download Const Mismatch"8359#endif8360 /*···8389 /* Round down to the nearest power of 2. */8390 while (powerof2(sg_prefetch_align) == 0)8391 sg_prefetch_align--;8392+8393+ cacheline_mask = sg_prefetch_align - 1;8394+8395 /*8396 * If the cacheline boundary is greater than half our prefetch RAM8397 * we risk not being able to fetch even a single complete S/G···8429 download_consts[PKT_OVERRUN_BUFOFFSET] =8430 (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;8431 download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;8432+ download_consts[CACHELINE_MASK] = cacheline_mask;8433 cur_patch = patches;8434 downloaded = 0;8435 skip_addr = 0;8436 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);8437+ ahd_outw(ahd, PRGMCNT, 0);084388439 for (i = 0; i < sizeof(seqprog)/4; i++) {8440 if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {···8727 printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"8728 "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",8729 ahd_name(ahd), 8730+ ahd_inw(ahd, CURADDR),8731 ahd_build_mode_state(ahd, ahd->saved_src_mode,8732 ahd->saved_dst_mode));8733 if (paused)···88368837 printf("Sequencer DMA-Up and Complete list: ");8838 scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);8839+ i = 0;8840+ while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {8841+ ahd_set_scbptr(ahd, scb_index);8842+ printf("%d ", scb_index);8843+ scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);8844+ }8845+ printf("\n");8846+ printf("Sequencer On QFreeze and Complete list: ");8847+ scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);8848 i = 0;8849 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {8850 ahd_set_scbptr(ahd, scb_index);···9077{9078 int cnt;90799080+ cnt = 5000;9081 while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)9082 ahd_delay(5);9083···9423 if ((ahd->features & AHD_MULTI_TID) != 0) {9424 u_int targid_mask;94259426+ targid_mask = ahd_inw(ahd, TARGID);009427 targid_mask |= target_mask;9428+ ahd_outw(ahd, TARGID, targid_mask);009429 ahd_update_scsiid(ahd, targid_mask);9430 } else {9431 u_int our_id;···9543 if (ahd->features & AHD_MULTI_TID) {9544 u_int targid_mask;95459546+ targid_mask = ahd_inw(ahd, TARGID);0009547 targid_mask &= ~target_mask;9548+ ahd_outw(ahd, TARGID, targid_mask);009549 ahd_update_scsiid(ahd, targid_mask);9550 }9551 }···96519652 cmd->cmd_valid = 0;9653 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,9654+ ahd->shared_data_map.dmamap,9655 ahd_targetcmd_offset(ahd, ahd->tqinfifonext),9656 sizeof(struct target_cmd),9657 BUS_DMASYNC_PREREAD);
+26-12
drivers/scsi/aic7xxx/aic79xx_inline.h
···37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE38 * POSSIBILITY OF SUCH DAMAGES.39 *40- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#51 $41 *42 * $FreeBSD$43 */···522static __inline uint16_t523ahd_inw(struct ahd_softc *ahd, u_int port)524{00000525 return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));526}527528static __inline void529ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)530{0000531 ahd_outb(ahd, port, value & 0xFF);532 ahd_outb(ahd, port+1, (value >> 8) & 0xFF);533}···693 * Razor #528694 */695 value = ahd_inb(ahd, offset);696- if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0)697 ahd_inb(ahd, MODE_PTR);698 return (value);699}···736static __inline void737ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)738{739- struct hardware_scb *q_hscb;0740 uint32_t saved_hscb_busaddr;741742 /*···753 * locate the correct SCB by SCB_TAG.754 */755 q_hscb = ahd->next_queued_hscb;0756 saved_hscb_busaddr = q_hscb->hscb_busaddr;757 memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));758 q_hscb->hscb_busaddr = saved_hscb_busaddr;···761762 /* Now swap HSCB pointers. */763 ahd->next_queued_hscb = scb->hscb;0764 scb->hscb = q_hscb;0765766 /* Now define the mapping from tag to SCB in the scbindex */767 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;···837static __inline void838ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)839{840- ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,841- /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op);0842}843844static __inline void···848#ifdef AHD_TARGET_MODE849 if ((ahd->flags & AHD_TARGETROLE) != 0) {850 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,851- ahd->shared_data_dmamap,852 ahd_targetcmd_offset(ahd, 0),853 sizeof(struct target_cmd) * AHD_TMODE_CMDS,854 op);···868 u_int retval;869870 retval = 0;871- ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,872- /*offset*/ahd->qoutfifonext, /*len*/2,873- BUS_DMASYNC_POSTREAD);874- if ((ahd->qoutfifo[ahd->qoutfifonext]875- & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag)876 retval |= AHD_RUN_QOUTFIFO;877#ifdef AHD_TARGET_MODE878 if ((ahd->flags & AHD_TARGETROLE) != 0879 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {880 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,881- ahd->shared_data_dmamap,882 ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),883 /*len*/sizeof(struct target_cmd),884 BUS_DMASYNC_POSTREAD);
···37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE38 * POSSIBILITY OF SUCH DAMAGES.39 *40+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $41 *42 * $FreeBSD$43 */···522static __inline uint16_t523ahd_inw(struct ahd_softc *ahd, u_int port)524{525+ /*526+ * Read high byte first as some registers increment527+ * or have other side effects when the low byte is528+ * read.529+ */530 return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));531}532533static __inline void534ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)535{536+ /*537+ * Write low byte first to accomodate registers538+ * such as PRGMCNT where the order maters.539+ */540 ahd_outb(ahd, port, value & 0xFF);541 ahd_outb(ahd, port+1, (value >> 8) & 0xFF);542}···684 * Razor #528685 */686 value = ahd_inb(ahd, offset);687+ if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)688 ahd_inb(ahd, MODE_PTR);689 return (value);690}···727static __inline void728ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)729{730+ struct hardware_scb *q_hscb;731+ struct map_node *q_hscb_map;732 uint32_t saved_hscb_busaddr;733734 /*···743 * locate the correct SCB by SCB_TAG.744 */745 q_hscb = ahd->next_queued_hscb;746+ q_hscb_map = ahd->next_queued_hscb_map;747 saved_hscb_busaddr = q_hscb->hscb_busaddr;748 memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));749 q_hscb->hscb_busaddr = saved_hscb_busaddr;···750751 /* Now swap HSCB pointers. */752 ahd->next_queued_hscb = scb->hscb;753+ ahd->next_queued_hscb_map = scb->hscb_map;754 scb->hscb = q_hscb;755+ scb->hscb_map = q_hscb_map;756757 /* Now define the mapping from tag to SCB in the scbindex */758 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;···824static __inline void825ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)826{827+ ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,828+ /*offset*/0,829+ /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);830}831832static __inline void···834#ifdef AHD_TARGET_MODE835 if ((ahd->flags & AHD_TARGETROLE) != 0) {836 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,837+ ahd->shared_data_map.dmamap,838 ahd_targetcmd_offset(ahd, 0),839 sizeof(struct target_cmd) * AHD_TMODE_CMDS,840 op);···854 u_int retval;855856 retval = 0;857+ ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,858+ /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),859+ /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);860+ if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag861+ == ahd->qoutfifonext_valid_tag)862 retval |= AHD_RUN_QOUTFIFO;863#ifdef AHD_TARGET_MODE864 if ((ahd->flags & AHD_TARGETROLE) != 0865 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {866 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,867+ ahd->shared_data_map.dmamap,868 ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),869 /*len*/sizeof(struct target_cmd),870 BUS_DMASYNC_POSTREAD);
+51-11
drivers/scsi/aic7xxx/aic79xx_osm.c
···1468 if ((tstate->auto_negotiate & mask) != 0) {1469 scb->flags |= SCB_AUTO_NEGOTIATE;1470 scb->hscb->control |= MK_MESSAGE;0000000000000000000000001471 }14721473 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {···2082 int paused;2083 int wait;2084 int disconnected;02085 ahd_mode_state saved_modes;2086 unsigned long flags;2087···2201 last_phase = ahd_inb(ahd, LASTPHASE);2202 saved_scbptr = ahd_get_scbptr(ahd);2203 active_scbptr = saved_scbptr;2204- if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {02205 struct scb *bus_scb;22062207 bus_scb = ahd_lookup_scb(ahd, active_scbptr);···2220 * bus or is in the disconnected state.2221 */2222 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);2223- if (last_phase != P_BUSFREE2224- && (SCB_GET_TAG(pending_scb) == active_scbptr2225 || (flag == SCB_DEVICE_RESET2226- && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) {22272228 /*2229 * We're active on the bus, so assert ATN2230 * and hope that the target responds.2231 */2232 pending_scb = ahd_lookup_scb(ahd, active_scbptr);2233- pending_scb->flags |= SCB_RECOVERY_SCB|flag;2234 ahd_outb(ahd, MSG_OUT, HOST_MSG);2235 ahd_outb(ahd, SCSISIGO, last_phase|ATNO);2236- scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");2237 wait = TRUE;000000000000002238 } else if (disconnected) {22392240 /*2241 * Actually re-queue this SCB in an attempt2242 * to select the device before it reconnects.2243 */2244- pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;2245 ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));2246 pending_scb->hscb->cdb_len = 0;2247 pending_scb->hscb->task_attribute = 0;···2335 timer.expires = jiffies + (5 * HZ);2336 timer.function = ahd_linux_sem_timeout;2337 add_timer(&timer);2338- printf("Recovery code sleeping\n");2339 down(&ahd->platform_data->eh_sem);2340- printf("Recovery code awake\n");2341 ret = del_timer_sync(&timer);2342 if (ret == 0) {2343- printf("Timer Expired\n");02344 retval = FAILED;2345 }2346 }2347- ahd_unlock(ahd, &flags);2348 return (retval);2349}2350
···1468 if ((tstate->auto_negotiate & mask) != 0) {1469 scb->flags |= SCB_AUTO_NEGOTIATE;1470 scb->hscb->control |= MK_MESSAGE;1471+ } else if (cmd->cmnd[0] == INQUIRY1472+ && (tinfo->curr.offset != 01473+ || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT1474+ || tinfo->curr.ppr_options != 0)1475+ && (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) {1476+ /*1477+ * The SCSI spec requires inquiry1478+ * commands to complete without1479+ * reporting unit attention conditions.1480+ * Because of this, an inquiry command1481+ * that occurs just after a device is1482+ * reset will result in a data phase1483+ * with mismatched negotiated rates.1484+ * The core already forces a renegotiation1485+ * for reset events that are visible to1486+ * our controller or that we initiate,1487+ * but a third party device reset or a1488+ * hot-plug insertion can still cause this1489+ * issue. Therefore, we force a re-negotiation1490+ * for every inquiry command unless we1491+ * are async.1492+ */1493+ scb->flags |= SCB_NEGOTIATE;1494+ scb->hscb->control |= MK_MESSAGE;1495 }14961497 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {···2058 int paused;2059 int wait;2060 int disconnected;2061+ int found;2062 ahd_mode_state saved_modes;2063 unsigned long flags;2064···2176 last_phase = ahd_inb(ahd, LASTPHASE);2177 saved_scbptr = ahd_get_scbptr(ahd);2178 active_scbptr = saved_scbptr;2179+ if (disconnected && ((last_phase != P_BUSFREE) || 2180+ (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) {2181 struct scb *bus_scb;21822183 bus_scb = ahd_lookup_scb(ahd, active_scbptr);···2194 * bus or is in the disconnected state.2195 */2196 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);2197+ if (SCB_GET_TAG(pending_scb) == active_scbptr02198 || (flag == SCB_DEVICE_RESET2199+ && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) {22002201 /*2202 * We're active on the bus, so assert ATN2203 * and hope that the target responds.2204 */2205 pending_scb = ahd_lookup_scb(ahd, active_scbptr);2206+ pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;2207 ahd_outb(ahd, MSG_OUT, HOST_MSG);2208 ahd_outb(ahd, SCSISIGO, last_phase|ATNO);2209+ scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n");2210 wait = TRUE;2211+ } else if (last_phase != P_BUSFREE2212+ && ahd_inb(ahd, SCSIPHASE) == 0) {2213+ /*2214+ * SCB is not identified, there2215+ * is no pending REQ, and the sequencer2216+ * has not seen a busfree. Looks like2217+ * a stuck connection waiting to2218+ * go busfree. Reset the bus.2219+ */2220+ found = ahd_reset_channel(ahd, cmd->device->channel + 'A',2221+ /*Initiate Reset*/TRUE);2222+ printf("%s: Issued Channel %c Bus Reset. "2223+ "%d SCBs aborted\n", ahd_name(ahd),2224+ cmd->device->channel + 'A', found);2225 } else if (disconnected) {22262227 /*2228 * Actually re-queue this SCB in an attempt2229 * to select the device before it reconnects.2230 */2231+ pending_scb->flags |= SCB_RECOVERY_SCB|flag;2232 ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));2233 pending_scb->hscb->cdb_len = 0;2234 pending_scb->hscb->task_attribute = 0;···2296 timer.expires = jiffies + (5 * HZ);2297 timer.function = ahd_linux_sem_timeout;2298 add_timer(&timer);2299+ printf("%s: Recovery code sleeping\n", ahd_name(ahd));2300 down(&ahd->platform_data->eh_sem);2301+ printf("%s: Recovery code awake\n", ahd_name(ahd));2302 ret = del_timer_sync(&timer);2303 if (ret == 0) {2304+ printf("%s: Timer Expired (active %d)\n",2305+ ahd_name(ahd), dev->active);2306 retval = FAILED;2307 }2308 }2309+ ahd_unlock(ahd, &flags);2310 return (retval);2311}2312
+1-1
drivers/scsi/aic7xxx/aic79xx_osm.h
···252/***************************** SMP support ************************************/253#include <linux/spinlock.h>254255-#define AIC79XX_DRIVER_VERSION "1.3.11"256257/*************************** Device Data Structures ***************************/258/*
···252/***************************** SMP support ************************************/253#include <linux/spinlock.h>254255+#define AIC79XX_DRIVER_VERSION "3.0"256257/*************************** Device Data Structures ***************************/258/*
+15-9
drivers/scsi/aic7xxx/aic79xx_pci.c
···38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE39 * POSSIBILITY OF SUCH DAMAGES.40 *41- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#77 $42- *43- * $FreeBSD$44 */4546#ifdef __linux__···112 "Adaptec 29320ALP Ultra320 SCSI adapter",113 ahd_aic7901_setup114 },0000000115 /* aic7902 based controllers */ 116 {117 ID_AHA_29320,···133 ahd_aic7902_setup134 },135 {136- ID_AHA_29320LP,137- ID_ALL_MASK,138- "Adaptec 29320LP Ultra320 SCSI adapter",139- ahd_aic7901A_setup140- },141- {142 ID_AHA_39320,143 ID_ALL_MASK,144 "Adaptec 39320 Ultra320 SCSI adapter",···142 ID_AHA_39320_B,143 ID_ALL_MASK,144 "Adaptec 39320 Ultra320 SCSI adapter",000000145 ahd_aic7902_setup146 },147 {···673 * Now set the termination based on what we found.674 */675 sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;0676 if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {677 ahd->flags |= AHD_TERM_ENB_A;678 sxfrctl1 |= STPWEN;
···38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE39 * POSSIBILITY OF SUCH DAMAGES.40 *41+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $0042 */4344#ifdef __linux__···114 "Adaptec 29320ALP Ultra320 SCSI adapter",115 ahd_aic7901_setup116 },117+ /* aic7901A based controllers */118+ {119+ ID_AHA_29320LP,120+ ID_ALL_MASK,121+ "Adaptec 29320LP Ultra320 SCSI adapter",122+ ahd_aic7901A_setup123+ },124 /* aic7902 based controllers */ 125 {126 ID_AHA_29320,···128 ahd_aic7902_setup129 },130 {000000131 ID_AHA_39320,132 ID_ALL_MASK,133 "Adaptec 39320 Ultra320 SCSI adapter",···143 ID_AHA_39320_B,144 ID_ALL_MASK,145 "Adaptec 39320 Ultra320 SCSI adapter",146+ ahd_aic7902_setup147+ },148+ {149+ ID_AHA_39320_B_DELL,150+ ID_ALL_MASK,151+ "Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter",152 ahd_aic7902_setup153 },154 {···668 * Now set the termination based on what we found.669 */670 sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;671+ ahd->flags &= ~AHD_TERM_ENB_A;672 if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {673 ahd->flags |= AHD_TERM_ENB_A;674 sxfrctl1 |= STPWEN;
···39 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE40 * POSSIBILITY OF SUCH DAMAGES.41 *42- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#69 $43- *44- * $FreeBSD$45 */4647#ifdef __linux__···389 ID_AIC7892_ARO,390 ID_ALL_MASK,391 "Adaptec aic7892 Ultra160 SCSI adapter (ARO)",000000392 ahc_aic7892_setup393 },394 /* aic7895 based controllers */ ···1197 * use for this test.1198 */1199 hcntrl = ahc_inb(ahc, HCNTRL);01200 if (hcntrl == 0xFF)1201 goto fail;00000000012021203 /*1204 * Next create a situation where write combining···1321 sd.sd_chip = C56_66;1322 }1323 ahc_release_seeprom(&sd);00001324 }13251326 if (!have_seeprom) {
···39 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE40 * POSSIBILITY OF SUCH DAMAGES.41 *42+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $0043 */4445#ifdef __linux__···391 ID_AIC7892_ARO,392 ID_ALL_MASK,393 "Adaptec aic7892 Ultra160 SCSI adapter (ARO)",394+ ahc_aic7892_setup395+ },396+ {397+ ID_AHA_2915_30LP,398+ ID_ALL_MASK,399+ "Adaptec 2915/30LP Ultra160 SCSI adapter",400 ahc_aic7892_setup401 },402 /* aic7895 based controllers */ ···1193 * use for this test.1194 */1195 hcntrl = ahc_inb(ahc, HCNTRL);1196+1197 if (hcntrl == 0xFF)1198 goto fail;1199+1200+ if ((hcntrl & CHIPRST) != 0) {1201+ /*1202+ * The chip has not been initialized since1203+ * PCI/EISA/VLB bus reset. Don't trust1204+ * "left over BIOS data".1205+ */1206+ ahc->flags |= AHC_NO_BIOS_INIT;1207+ }12081209 /*1210 * Next create a situation where write combining···1307 sd.sd_chip = C56_66;1308 }1309 ahc_release_seeprom(&sd);1310+1311+ /* Remember the SEEPROM type for later */1312+ if (sd.sd_chip == C56_66)1313+ ahc->flags |= AHC_LARGE_SEEPROM;1314 }13151316 if (!have_seeprom) {
···4479 * serialized. This is so because we want to reserve maximum number of4480 * available command ids for the I/O commands.4481 */4482- down(&adapter->int_mtx);44834484 scb = &adapter->int_scb;4485 memset(scb, 0, sizeof(scb_t));···4527 mc->cmd, mc->opcode, mc->subopcode, scmd->result);4528 }45294530- up(&adapter->int_mtx);45314532 return rval;4533}···4866 adapter->has_64bit_addr = 0;4867 }48684869- init_MUTEX(&adapter->int_mtx);4870 init_completion(&adapter->int_waitq);48714872 adapter->this_id = DEFAULT_INITIATOR_ID;
···4479 * serialized. This is so because we want to reserve maximum number of4480 * available command ids for the I/O commands.4481 */4482+ mutex_lock(&adapter->int_mtx);44834484 scb = &adapter->int_scb;4485 memset(scb, 0, sizeof(scb_t));···4527 mc->cmd, mc->opcode, mc->subopcode, scmd->result);4528 }45294530+ mutex_unlock(&adapter->int_mtx);45314532 return rval;4533}···4866 adapter->has_64bit_addr = 0;4867 }48684869+ mutex_init(&adapter->int_mtx);4870 init_completion(&adapter->int_waitq);48714872 adapter->this_id = DEFAULT_INITIATOR_ID;
+2-2
drivers/scsi/megaraid.h
···2#define __MEGARAID_H__34#include <linux/spinlock.h>5-67#define MEGARAID_VERSION \8 "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n"···889890 scb_t int_scb;891 Scsi_Cmnd int_scmd;892- struct semaphore int_mtx; /* To synchronize the internal893 commands */894 struct completion int_waitq; /* wait queue for internal895 cmds */
···2#define __MEGARAID_H__34#include <linux/spinlock.h>5+#include <linux/mutex.h>67#define MEGARAID_VERSION \8 "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n"···889890 scb_t int_scb;891 Scsi_Cmnd int_scmd;892+ struct mutex int_mtx; /* To synchronize the internal893 commands */894 struct completion int_waitq; /* wait queue for internal895 cmds */
+4-3
drivers/scsi/megaraid/megaraid_sas.c
···35#include <asm/uaccess.h>36#include <linux/fs.h>37#include <linux/compat.h>03839#include <scsi/scsi.h>40#include <scsi/scsi_cmnd.h>···73static int megasas_mgmt_majorno;74static struct megasas_mgmt_info megasas_mgmt_info;75static struct fasync_struct *megasas_async_queue;76-static DECLARE_MUTEX(megasas_async_queue_mutex);7778/**79 * megasas_get_cmd - Get a command from the free pool···2363{2364 int rc;23652366- down(&megasas_async_queue_mutex);23672368 rc = fasync_helper(fd, filep, mode, &megasas_async_queue);23692370- up(&megasas_async_queue_mutex);23712372 if (rc >= 0) {2373 /* For sanity check when we get ioctl */
···35#include <asm/uaccess.h>36#include <linux/fs.h>37#include <linux/compat.h>38+#include <linux/mutex.h>3940#include <scsi/scsi.h>41#include <scsi/scsi_cmnd.h>···72static int megasas_mgmt_majorno;73static struct megasas_mgmt_info megasas_mgmt_info;74static struct fasync_struct *megasas_async_queue;75+static DEFINE_MUTEX(megasas_async_queue_mutex);7677/**78 * megasas_get_cmd - Get a command from the free pool···2362{2363 int rc;23642365+ mutex_lock(&megasas_async_queue_mutex);23662367 rc = fasync_helper(fd, filep, mode, &megasas_async_queue);23682369+ mutex_unlock(&megasas_async_queue_mutex);23702371 if (rc >= 0) {2372 /* For sanity check when we get ioctl */
+16-8
drivers/scsi/qla2xxx/Kconfig
···1-config SCSI_QLA2XXX2 tristate "QLogic QLA2XXX Fibre Channel Support"3 depends on PCI && SCSI4 select SCSI_FC_ATTRS···22 Upon request, the driver caches the firmware image until23 the driver is unloaded.24000025 NOTE: The original method of building firmware-loader26 modules has been deprecated as the firmware-images will27 be removed from the kernel sources.2829config SCSI_QLA2XXX_EMBEDDED_FIRMWARE30 bool " Use firmware-loader modules (DEPRECATED)"31- depends on SCSI_QLA2XXX00003233config SCSI_QLA21XX34 tristate " Build QLogic ISP2100 firmware-module"35- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE36 ---help---37 This driver supports the QLogic 21xx (ISP2100) host adapter family.3839config SCSI_QLA22XX40 tristate " Build QLogic ISP2200 firmware-module"41- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE42 ---help---43 This driver supports the QLogic 22xx (ISP2200) host adapter family.4445config SCSI_QLA230046 tristate " Build QLogic ISP2300 firmware-module"47- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE48 ---help---49 This driver supports the QLogic 2300 (ISP2300 and ISP2312) host50 adapter family.5152config SCSI_QLA232253 tristate " Build QLogic ISP2322 firmware-module"54- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE55 ---help---56 This driver supports the QLogic 2322 (ISP2322) host adapter family.5758config SCSI_QLA631259 tristate " Build QLogic ISP63xx firmware-module"60- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE61 ---help---62 This driver supports the QLogic 63xx (ISP6312 and ISP6322) host63 adapter family.6465config SCSI_QLA24XX66 tristate " Build QLogic ISP24xx firmware-module"67- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE68 ---help---69 This driver supports the QLogic 24xx (ISP2422 and ISP2432) host70 adapter family.
···1+config SCSI_QLA_FC2 tristate "QLogic QLA2XXX Fibre Channel Support"3 depends on PCI && SCSI4 select SCSI_FC_ATTRS···22 Upon request, the driver caches the firmware image until23 the driver is unloaded.2425+ Firmware images can be retrieved from:26+27+ ftp://ftp.qlogic.com/outgoing/linux/firmware/28+29 NOTE: The original method of building firmware-loader30 modules has been deprecated as the firmware-images will31 be removed from the kernel sources.3233config SCSI_QLA2XXX_EMBEDDED_FIRMWARE34 bool " Use firmware-loader modules (DEPRECATED)"35+ depends on SCSI_QLA_FC36+ help37+ This option offers you the deprecated firmware-loader38+ modules that have been obsoleted by the usage of the39+ Firmware Loader interface in the qla2xxx driver.4041config SCSI_QLA21XX42 tristate " Build QLogic ISP2100 firmware-module"43+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE44 ---help---45 This driver supports the QLogic 21xx (ISP2100) host adapter family.4647config SCSI_QLA22XX48 tristate " Build QLogic ISP2200 firmware-module"49+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE50 ---help---51 This driver supports the QLogic 22xx (ISP2200) host adapter family.5253config SCSI_QLA230054 tristate " Build QLogic ISP2300 firmware-module"55+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE56 ---help---57 This driver supports the QLogic 2300 (ISP2300 and ISP2312) host58 adapter family.5960config SCSI_QLA232261 tristate " Build QLogic ISP2322 firmware-module"62+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE63 ---help---64 This driver supports the QLogic 2322 (ISP2322) host adapter family.6566config SCSI_QLA631267 tristate " Build QLogic ISP63xx firmware-module"68+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE69 ---help---70 This driver supports the QLogic 63xx (ISP6312 and ISP6322) host71 adapter family.7273config SCSI_QLA24XX74 tristate " Build QLogic ISP24xx firmware-module"75+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE76 ---help---77 This driver supports the QLogic 24xx (ISP2422 and ISP2432) host78 adapter family.
···62extern int ql2xplogiabsentdevice;63extern int ql2xloginretrycount;64extern int ql2xfdmienable;06566extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);67···97 * Global Function Prototypes in qla_mbx.c source file.98 */99extern int100-qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t);101-102-extern int103-qla2x00_load_ram_ext(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);104105extern int106qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
···62extern int ql2xplogiabsentdevice;63extern int ql2xloginretrycount;64extern int ql2xfdmienable;65+extern int ql2xprocessrscn;6667extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);68···96 * Global Function Prototypes in qla_mbx.c source file.97 */98extern int99+qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);000100101extern int102qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
···71 "Enables FDMI registratons "72 "Default is 0 - no FDMI. 1 - perfom FDMI.");7374+int ql2xprocessrscn;75+module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR);76+MODULE_PARM_DESC(ql2xprocessrscn,77+ "Option to enable port RSCN handling via a series of less"78+ "fabric intrusive ADISCs and PLOGIs.");79+80/*81 * SCSI host template entry points82 */
···55#include <linux/interrupt.h>56#include <linux/notifier.h>57#include <linux/cpu.h>05859#include <scsi/scsi.h>60#include <scsi/scsi_cmnd.h>···210 .gfp_mask = __GFP_DMA,211};212213-static DECLARE_MUTEX(host_cmd_pool_mutex);214215static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,216 gfp_t gfp_mask)···331 * Select a command slab for this host and create it if not332 * yet existant.333 */334- down(&host_cmd_pool_mutex);335 pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);336 if (!pool->users) {337 pool->slab = kmem_cache_create(pool->name,···343344 pool->users++;345 shost->cmd_pool = pool;346- up(&host_cmd_pool_mutex);347348 /*349 * Get one backup command for this host.···360 kmem_cache_destroy(pool->slab);361 return -ENOMEM;362 fail:363- up(&host_cmd_pool_mutex);364 return -ENOMEM;365366}···382 kmem_cache_free(shost->cmd_pool->slab, cmd);383 }384385- down(&host_cmd_pool_mutex);386 if (!--shost->cmd_pool->users)387 kmem_cache_destroy(shost->cmd_pool->slab);388- up(&host_cmd_pool_mutex);389}390391#ifdef CONFIG_SCSI_LOGGING
···55#include <linux/interrupt.h>56#include <linux/notifier.h>57#include <linux/cpu.h>58+#include <linux/mutex.h>5960#include <scsi/scsi.h>61#include <scsi/scsi_cmnd.h>···209 .gfp_mask = __GFP_DMA,210};211212+static DEFINE_MUTEX(host_cmd_pool_mutex);213214static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,215 gfp_t gfp_mask)···330 * Select a command slab for this host and create it if not331 * yet existant.332 */333+ mutex_lock(&host_cmd_pool_mutex);334 pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);335 if (!pool->users) {336 pool->slab = kmem_cache_create(pool->name,···342343 pool->users++;344 shost->cmd_pool = pool;345+ mutex_unlock(&host_cmd_pool_mutex);346347 /*348 * Get one backup command for this host.···359 kmem_cache_destroy(pool->slab);360 return -ENOMEM;361 fail:362+ mutex_unlock(&host_cmd_pool_mutex);363 return -ENOMEM;364365}···381 kmem_cache_free(shost->cmd_pool->slab, cmd);382 }383384+ mutex_lock(&host_cmd_pool_mutex);385 if (!--shost->cmd_pool->users)386 kmem_cache_destroy(shost->cmd_pool->slab);387+ mutex_unlock(&host_cmd_pool_mutex);388}389390#ifdef CONFIG_SCSI_LOGGING
+8-8
drivers/scsi/scsi_lib.c
···1212 return -EOPNOTSUPP;1213}12141215-static void scsi_generic_done(struct scsi_cmnd *cmd)1216{1217 BUG_ON(!blk_pc_request(cmd->request));1218 /*···1224 scsi_io_completion(cmd, cmd->bufflen, 0);1225}12261227-void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)1228{1229 struct request *req = cmd->request;1230···1241 cmd->transfersize = req->data_len;1242 cmd->allowed = req->retries;1243 cmd->timeout_per_command = req->timeout;01244}1245-EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);12461247static int scsi_prep_fn(struct request_queue *q, struct request *req)1248{···1339 * happening now.1340 */1341 if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {1342- struct scsi_driver *drv;1343 int ret;13441345 /*···1370 /*1371 * Initialize the actual SCSI command for this request.1372 */1373- if (req->rq_disk) {00001374 drv = *(struct scsi_driver **)req->rq_disk->private_data;1375 if (unlikely(!drv->init_command(cmd))) {1376 scsi_release_buffers(cmd);1377 scsi_put_command(cmd);1378 goto kill;1379 }1380- } else {1381- scsi_setup_blk_pc_cmnd(cmd);1382- cmd->done = scsi_generic_done;1383 }1384 }1385
···1212 return -EOPNOTSUPP;1213}12141215+static void scsi_blk_pc_done(struct scsi_cmnd *cmd)1216{1217 BUG_ON(!blk_pc_request(cmd->request));1218 /*···1224 scsi_io_completion(cmd, cmd->bufflen, 0);1225}12261227+static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)1228{1229 struct request *req = cmd->request;1230···1241 cmd->transfersize = req->data_len;1242 cmd->allowed = req->retries;1243 cmd->timeout_per_command = req->timeout;1244+ cmd->done = scsi_blk_pc_done;1245}012461247static int scsi_prep_fn(struct request_queue *q, struct request *req)1248{···1339 * happening now.1340 */1341 if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {01342 int ret;13431344 /*···1371 /*1372 * Initialize the actual SCSI command for this request.1373 */1374+ if (req->flags & REQ_BLOCK_PC) {1375+ scsi_setup_blk_pc_cmnd(cmd);1376+ } else if (req->rq_disk) {1377+ struct scsi_driver *drv;1378+1379 drv = *(struct scsi_driver **)req->rq_disk->private_data;1380 if (unlikely(!drv->init_command(cmd))) {1381 scsi_release_buffers(cmd);1382 scsi_put_command(cmd);1383 goto kill;1384 }0001385 }1386 }1387
-6
drivers/scsi/scsi_priv.h
···26#define SCSI_SENSE_VALID(scmd) \27 (((scmd)->sense_buffer[0] & 0x70) == 0x70)2829-/*30- * Special value for scanning to specify scanning or rescanning of all31- * possible channels, (target) ids, or luns on a given shost.32- */33-#define SCAN_WILD_CARD ~034-35/* hosts.c */36extern int scsi_init_hosts(void);37extern void scsi_exit_hosts(void);
···24#include <linux/module.h>25#include <linux/workqueue.h>26#include <linux/blkdev.h>27-#include <asm/semaphore.h>28#include <scsi/scsi.h>29#include "scsi_priv.h"30#include <scsi/scsi_device.h>···4849/* Private data accessors (keep these out of the header file) */50#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)51-#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem)5253struct spi_internal {54 struct scsi_transport_template t;···242 spi_hold_mcs(starget) = 0;243 spi_dv_pending(starget) = 0;244 spi_initial_dv(starget) = 0;245- init_MUTEX(&spi_dv_sem(starget));246247 return 0;248}···915 scsi_target_quiesce(starget);916917 spi_dv_pending(starget) = 1;918- down(&spi_dv_sem(starget));919920 starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n");921···923924 starget_printk(KERN_INFO, starget, "Ending Domain Validation\n");925926- up(&spi_dv_sem(starget));927 spi_dv_pending(starget) = 0;928929 scsi_target_resume(starget);···1075/* 0x04 */ "Parallel Protocol Request"1076};10771078-void print_nego(const unsigned char *msg, int per, int off, int width)1079{1080 if (per) {1081 char buf[20];
···24#include <linux/module.h>25#include <linux/workqueue.h>26#include <linux/blkdev.h>27+#include <linux/mutex.h>28#include <scsi/scsi.h>29#include "scsi_priv.h"30#include <scsi/scsi_device.h>···4849/* Private data accessors (keep these out of the header file) */50#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)51+#define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex)5253struct spi_internal {54 struct scsi_transport_template t;···242 spi_hold_mcs(starget) = 0;243 spi_dv_pending(starget) = 0;244 spi_initial_dv(starget) = 0;245+ mutex_init(&spi_dv_mutex(starget));246247 return 0;248}···915 scsi_target_quiesce(starget);916917 spi_dv_pending(starget) = 1;918+ mutex_lock(&spi_dv_mutex(starget));919920 starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n");921···923924 starget_printk(KERN_INFO, starget, "Ending Domain Validation\n");925926+ mutex_unlock(&spi_dv_mutex(starget));927 spi_dv_pending(starget) = 0;928929 scsi_target_resume(starget);···1075/* 0x04 */ "Parallel Protocol Request"1076};10771078+static void print_nego(const unsigned char *msg, int per, int off, int width)1079{1080 if (per) {1081 char buf[20];
+16-47
drivers/scsi/sd.c
···49#include <linux/blkpg.h>50#include <linux/kref.h>51#include <linux/delay.h>052#include <asm/uaccess.h>5354#include <scsi/scsi.h>···112/* This semaphore is used to mediate the 0->1 reference get in the113 * face of object destruction (i.e. we can't allow a get on an114 * object after last put) */115-static DECLARE_MUTEX(sd_ref_sem);116117static int sd_revalidate_disk(struct gendisk *disk);118static void sd_rw_intr(struct scsi_cmnd * SCpnt);···194{195 struct scsi_disk *sdkp;196197- down(&sd_ref_sem);198 sdkp = __scsi_disk_get(disk);199- up(&sd_ref_sem);200 return sdkp;201}202···204{205 struct scsi_disk *sdkp;206207- down(&sd_ref_sem);208 sdkp = dev_get_drvdata(dev);209 if (sdkp)210 sdkp = __scsi_disk_get(sdkp->disk);211- up(&sd_ref_sem);212 return sdkp;213}214···216{217 struct scsi_device *sdev = sdkp->device;218219- down(&sd_ref_sem);220 kref_put(&sdkp->kref, scsi_disk_release);221 scsi_device_put(sdev);222- up(&sd_ref_sem);223}224225/**···232 **/233static int sd_init_command(struct scsi_cmnd * SCpnt)234{235- unsigned int this_count, timeout;236- struct gendisk *disk;237- sector_t block;238 struct scsi_device *sdp = SCpnt->device;239 struct request *rq = SCpnt->request;240-241- timeout = sdp->timeout;242-243- /*244- * SG_IO from block layer already setup, just copy cdb basically245- */246- if (blk_pc_request(rq)) {247- scsi_setup_blk_pc_cmnd(SCpnt);248- if (rq->timeout)249- timeout = rq->timeout;250-251- goto queue;252- }253-254- /*255- * we only do REQ_CMD and REQ_BLOCK_PC256- */257- if (!blk_fs_request(rq))258- return 0;259-260- disk = rq->rq_disk;261- block = rq->sector;262- this_count = SCpnt->request_bufflen >> 9;263264 SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "265 "count=%d\n", disk->disk_name,···380 SCpnt->transfersize = sdp->sector_size;381 SCpnt->underflow = this_count << 9;382 SCpnt->allowed = SD_MAX_RETRIES;383-384-queue:385 SCpnt->timeout_per_command = timeout;386387 /*···813 relatively rare error condition, no care is taken to avoid814 unnecessary additional work such as memcpy's that could be avoided.815 */816-817- /* 818- * If SG_IO from block layer then set good_bytes to stop retries;819- * else if errors, check them, and if necessary prepare for820- * (partial) retries.821- */822- if (blk_pc_request(SCpnt->request))823- good_bytes = this_count;824- else if (driver_byte(result) != 0 &&825 sense_valid && !sense_deferred) {826 switch (sshdr.sense_key) {827 case MEDIUM_ERROR:···1604 del_gendisk(sdkp->disk);1605 sd_shutdown(dev);16061607- down(&sd_ref_sem);1608 dev_set_drvdata(dev, NULL);1609 kref_put(&sdkp->kref, scsi_disk_release);1610- up(&sd_ref_sem);16111612 return 0;1613}···1616 * scsi_disk_release - Called to free the scsi_disk structure1617 * @kref: pointer to embedded kref1618 *1619- * sd_ref_sem must be held entering this routine. Because it is1620 * called on last put, you should always use the scsi_disk_get()1621 * scsi_disk_put() helpers which manipulate the semaphore directly1622 * and never do a direct kref_put().
···49#include <linux/blkpg.h>50#include <linux/kref.h>51#include <linux/delay.h>52+#include <linux/mutex.h>53#include <asm/uaccess.h>5455#include <scsi/scsi.h>···111/* This semaphore is used to mediate the 0->1 reference get in the112 * face of object destruction (i.e. we can't allow a get on an113 * object after last put) */114+static DEFINE_MUTEX(sd_ref_mutex);115116static int sd_revalidate_disk(struct gendisk *disk);117static void sd_rw_intr(struct scsi_cmnd * SCpnt);···193{194 struct scsi_disk *sdkp;195196+ mutex_lock(&sd_ref_mutex);197 sdkp = __scsi_disk_get(disk);198+ mutex_unlock(&sd_ref_mutex);199 return sdkp;200}201···203{204 struct scsi_disk *sdkp;205206+ mutex_lock(&sd_ref_mutex);207 sdkp = dev_get_drvdata(dev);208 if (sdkp)209 sdkp = __scsi_disk_get(sdkp->disk);210+ mutex_unlock(&sd_ref_mutex);211 return sdkp;212}213···215{216 struct scsi_device *sdev = sdkp->device;217218+ mutex_lock(&sd_ref_mutex);219 kref_put(&sdkp->kref, scsi_disk_release);220 scsi_device_put(sdev);221+ mutex_unlock(&sd_ref_mutex);222}223224/**···231 **/232static int sd_init_command(struct scsi_cmnd * SCpnt)233{000234 struct scsi_device *sdp = SCpnt->device;235 struct request *rq = SCpnt->request;236+ struct gendisk *disk = rq->rq_disk;237+ sector_t block = rq->sector;238+ unsigned int this_count = SCpnt->request_bufflen >> 9;239+ unsigned int timeout = sdp->timeout;0000000000000000000240241 SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "242 "count=%d\n", disk->disk_name,···401 SCpnt->transfersize = sdp->sector_size;402 SCpnt->underflow = this_count << 9;403 SCpnt->allowed = SD_MAX_RETRIES;00404 SCpnt->timeout_per_command = timeout;405406 /*···836 relatively rare error condition, no care is taken to avoid837 unnecessary additional work such as memcpy's that could be avoided.838 */839+ if (driver_byte(result) != 0 &&00000000840 sense_valid && !sense_deferred) {841 switch (sshdr.sense_key) {842 case MEDIUM_ERROR:···1635 del_gendisk(sdkp->disk);1636 sd_shutdown(dev);16371638+ mutex_lock(&sd_ref_mutex);1639 dev_set_drvdata(dev, NULL);1640 kref_put(&sdkp->kref, scsi_disk_release);1641+ mutex_unlock(&sd_ref_mutex);16421643 return 0;1644}···1647 * scsi_disk_release - Called to free the scsi_disk structure1648 * @kref: pointer to embedded kref1649 *1650+ * sd_ref_mutex must be held entering this routine. Because it is1651 * called on last put, you should always use the scsi_disk_get()1652 * scsi_disk_put() helpers which manipulate the semaphore directly1653 * and never do a direct kref_put().
+12-31
drivers/scsi/sr.c
···44#include <linux/interrupt.h>45#include <linux/init.h>46#include <linux/blkdev.h>047#include <asm/uaccess.h>4849#include <scsi/scsi.h>···91/* This semaphore is used to mediate the 0->1 reference get in the92 * face of object destruction (i.e. we can't allow a get on an93 * object after last put) */94-static DECLARE_MUTEX(sr_ref_sem);9596static int sr_open(struct cdrom_device_info *, int);97static void sr_release(struct cdrom_device_info *);···134{135 struct scsi_cd *cd = NULL;136137- down(&sr_ref_sem);138 if (disk->private_data == NULL)139 goto out;140 cd = scsi_cd(disk);···147 kref_put(&cd->kref, sr_kref_release);148 cd = NULL;149 out:150- up(&sr_ref_sem);151 return cd;152}153···155{156 struct scsi_device *sdev = cd->device;157158- down(&sr_ref_sem);159 kref_put(&cd->kref, sr_kref_release);160 scsi_device_put(sdev);161- up(&sr_ref_sem);162}163164/*···238 case ILLEGAL_REQUEST:239 if (!(SCpnt->sense_buffer[0] & 0x90))240 break;241- if (!blk_fs_request(SCpnt->request))242- break;243 error_sector = (SCpnt->sense_buffer[3] << 24) |244 (SCpnt->sense_buffer[4] << 16) |245 (SCpnt->sense_buffer[5] << 8) |···312 * quietly refuse to do anything to a changed disc until the313 * changed bit has been reset314 */315- return 0;316- }317-318- /*319- * these are already setup, just copy cdb basically320- */321- if (SCpnt->request->flags & REQ_BLOCK_PC) {322- scsi_setup_blk_pc_cmnd(SCpnt);323-324- if (SCpnt->timeout_per_command)325- timeout = SCpnt->timeout_per_command;326-327- goto queue;328- }329-330- if (!(SCpnt->request->flags & REQ_CMD)) {331- blk_dump_rq_flags(SCpnt->request, "sr unsup command");332 return 0;333 }334···403 */404 SCpnt->transfersize = cd->device->sector_size;405 SCpnt->underflow = this_count << 9;406-407-queue:408 SCpnt->allowed = MAX_RETRIES;409 SCpnt->timeout_per_command = timeout;410···742 /* failed, drive doesn't have capabilities mode page */743 cd->cdi.speed = 1;744 cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |745- CDC_DVD | CDC_DVD_RAM |746- CDC_SELECT_DISC | CDC_SELECT_SPEED);0747 kfree(buffer);748 printk("%s: scsi-1 drive\n", cd->cdi.name);749 return;···826 * sr_kref_release - Called to free the scsi_cd structure827 * @kref: pointer to embedded kref828 *829- * sr_ref_sem must be held entering this routine. Because it is830 * called on last put, you should always use the scsi_cd_get()831 * scsi_cd_put() helpers which manipulate the semaphore directly832 * and never do a direct kref_put().···855856 del_gendisk(cd->disk);857858- down(&sr_ref_sem);859 kref_put(&cd->kref, sr_kref_release);860- up(&sr_ref_sem);861862 return 0;863}
···44#include <linux/interrupt.h>45#include <linux/init.h>46#include <linux/blkdev.h>47+#include <linux/mutex.h>48#include <asm/uaccess.h>4950#include <scsi/scsi.h>···90/* This semaphore is used to mediate the 0->1 reference get in the91 * face of object destruction (i.e. we can't allow a get on an92 * object after last put) */93+static DEFINE_MUTEX(sr_ref_mutex);9495static int sr_open(struct cdrom_device_info *, int);96static void sr_release(struct cdrom_device_info *);···133{134 struct scsi_cd *cd = NULL;135136+ mutex_lock(&sr_ref_mutex);137 if (disk->private_data == NULL)138 goto out;139 cd = scsi_cd(disk);···146 kref_put(&cd->kref, sr_kref_release);147 cd = NULL;148 out:149+ mutex_unlock(&sr_ref_mutex);150 return cd;151}152···154{155 struct scsi_device *sdev = cd->device;156157+ mutex_lock(&sr_ref_mutex);158 kref_put(&cd->kref, sr_kref_release);159 scsi_device_put(sdev);160+ mutex_unlock(&sr_ref_mutex);161}162163/*···237 case ILLEGAL_REQUEST:238 if (!(SCpnt->sense_buffer[0] & 0x90))239 break;00240 error_sector = (SCpnt->sense_buffer[3] << 24) |241 (SCpnt->sense_buffer[4] << 16) |242 (SCpnt->sense_buffer[5] << 8) |···313 * quietly refuse to do anything to a changed disc until the314 * changed bit has been reset315 */00000000000000000316 return 0;317 }318···421 */422 SCpnt->transfersize = cd->device->sector_size;423 SCpnt->underflow = this_count << 9;00424 SCpnt->allowed = MAX_RETRIES;425 SCpnt->timeout_per_command = timeout;426···762 /* failed, drive doesn't have capabilities mode page */763 cd->cdi.speed = 1;764 cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |765+ CDC_DVD | CDC_DVD_RAM |766+ CDC_SELECT_DISC | CDC_SELECT_SPEED |767+ CDC_MRW | CDC_MRW_W | CDC_RAM);768 kfree(buffer);769 printk("%s: scsi-1 drive\n", cd->cdi.name);770 return;···845 * sr_kref_release - Called to free the scsi_cd structure846 * @kref: pointer to embedded kref847 *848+ * sr_ref_mutex must be held entering this routine. Because it is849 * called on last put, you should always use the scsi_cd_get()850 * scsi_cd_put() helpers which manipulate the semaphore directly851 * and never do a direct kref_put().···874875 del_gendisk(cd->disk);876877+ mutex_lock(&sr_ref_mutex);878 kref_put(&cd->kref, sr_kref_release);879+ mutex_unlock(&sr_ref_mutex);880881 return 0;882}
+111-91
drivers/scsi/sr_ioctl.c
···3132module_param(xa_test, int, S_IRUGO | S_IWUSR);3300000000000000000000000000000000000000000000000000000000000000000000000003435#define IOCTL_RETRIES 336···118 struct packet_command cgc;119 int ntracks, ret;120121- if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr)))0122 return ret;123124 ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;···134 trk1_te.cdte_track = ti->cdti_trk1;135 trk1_te.cdte_format = CDROM_MSF;136137- if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk0_te)))0138 return ret;139- if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te)))0140 return ret;141142 memset(&cgc, 0, sizeof(struct packet_command));···152 cgc.data_direction = DMA_NONE;153 cgc.timeout = IOCTL_TIMEOUT;154 return sr_do_ioctl(cdi->handle, &cgc);000000000000000000000000155}156157/* We do our own retries because we want to know what the specific···329 int i, rc, have_datatracks = 0;330331 /* look for data tracks */332- if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h)))0333 return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO;334335 for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {336 toc_e.cdte_track = i;337 toc_e.cdte_format = CDROM_LBA;338- if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e))339 return CDS_NO_INFO;340 if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) {341 have_datatracks = 1;···362363 return 0;364}365-366-/* primitive to determine whether we need to have GFP_DMA set based on367- * the status of the unchecked_isa_dma flag in the host structure */368-#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)369370int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)371{···426427int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)428{429- Scsi_CD *cd = cdi->handle;430- struct packet_command cgc;431- int result;432- unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));433-434- if (!buffer)435- return -ENOMEM;436-437- memset(&cgc, 0, sizeof(struct packet_command));438- cgc.timeout = IOCTL_TIMEOUT;439-440 switch (cmd) {441 case CDROMREADTOCHDR:442- {443- struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;444-445- cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;446- cgc.cmd[8] = 12; /* LSB of length */447- cgc.buffer = buffer;448- cgc.buflen = 12;449- cgc.quiet = 1;450- cgc.data_direction = DMA_FROM_DEVICE;451-452- result = sr_do_ioctl(cd, &cgc);453-454- tochdr->cdth_trk0 = buffer[2];455- tochdr->cdth_trk1 = buffer[3];456-457- break;458- }459-460 case CDROMREADTOCENTRY:461- {462- struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;463-464- cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;465- cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;466- cgc.cmd[6] = tocentry->cdte_track;467- cgc.cmd[8] = 12; /* LSB of length */468- cgc.buffer = buffer;469- cgc.buflen = 12;470- cgc.data_direction = DMA_FROM_DEVICE;471-472- result = sr_do_ioctl(cd, &cgc);473-474- tocentry->cdte_ctrl = buffer[5] & 0xf;475- tocentry->cdte_adr = buffer[5] >> 4;476- tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;477- if (tocentry->cdte_format == CDROM_MSF) {478- tocentry->cdte_addr.msf.minute = buffer[9];479- tocentry->cdte_addr.msf.second = buffer[10];480- tocentry->cdte_addr.msf.frame = buffer[11];481- } else482- tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)483- + buffer[10]) << 8) + buffer[11];484-485- break;486- }487-488- case CDROMPLAYTRKIND: {489- struct cdrom_ti* ti = (struct cdrom_ti*)arg;490-491- cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;492- cgc.cmd[4] = ti->cdti_trk0;493- cgc.cmd[5] = ti->cdti_ind0;494- cgc.cmd[7] = ti->cdti_trk1;495- cgc.cmd[8] = ti->cdti_ind1;496- cgc.data_direction = DMA_NONE;497-498- result = sr_do_ioctl(cd, &cgc);499- if (result == -EDRIVE_CANT_DO_THIS)500- result = sr_fake_playtrkind(cdi, ti);501-502- break;503- }504-505 default:506- result = -EINVAL;507 }508-509-#if 0510- if (result)511- printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result);512-#endif513-514- kfree(buffer);515- return result;516}517518/* -----------------------------------------------------------------------
···3132module_param(xa_test, int, S_IRUGO | S_IWUSR);3334+/* primitive to determine whether we need to have GFP_DMA set based on35+ * the status of the unchecked_isa_dma flag in the host structure */36+#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)37+38+39+static int sr_read_tochdr(struct cdrom_device_info *cdi,40+ struct cdrom_tochdr *tochdr)41+{42+ struct scsi_cd *cd = cdi->handle;43+ struct packet_command cgc;44+ int result;45+ unsigned char *buffer;46+47+ buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));48+ if (!buffer)49+ return -ENOMEM;50+51+ memset(&cgc, 0, sizeof(struct packet_command));52+ cgc.timeout = IOCTL_TIMEOUT;53+ cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;54+ cgc.cmd[8] = 12; /* LSB of length */55+ cgc.buffer = buffer;56+ cgc.buflen = 12;57+ cgc.quiet = 1;58+ cgc.data_direction = DMA_FROM_DEVICE;59+60+ result = sr_do_ioctl(cd, &cgc);61+62+ tochdr->cdth_trk0 = buffer[2];63+ tochdr->cdth_trk1 = buffer[3];64+65+ kfree(buffer);66+ return result;67+}68+69+static int sr_read_tocentry(struct cdrom_device_info *cdi,70+ struct cdrom_tocentry *tocentry)71+{72+ struct scsi_cd *cd = cdi->handle;73+ struct packet_command cgc;74+ int result;75+ unsigned char *buffer;76+77+ buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));78+ if (!buffer)79+ return -ENOMEM;80+81+ memset(&cgc, 0, sizeof(struct packet_command));82+ cgc.timeout = IOCTL_TIMEOUT;83+ cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;84+ cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;85+ cgc.cmd[6] = tocentry->cdte_track;86+ cgc.cmd[8] = 12; /* LSB of length */87+ cgc.buffer = buffer;88+ cgc.buflen = 12;89+ cgc.data_direction = DMA_FROM_DEVICE;90+91+ result = sr_do_ioctl(cd, &cgc);92+93+ tocentry->cdte_ctrl = buffer[5] & 0xf;94+ tocentry->cdte_adr = buffer[5] >> 4;95+ tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;96+ if (tocentry->cdte_format == CDROM_MSF) {97+ tocentry->cdte_addr.msf.minute = buffer[9];98+ tocentry->cdte_addr.msf.second = buffer[10];99+ tocentry->cdte_addr.msf.frame = buffer[11];100+ } else101+ tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)102+ + buffer[10]) << 8) + buffer[11];103+104+ kfree(buffer);105+ return result;106+}107108#define IOCTL_RETRIES 3109···45 struct packet_command cgc;46 int ntracks, ret;4748+ ret = sr_read_tochdr(cdi, &tochdr);49+ if (ret)50 return ret;5152 ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;···60 trk1_te.cdte_track = ti->cdti_trk1;61 trk1_te.cdte_format = CDROM_MSF;6263+ ret = sr_read_tocentry(cdi, &trk0_te);64+ if (ret)65 return ret;66+ ret = sr_read_tocentry(cdi, &trk1_te);67+ if (ret)68 return ret;6970 memset(&cgc, 0, sizeof(struct packet_command));···76 cgc.data_direction = DMA_NONE;77 cgc.timeout = IOCTL_TIMEOUT;78 return sr_do_ioctl(cdi->handle, &cgc);79+}80+81+static int sr_play_trkind(struct cdrom_device_info *cdi,82+ struct cdrom_ti *ti)83+84+{85+ struct scsi_cd *cd = cdi->handle;86+ struct packet_command cgc;87+ int result;88+89+ memset(&cgc, 0, sizeof(struct packet_command));90+ cgc.timeout = IOCTL_TIMEOUT;91+ cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;92+ cgc.cmd[4] = ti->cdti_trk0;93+ cgc.cmd[5] = ti->cdti_ind0;94+ cgc.cmd[7] = ti->cdti_trk1;95+ cgc.cmd[8] = ti->cdti_ind1;96+ cgc.data_direction = DMA_NONE;97+98+ result = sr_do_ioctl(cd, &cgc);99+ if (result == -EDRIVE_CANT_DO_THIS)100+ result = sr_fake_playtrkind(cdi, ti);101+102+ return result;103}104105/* We do our own retries because we want to know what the specific···229 int i, rc, have_datatracks = 0;230231 /* look for data tracks */232+ rc = sr_read_tochdr(cdi, &toc_h);233+ if (rc)234 return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO;235236 for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {237 toc_e.cdte_track = i;238 toc_e.cdte_format = CDROM_LBA;239+ if (sr_read_tocentry(cdi, &toc_e))240 return CDS_NO_INFO;241 if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) {242 have_datatracks = 1;···261262 return 0;263}0000264265int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)266{···329330int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)331{00000000000332 switch (cmd) {333 case CDROMREADTOCHDR:334+ return sr_read_tochdr(cdi, arg);00000000000000000335 case CDROMREADTOCENTRY:336+ return sr_read_tocentry(cdi, arg);337+ case CDROMPLAYTRKIND:338+ return sr_play_trkind(cdi, arg);00000000000000000000000000000000000000000339 default:340+ return -EINVAL;341 }00000000342}343344/* -----------------------------------------------------------------------
+9-33
drivers/scsi/st.c
···38#include <linux/devfs_fs_kernel.h>39#include <linux/cdev.h>40#include <linux/delay.h>04142#include <asm/uaccess.h>43#include <asm/dma.h>···194195static int st_probe(struct device *);196static int st_remove(struct device *);197-static int st_init_command(struct scsi_cmnd *);198199static void do_create_driverfs_files(void);200static void do_remove_driverfs_files(void);···206 .probe = st_probe,207 .remove = st_remove,208 },209- .init_command = st_init_command,210};211212static int st_compression(struct scsi_tape *, int);···219220#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)221222-static DECLARE_MUTEX(st_ref_sem);223224225#include "osst_detect.h"···236{237 struct scsi_tape *STp = NULL;238239- down(&st_ref_sem);240 write_lock(&st_dev_arr_lock);241242 if (dev < st_dev_max && scsi_tapes != NULL)···258 STp = NULL;259out:260 write_unlock(&st_dev_arr_lock);261- up(&st_ref_sem);262 return STp;263}264···266{267 struct scsi_device *sdev = STp->device;268269- down(&st_ref_sem);270 kref_put(&STp->kref, scsi_tape_release);271 scsi_device_put(sdev);272- up(&st_ref_sem);273}274275struct st_reject_data {···4140 }4141 }41424143- down(&st_ref_sem);4144 kref_put(&tpnt->kref, scsi_tape_release);4145- up(&st_ref_sem);4146 return 0;4147 }4148 }···4155 * scsi_tape_release - Called to free the Scsi_Tape structure4156 * @kref: pointer to embedded kref4157 *4158- * st_ref_sem must be held entering this routine. Because it is4159 * called on last put, you should always use the scsi_tape_get()4160 * scsi_tape_put() helpers which manipulate the semaphore directly4161 * and never do a direct kref_put().···4177 put_disk(disk);4178 kfree(tpnt);4179 return;4180-}4181-4182-static void st_intr(struct scsi_cmnd *SCpnt)4183-{4184- /*4185- * The caller should be checking the request's errors4186- * value.4187- */4188- scsi_io_completion(SCpnt, SCpnt->bufflen, 0);4189-}4190-4191-/*4192- * st_init_command: only called via the scsi_cmd_ioctl (block SG_IO)4193- * interface for REQ_BLOCK_PC commands.4194- */4195-static int st_init_command(struct scsi_cmnd *SCpnt)4196-{4197- if (!(SCpnt->request->flags & REQ_BLOCK_PC))4198- return 0;4199-4200- scsi_setup_blk_pc_cmnd(SCpnt);4201- SCpnt->done = st_intr;4202- return 1;4203}42044205static int __init init_st(void)
···38#include <linux/devfs_fs_kernel.h>39#include <linux/cdev.h>40#include <linux/delay.h>41+#include <linux/mutex.h>4243#include <asm/uaccess.h>44#include <asm/dma.h>···193194static int st_probe(struct device *);195static int st_remove(struct device *);0196197static void do_create_driverfs_files(void);198static void do_remove_driverfs_files(void);···206 .probe = st_probe,207 .remove = st_remove,208 },0209};210211static int st_compression(struct scsi_tape *, int);···220221#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)222223+static DEFINE_MUTEX(st_ref_mutex);224225226#include "osst_detect.h"···237{238 struct scsi_tape *STp = NULL;239240+ mutex_lock(&st_ref_mutex);241 write_lock(&st_dev_arr_lock);242243 if (dev < st_dev_max && scsi_tapes != NULL)···259 STp = NULL;260out:261 write_unlock(&st_dev_arr_lock);262+ mutex_unlock(&st_ref_mutex);263 return STp;264}265···267{268 struct scsi_device *sdev = STp->device;269270+ mutex_lock(&st_ref_mutex);271 kref_put(&STp->kref, scsi_tape_release);272 scsi_device_put(sdev);273+ mutex_unlock(&st_ref_mutex);274}275276struct st_reject_data {···4141 }4142 }41434144+ mutex_lock(&st_ref_mutex);4145 kref_put(&tpnt->kref, scsi_tape_release);4146+ mutex_unlock(&st_ref_mutex);4147 return 0;4148 }4149 }···4156 * scsi_tape_release - Called to free the Scsi_Tape structure4157 * @kref: pointer to embedded kref4158 *4159+ * st_ref_mutex must be held entering this routine. Because it is4160 * called on last put, you should always use the scsi_tape_get()4161 * scsi_tape_put() helpers which manipulate the semaphore directly4162 * and never do a direct kref_put().···4178 put_disk(disk);4179 kfree(tpnt);4180 return;000000000000000000000004181}41824183static int __init init_st(void)
···32extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];3334/*35+ * Special value for scanning to specify scanning or rescanning of all36+ * possible channels, (target) ids, or luns on a given shost.37+ */38+#define SCAN_WILD_CARD ~039+40+/*41 * SCSI opcodes42 */43
···30 struct transport_container device_attrs;3132 /*33- * If set, call target_parent prior to allocating a scsi_target,34- * so we get the appropriate parent for the target. This function35- * is required for transports like FC and iSCSI that do not put the36- * scsi_target under scsi_host.37 */38- struct device *(*target_parent)(struct Scsi_Host *, int, uint);3940 /* The size of the specific transport attribute structure (a41 * space of this size will be left at the end of the
···30 struct transport_container device_attrs;3132 /*33+ * If set, called from sysfs and legacy procfs rescanning code.00034 */35+ int (*user_scan)(struct Scsi_Host *, uint, uint, uint);3637 /* The size of the specific transport attribute structure (a38 * space of this size will be left at the end of the
+4
include/scsi/scsi_transport_fc.h
···303 /* Fixed Attributes */304 u64 node_name;305 u64 port_name;0306 u32 supported_classes;307 u8 supported_fc4s[FC_FC4_LIST_SIZE];308 char symbolic_name[FC_SYMBOLIC_NAME_SIZE];···339 (((struct fc_host_attrs *)(x)->shost_data)->node_name)340#define fc_host_port_name(x) \341 (((struct fc_host_attrs *)(x)->shost_data)->port_name)00342#define fc_host_supported_classes(x) \343 (((struct fc_host_attrs *)(x)->shost_data)->supported_classes)344#define fc_host_supported_fc4s(x) \···429 /* host fixed attributes */430 unsigned long show_host_node_name:1;431 unsigned long show_host_port_name:1;0432 unsigned long show_host_supported_classes:1;433 unsigned long show_host_supported_fc4s:1;434 unsigned long show_host_symbolic_name:1;
···303 /* Fixed Attributes */304 u64 node_name;305 u64 port_name;306+ u64 permanent_port_name;307 u32 supported_classes;308 u8 supported_fc4s[FC_FC4_LIST_SIZE];309 char symbolic_name[FC_SYMBOLIC_NAME_SIZE];···338 (((struct fc_host_attrs *)(x)->shost_data)->node_name)339#define fc_host_port_name(x) \340 (((struct fc_host_attrs *)(x)->shost_data)->port_name)341+#define fc_host_permanent_port_name(x) \342+ (((struct fc_host_attrs *)(x)->shost_data)->permanent_port_name)343#define fc_host_supported_classes(x) \344 (((struct fc_host_attrs *)(x)->shost_data)->supported_classes)345#define fc_host_supported_fc4s(x) \···426 /* host fixed attributes */427 unsigned long show_host_node_name:1;428 unsigned long show_host_port_name:1;429+ unsigned long show_host_permanent_port_name:1;430 unsigned long show_host_supported_classes:1;431 unsigned long show_host_supported_fc4s:1;432 unsigned long show_host_symbolic_name:1;
+67-8
include/scsi/scsi_transport_iscsi.h
···23#ifndef SCSI_TRANSPORT_ISCSI_H24#define SCSI_TRANSPORT_ISCSI_H25026#include <scsi/iscsi_if.h>000002728/**29 * struct iscsi_transport - iSCSI Transport template···54 char *name;55 unsigned int caps;56 struct scsi_host_template *host_template;057 int hostdata_size;000058 int max_lun;59 unsigned int max_conn;60 unsigned int max_cmd_len;61- iscsi_sessionh_t (*create_session) (uint32_t initial_cmdsn,62- struct Scsi_Host *shost);63- void (*destroy_session) (iscsi_sessionh_t session);64- iscsi_connh_t (*create_conn) (iscsi_sessionh_t session, uint32_t cid);065 int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn,66 uint32_t transport_fd, int is_leading);67 int (*start_conn) (iscsi_connh_t conn);68 void (*stop_conn) (iscsi_connh_t conn, int flag);69- void (*destroy_conn) (iscsi_connh_t conn);70 int (*set_param) (iscsi_connh_t conn, enum iscsi_param param,71 uint32_t value);72- int (*get_param) (iscsi_connh_t conn, enum iscsi_param param,73- uint32_t *value);0074 int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr,75 char *data, uint32_t data_size);76 void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats);···87/*88 * transport registration upcalls89 */90-extern int iscsi_register_transport(struct iscsi_transport *tt);91extern int iscsi_unregister_transport(struct iscsi_transport *tt);9293/*···96extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error);97extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr,98 char *data, uint32_t data_size);00000000000000000000000000000000000000000000099100#endif
···23#ifndef SCSI_TRANSPORT_ISCSI_H24#define SCSI_TRANSPORT_ISCSI_H2526+#include <linux/device.h>27#include <scsi/iscsi_if.h>28+29+struct scsi_transport_template;30+struct Scsi_Host;31+struct mempool_zone;32+struct iscsi_cls_conn;3334/**35 * struct iscsi_transport - iSCSI Transport template···48 char *name;49 unsigned int caps;50 struct scsi_host_template *host_template;51+ /* LLD session/scsi_host data size */52 int hostdata_size;53+ /* LLD iscsi_host data size */54+ int ihostdata_size;55+ /* LLD connection data size */56+ int conndata_size;57 int max_lun;58 unsigned int max_conn;59 unsigned int max_cmd_len;60+ struct Scsi_Host *(*create_session) (struct scsi_transport_template *t,61+ uint32_t initial_cmdsn);62+ void (*destroy_session) (struct Scsi_Host *shost);63+ struct iscsi_cls_conn *(*create_conn) (struct Scsi_Host *shost,64+ uint32_t cid);65 int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn,66 uint32_t transport_fd, int is_leading);67 int (*start_conn) (iscsi_connh_t conn);68 void (*stop_conn) (iscsi_connh_t conn, int flag);69+ void (*destroy_conn) (struct iscsi_cls_conn *conn);70 int (*set_param) (iscsi_connh_t conn, enum iscsi_param param,71 uint32_t value);72+ int (*get_conn_param) (void *conndata, enum iscsi_param param,73+ uint32_t *value);74+ int (*get_session_param) (struct Scsi_Host *shost,75+ enum iscsi_param param, uint32_t *value);76 int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr,77 char *data, uint32_t data_size);78 void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats);···73/*74 * transport registration upcalls75 */76+extern struct scsi_transport_template *iscsi_register_transport(struct iscsi_transport *tt);77extern int iscsi_unregister_transport(struct iscsi_transport *tt);7879/*···82extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error);83extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr,84 char *data, uint32_t data_size);85+86+struct iscsi_cls_conn {87+ struct list_head conn_list; /* item in connlist */88+ void *dd_data; /* LLD private data */89+ struct iscsi_transport *transport;90+ iscsi_connh_t connh;91+ int active; /* must be accessed with the connlock */92+ struct device dev; /* sysfs transport/container device */93+ struct mempool_zone *z_error;94+ struct mempool_zone *z_pdu;95+ struct list_head freequeue;96+};97+98+#define iscsi_dev_to_conn(_dev) \99+ container_of(_dev, struct iscsi_cls_conn, dev)100+101+struct iscsi_cls_session {102+ struct list_head list; /* item in session_list */103+ struct iscsi_transport *transport;104+ struct device dev; /* sysfs transport/container device */105+};106+107+#define iscsi_dev_to_session(_dev) \108+ container_of(_dev, struct iscsi_cls_session, dev)109+110+#define iscsi_session_to_shost(_session) \111+ dev_to_shost(_session->dev.parent)112+113+/*114+ * session and connection functions that can be used by HW iSCSI LLDs115+ */116+extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,117+ struct iscsi_transport *t);118+extern int iscsi_destroy_session(struct iscsi_cls_session *session);119+extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,120+ uint32_t cid);121+extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);122+123+/*124+ * session functions used by software iscsi125+ */126+extern struct Scsi_Host *127+iscsi_transport_create_session(struct scsi_transport_template *scsit,128+ struct iscsi_transport *transport);129+extern int iscsi_transport_destroy_session(struct Scsi_Host *shost);130131#endif
+1-1
include/scsi/scsi_transport_spi.h
···54 unsigned int support_qas; /* supports quick arbitration and selection */55 /* Private Fields */56 unsigned int dv_pending:1; /* Internal flag */57- struct semaphore dv_sem; /* semaphore to serialise dv */58};5960enum spi_signal_type {
···54 unsigned int support_qas; /* supports quick arbitration and selection */55 /* Private Fields */56 unsigned int dv_pending:1; /* Internal flag */57+ struct mutex dv_mutex; /* semaphore to serialise dv */58};5960enum spi_signal_type {